]> icculus.org git repositories - taylor/freespace2.git/blob - src/missionui/missiondebrief.cpp
add support for retail FS1 pilot files
[taylor/freespace2.git] / src / missionui / missiondebrief.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/MissionUI/MissionDebrief.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C module for running the debriefing
16  *
17  * $Log$
18  * Revision 1.14  2006/04/26 19:43:25  taylor
19  * this should squash the first second double-play of debriefing voice
20  *
21  * Revision 1.13  2005/08/12 08:52:32  taylor
22  * various GCC4 warning fixes
23  *
24  * Revision 1.12  2005/03/29 02:18:47  taylor
25  * Various 64-bit platform fixes
26  * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
27  * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
28  * Streaming audio support (big thanks to Pierre Willenbrock!!)
29  * Removed dependance on strings.tbl for FS1 since we don't actually need it now
30  *
31  * Revision 1.11  2004/09/20 01:31:44  theoddone33
32  * GCC 3.4 fixes.
33  *
34  * Revision 1.10  2004/07/04 11:39:06  taylor
35  * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
36  *
37  * Revision 1.9  2003/08/03 16:10:29  taylor
38  * cleanup; compile warning fixes
39  *
40  * Revision 1.8  2003/06/03 04:00:40  taylor
41  * Polish language support (Janusz Dziemidowicz)
42  *
43  * Revision 1.7  2003/05/25 02:30:43  taylor
44  * Freespace 1 support
45  *
46  * Revision 1.6  2002/07/13 06:46:48  theoddone33
47  * Warning cleanups
48  *
49  * Revision 1.5  2002/06/09 04:41:23  relnev
50  * added copyright header
51  *
52  * Revision 1.4  2002/06/02 04:26:34  relnev
53  * warning cleanup
54  *
55  * Revision 1.3  2002/05/26 22:06:17  relnev
56  * makefile: disable stand_gui for now.
57  *
58  * rest: staticize some globals
59  *
60  * Revision 1.2  2002/05/07 03:16:46  theoddone33
61  * The Great Newline Fix
62  *
63  * Revision 1.1.1.1  2002/05/03 03:28:10  root
64  * Initial import.
65  *
66  * 
67  * 57    10/29/99 10:40p Jefff
68  * hack to make german medal names display without actually changing them
69  * 
70  * 56    10/13/99 3:26p Jefff
71  * fixed unnumbered XSTRs
72  * 
73  * 55    10/06/99 10:28a Jefff
74  * updates for OEM
75  * 
76  * 54    9/30/99 5:57p Jefff
77  * show upsell at end of campaign in OEM builds
78  * 
79  * 53    9/15/99 3:42a Jefff
80  * badge voice fix
81  * 
82  * 52    9/14/99 4:35a Dave
83  * Argh. Added all kinds of code to handle potential crashes in debriefing
84  * code.
85  * 
86  * 51    9/14/99 3:26a Dave
87  * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
88  * respawn-too-early problem. Made a few crash points safe.
89  * 
90  * 50    9/14/99 12:51a Jefff
91  * 
92  * 49    9/13/99 6:01p Jefff
93  * fixed wrong promotion voice mapping for sm1-08
94  * 
95  * 48    9/13/99 11:15a Jefff
96  * clear out award text bug fixed
97  * 
98  * 47    9/13/99 12:17p Andsager
99  * Fix traitor debrief not playinf for FS2.  Don't append _3 or _1 as in
100  * FS1.
101  * 
102  * 46    9/07/99 9:35p Jefff
103  * fixed bug where award text was not getting cleared properly between
104  * debriefs.
105  * 
106  * 45    9/07/99 6:56p Jefff
107  * a few adjustments to loop detection
108  * 
109  * 44    9/07/99 1:54p Jefff
110  * skip mission cleanup
111  * 
112  * 43    9/06/99 9:45p Jefff
113  * skip mission support
114  * 
115  * 42    9/06/99 6:38p Dave
116  * Improved CD detection code.
117  * 
118  * 41    9/03/99 1:32a Dave
119  * CD checking by act. Added support to play 2 cutscenes in a row
120  * seamlessly. Fixed super low level cfile bug related to files in the
121  * root directory of a CD. Added cheat code to set campaign mission # in
122  * main hall.
123  * 
124  * 40    9/02/99 3:45p Jefff
125  * forgot to remove some debug code.  doh.
126  * 
127  * 39    9/02/99 3:41p Jefff
128  * changed badge voice handling to be similar to promotion voice handling
129  * 
130  * 38    9/01/99 4:41p Jefff
131  * fixed stoopid text color bug
132  * 
133  * 37    8/31/99 11:54a Jefff
134  * minor debrief music tweak
135  * 
136  * 36    8/27/99 9:57a Dave
137  * Enabled standard cheat codes. Allow player to continue in a campaing
138  * after using cheat codes.
139  * 
140  * 35    8/27/99 12:04a Dave
141  * Campaign loop screen.
142  * 
143  * 34    8/26/99 8:49p Jefff
144  * Updated medals screen and about everything that ever touches medals in
145  * one way or another.  Sheesh.
146  * 
147  * 33    8/20/99 4:20p Jefff
148  * hack for choosing the correct promotion voice
149  * 
150  * 32    8/16/99 4:05p Dave
151  * Big honking checkin.
152  * 
153  * 31    8/16/99 9:49a Jefff
154  * mission title length fix in multi
155  * 
156  * 30    8/11/99 5:33p Jefff
157  * added 3rd debrief music track
158  * 
159  * 29    8/10/99 7:28p Jefff
160  * shuffled some text around
161  * 
162  * 28    8/04/99 5:36p Andsager
163  * Show upsell screens at end of demo campaign before returning to main
164  * hall.
165  * 
166  * 27    8/04/99 2:07p Jefff
167  * mission title no longer overwrites popup
168  * 
169  * 26    8/02/99 5:37p Jefff
170  * 
171  * 25    8/02/99 4:52p Jefff
172  * negative feedback sound when recommendations button pressed and
173  * disabled.
174  * 
175  * 24    7/21/99 6:21p Jefff
176  * added hotkeys to the "you cannot accept" popup
177  * 
178  * 23    6/15/99 12:04p Anoop
179  * Added a warning for running out of debrief text lines.
180  * 
181  * 22    6/09/99 2:17p Dave
182  * Fixed up pleasewait bitmap rendering.
183  * 
184  * 21    6/01/99 6:07p Dave
185  * New loading/pause/please wait bar.
186  * 
187  * 20    5/22/99 6:05p Dave
188  * Fixed a few localization # problems.
189  * 
190  * 19    5/22/99 5:35p Dave
191  * Debrief and chatbox screens. Fixed small hi-res HUD bug.
192  * 
193  * 18    3/20/99 3:47p Andsager
194  * Fix crash with no mission loop description.
195  * 
196  * 17    2/23/99 2:29p Dave
197  * First run of oldschool dogfight mode. 
198  * 
199  * 16    2/21/99 6:01p Dave
200  * Fixed standalone WSS packets. 
201  * 
202  * 15    2/11/99 3:08p Dave
203  * PXO refresh button. Very preliminary squad war support.
204  * 
205  * 14    1/30/99 5:08p Dave
206  * More new hi-res stuff.Support for nice D3D textures.
207  * 
208  * 13    1/29/99 2:08a Dave
209  * Fixed beam weapon collisions with players. Reduced size of scoring
210  * struct for multiplayer. Disabled PXO.
211  * 
212  * 12    1/14/99 5:15p Neilk
213  * changed credits, command debrief interfaces to high resolution support
214  * 
215  * 11    1/13/99 2:11p Andsager
216  * change default debriefing string text
217  * 
218  * 10    12/17/98 4:50p Andsager
219  * Added debrief_assemble_optional_mission_popup_text() for single and
220  * multiplayer
221  * 
222  * 9     12/12/98 3:17p Andsager
223  * Clean up mission eval, goal, event and mission scoring.
224  * 
225  * 8     12/10/98 10:19a Andsager
226  * Fix mission loop assert
227  * 
228  * 7     12/10/98 9:59a Andsager
229  * Fix some bugs with mission loops
230  * 
231  * 6     12/09/98 1:56p Andsager
232  * Initial checkin of mission loop
233  * 
234  * 5     11/05/98 4:18p Dave
235  * First run nebula support. Beefed up localization a bit. Removed all
236  * conditional compiles for foreign versions. Modified mission file
237  * format.
238  * 
239  * 4     10/23/98 3:51p Dave
240  * Full support for tstrings.tbl and foreign languages. All that remains
241  * is to make it active in Fred.
242  * 
243  * 3     10/13/98 9:28a Dave
244  * Started neatening up freespace.h. Many variables renamed and
245  * reorganized. Added AlphaColors.[h,cpp]
246  * 
247  * 2     10/07/98 10:53a Dave
248  * Initial checkin.
249  * 
250  * 1     10/07/98 10:49a Dave
251  * 
252  * 178   9/17/98 3:08p Dave
253  * PXO to non-pxo game warning popup. Player icon stuff in create and join
254  * game screens. Upped server count refresh time in PXO to 35 secs (from
255  * 20).
256  * 
257  * 177   7/07/98 1:46p Dave
258  * Fixed nasty debriefing badge/promotion bug. Added extra physics info
259  * for capital ships. 
260  * 
261  * 175   6/09/98 10:31a Hoffoss
262  * Created index numbers for all xstr() references.  Any new xstr() stuff
263  * added from here on out should be added to the end if the list.  The
264  * current list count can be found in FreeSpace.cpp (search for
265  * XSTR_SIZE).
266  * 
267  * 174   6/07/98 3:26p Lawrance
268  * Fix bug with cut-off popup text
269  * 
270  * 173   6/05/98 9:54a Lawrance
271  * OEM changes
272  * 
273  * 172   6/01/98 11:43a John
274  * JAS & MK:  Classified all strings for localization.
275  * 
276  * 171   5/27/98 1:24p Allender
277  * make targeting dots work (as well as other targeting features) properly
278  * in multiplayer.  Don't query for CD when entering debrief in
279  * multiplayer
280  * 
281  * 170   5/26/98 11:10a Lawrance
282  * Fix bug where window controls get disabled when F1 pressed twice
283  * 
284  * 169   5/24/98 12:55a Mike
285  * Prevent SDL_assert() when no debriefing text for a stage.
286  * 
287  * 168   5/23/98 10:38p Lawrance
288  * Avoid doing a cfile refresh when running debug
289  * 
290  * 167   5/23/98 6:49p Lawrance
291  * Fix problems with refreshing the file list when a CD is inserted
292  * 
293  * 166   5/21/98 6:57p Lawrance
294  * Don't prompt for the CD if voice not found
295  * 
296  * 165   5/20/98 2:24a Dave
297  * Fixed server side voice muting. Tweaked multi debrief/endgame
298  * sequencing a bit. Much friendlier for stats tossing/accepting now.
299  * 
300  * 164   5/19/98 8:35p Dave
301  * Revamp PXO channel listing system. Send campaign goals/events to
302  * clients for evaluation. Made lock button pressable on all screens. 
303  * 
304  * 163   5/19/98 11:13a Hoffoss
305  * Fixed bug where wrong wings award was being displayed in debriefing.
306  * 
307  * 162   5/19/98 12:28a Mike
308  * Cheat stuff.
309  * 
310  * 161   5/18/98 8:08p Hoffoss
311  * Moved placement of 'More' text.
312  * 
313  * 160   5/18/98 3:50p Dan
314  * AL: Pick correct traitor debriefing voice file
315  * 
316  * 159   5/17/98 6:32p Dave
317  * Make sure clients/servers aren't kicked out of the debriefing when team
318  * captains leave a game. Fixed chatbox off-by-one error. Fixed image
319  * xfer/pilot info popup stuff.
320  * 
321  * 158   5/16/98 9:14p Allender
322  * fix scoring ckise fir training missions to actually count medals, but
323  * nothing else.  Code used to SDL_assert when wings were granted then taken
324  * away because they were actually never granted in scoring structure
325  * 
326  * 157   5/15/98 5:15p Dave
327  * Fix a standalone resetting bug.Tweaked PXO interface. Display captaincy
328  * status for team vs. team. Put in asserts to check for invalid team vs.
329  * team situations.
330  * 
331  * 156   5/15/98 4:36p Allender
332  * fixed minor bug with wings
333  * 
334  * 155   5/15/98 4:12p Allender
335  * removed redbook code.  Put back in ingame join timer.  Major fixups for
336  * stats in multiplayer.  Pass correct score, medals, etc when leaving
337  * game.  Be sure clients display medals, badges, etc.
338  * 
339  * 154   5/15/98 2:25p Jasen
340  * temporarily disable granting of promotion and badges for clients
341  * 
342  * 153   5/15/98 10:57a Allender
343  * fixed client side debriefings
344  * 
345  * 152   5/15/98 10:36a Dave
346  * Removed 2 bogus bitmap drawing Int3()'s
347  * 
348  * 151   5/14/98 2:44p Hoffoss
349  * Added wings awarding to debrief screen.
350  * 
351  * 150   5/13/98 9:11p Lawrance
352  * Make 'replay mission' popup warn users about the loss of mission stats. 
353  *
354  * $NoKeywords: $
355  */
356
357 #include "missiondebrief.h"
358 #include "missionbriefcommon.h"
359 #include "missionscreencommon.h"
360 #include "missiongoals.h"
361 #include "missionpause.h"
362 #include "freespace.h"
363 #include "gamesequence.h"
364 #include "key.h"
365 #include "2d.h"
366 #include "ui.h"
367 #include "uidefs.h"
368 #include "gamesnd.h"
369 #include "sexp.h"
370 #include "parselo.h"
371 #include "audiostr.h"
372 #include "timer.h"
373 #include "bmpman.h"
374 #include "contexthelp.h"
375 #include "stats.h"
376 #include "player.h"
377 #include "chatbox.h"
378 #include "mouse.h"
379 #include "multi.h"
380 #include "multimsgs.h"
381 #include "multiutil.h"
382 #include "multiteamselect.h"
383 #include "multiui.h"
384 #include "eventmusic.h"
385 #include "font.h"
386 #include "popup.h"
387 #include "medals.h"
388 #include "multi_pinfo.h"
389 #include "contexthelp.h"
390 #include "multi_kick.h"
391 #include "multi_campaign.h"
392 #include "alphacolors.h"
393 #include "localize.h"
394 #include "multi_endgame.h"
395 #include "osapi.h"
396
397 #define MAX_TOTAL_DEBRIEF_LINES 200
398
399 #define TEXT_TYPE_NORMAL                        1
400 #define TEXT_TYPE_RECOMMENDATION        2
401
402 #define DEBRIEF_NUM_STATS_PAGES 4
403 #define DEBRIEF_MISSION_STATS           0
404 #define DEBRIEF_MISSION_KILLS           1
405 #define DEBRIEF_ALLTIME_STATS           2
406 #define DEBRIEF_ALLTIME_KILLS           3
407
408 // 3rd coord is max width in pixels
409 int Debrief_title_coords[GR_NUM_RESOLUTIONS][3] = {
410         { // GR_640
411 #ifdef MAKE_FS1
412                 38, 120, 161
413 #else
414                 18, 118, 174
415 #endif
416         },
417         { // GR_1024
418                 28, 193, 280
419         }
420 };
421
422 int Debrief_text_wnd_coords[GR_NUM_RESOLUTIONS][4] = {
423         {       // GR_640
424 #ifdef MAKE_FS1
425                 38, 156, 342, 260
426 #else
427                 43, 140, 339, 303                       
428 #endif
429         },      
430         {       // GR_1024
431                 69, 224, 535, 485               
432         }
433 };
434
435 int Debrief_text_x2[GR_NUM_RESOLUTIONS] = {
436         276,    // GR_640
437         450     // GR_1024
438 };
439         
440 int Debrief_stage_info_coords[GR_NUM_RESOLUTIONS][2] = {
441         {       // GR_640
442 #ifdef MAKE_FS1
443                 379, 156
444 #else
445                 379, 137                
446 #endif
447         },      
448         {       // GR_1024
449                 578, 224
450         }
451 };
452
453 int Debrief_more_coords[GR_NUM_RESOLUTIONS][2] = {
454         {       // GR_640
455 #ifdef MAKE_FS1
456                 323, 418
457 #else
458                 323, 453        
459 #endif
460         },
461         {       // GR_1024
462                 323, 453        
463         }
464 };
465
466 #define MULTI_LIST_TEAM_OFFSET                                  16              
467
468 int Debrief_multi_list_team_max_display[GR_NUM_RESOLUTIONS] = {
469         9,      // GR_640
470         12      // GR_1024
471 };
472
473 int Debrief_list_coords[GR_NUM_RESOLUTIONS][4] = {
474         {       // GR_640
475                 416, 280, 195, 101
476         },
477         {       // GR_1024
478                 666, 448, 312, 162
479         }
480 };
481
482 int Debrief_award_wnd_coords[GR_NUM_RESOLUTIONS][2] = {
483         {       // GR_640
484 #ifdef MAKE_FS1
485                 391, 134
486 #else
487                 411, 126
488 #endif
489         },
490         {       // GR_1024
491                 658, 203        
492         }
493 };
494
495 int Debrief_award_coords[GR_NUM_RESOLUTIONS][2] = {
496         {       // GR_640
497 #ifdef MAKE_FS1
498                 448, 145
499 #else
500                 416, 140
501 #endif
502         },
503         {       // GR_1024
504                 666, 224        
505         }
506 };
507
508 #ifdef MAKE_FS1
509 int Debrief_rank_coords[2] = {
510         448, 168
511 };
512
513 int Debrief_badge_coords[2] = {
514         405, 166
515 };
516 #endif
517
518 #ifndef MAKE_FS1
519 // 0=x, 1=y, 2=width of the field
520 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][3] = {
521         {       // GR_640
522                 423, 247, 189
523         },
524         {       // GR_1024
525                 666, 333, 67
526         }
527 };
528
529 // 0=x, 1=y, 2=height of the field
530 int Debrief_award_text_coords[GR_NUM_RESOLUTIONS][3] = {
531         {       // GR_640
532                 416, 210, 42
533         },
534         {       // GR_1024
535                 666, 333, 67
536         }
537 };
538 #else
539 // the medal text in FS1 is a bitmap
540 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][2] = {
541         {
542                 402, 211
543         },
544         {
545                 402, 211
546         }
547 };
548
549 int Debrief_rank_text_coords[GR_NUM_RESOLUTIONS][2] = {
550         {
551                 409, 231
552         },
553         {
554                 409, 231
555         }
556 };
557
558 int Debrief_badge_text_coords[GR_NUM_RESOLUTIONS][2] = {
559         {
560                 401, 243
561         },
562         {
563                 401, 243
564         }
565 };
566 #endif
567
568 // 0 = with medal
569 // 1 = without medal (text will use medal space)
570 #define DB_WITH_MEDAL           0
571 #define DB_WITHOUT_MEDAL        1
572 int Debrief_award_text_width[GR_NUM_RESOLUTIONS][2] = {
573         {       // GR_640
574                 123, 203
575         },
576         {       // GR_1024
577                 196, 312        
578         }
579 };
580
581 const char *Debrief_single_name[GR_NUM_RESOLUTIONS] = {
582         "DebriefSingle",                // GR_640
583         "2_DebriefSingle"               // GR_1024
584 };
585 const char *Debrief_multi_name[GR_NUM_RESOLUTIONS] = {
586         "DebriefMulti",         // GR_640
587         "2_DebriefMulti"                // GR_1024
588 };
589 const char *Debrief_mask_name[GR_NUM_RESOLUTIONS] = {
590         "Debrief-m",                    // GR_640
591         "2_Debrief-m"                   // GR_1024
592 };
593
594 #define NUM_BUTTONS     18
595 #define NUM_TABS                2
596
597 #define DEBRIEF_TAB                             0
598 #define STATS_TAB                                       1
599 #define TEXT_SCROLL_UP                  2
600 #define TEXT_SCROLL_DOWN                3
601 #define REPLAY_MISSION                  4
602 #define RECOMMENDATIONS                 5
603 #define FIRST_STAGE                             6
604 #define PREV_STAGE                              7
605 #define NEXT_STAGE                              8
606 #define LAST_STAGE                              9
607 #define MULTI_PINFO_POPUP               10
608 #define MULTI_KICK                              11
609 #define MEDALS_BUTTON                   12
610 #define PLAYER_SCROLL_UP                13
611 #define PLAYER_SCROLL_DOWN              14
612 #define HELP_BUTTON                             15
613 #define OPTIONS_BUTTON                  16
614 #define ACCEPT_BUTTON                   17
615
616 #define REPEAT  1
617
618 //XSTR:OFF
619 const char* Debrief_loading_bitmap_fname[GR_NUM_RESOLUTIONS] = {
620         "PleaseWait",           // GR_640
621         "2_PleaseWait"          // GR_1024
622 };
623
624 //XSTR:ON
625
626 typedef struct {
627         char    text[NAME_LENGTH+1];    // name of ship type with a colon
628         int     num;                                            // how many ships of this type player has killed
629 } debrief_stats_kill_info;
630
631 typedef struct {
632         int net_player_index;   // index into Net_players[] array
633         int rank_bitmap;                        // bitmap id for rank
634         char callsign[CALLSIGN_LEN];
635 } debrief_multi_list_info;
636
637 static ui_button_info Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
638         { // GR_640
639 #ifdef MAKE_FS1
640                 ui_button_info("DB_00",         0,              2,              -1,     -1,     0),                     // debriefing
641                 ui_button_info("DB_01",         0,              20,             -1,     -1,     1),                     // statistics
642                 ui_button_info("DB_02",         0,              195,    -1,     -1,     2),                     // scroll stats up
643                 ui_button_info("DB_03",         0,              232,    -1,     -1,     3),                     // scroll stats down
644                 ui_button_info("DB_04",         24,             424,    -1,     -1,     4),                     // replay mission
645                 ui_button_info("DB_05",         30,             451,    -1,     -1,     5),                     // recommendations
646                 ui_button_info("DB_06",         211,    445,    -1,     -1,     6),                     // first page
647                 ui_button_info("DB_07",         234,    445,    -1,     -1,     7),                     // prev page
648                 ui_button_info("DB_08",         259,    445,    -1,     -1,     8),                     // next page
649                 ui_button_info("DB_09",         283,    445,    -1,     -1,     9),                     // last page
650                 ui_button_info("DB_21",         441,    384,    -1,     -1,     21),            // pilot info
651                 ui_button_info("DB_25",         511,    384,    -1,     -1,     25),            // kick
652                 ui_button_info("DB_15",         604,    224,    -1,     -1,     15),            // medals
653                 ui_button_info("DB_16",         615,    329,    -1,     -1,     16),            // scroll pilots up
654                 ui_button_info("DB_17",         615,    371,    -1,     -1,     17),            // scroll pilots down
655                 ui_button_info("DB_10",         469,    428,    -1,     -1,     10),            // help
656                 ui_button_info("DB_11",         447,    452,    -1,     -1,     11),            // options
657                 ui_button_info("DB_12",         562,    410,    -1,     -1,     12),            // accept
658 #else
659                 ui_button_info("DB_00",         6,              1,              37,     7,              0),             // debriefing
660                 ui_button_info("DB_01",         6,              21,     37,     23,     1),             // statistics
661                 ui_button_info("DB_02",         1,              195,    -1,     -1,     2),             // scroll stats up
662                 ui_button_info("DB_03",         1,              236,    -1,     -1,     3),             // scroll stats down
663                 ui_button_info("DB_04",         1,              428,    49,     447,    4),             // replay mission
664                 ui_button_info("DB_05",         17,     459,    49,     464,    5),             // recommendations
665                 ui_button_info("DB_06",         323,    454,    -1,     -1,     6),             // first page
666                 ui_button_info("DB_07",         348,    454,    -1,     -1,     7),             // prev page
667                 ui_button_info("DB_08",         372,    454,    -1,     -1,     8),             // next page
668                 ui_button_info("DB_09",         396,    454,    -1,     -1,     9),             // last page
669                 ui_button_info("DB_10",         441,    384,    433,    413,    10),            // pilot info
670                 ui_button_info("DB_11",         511,    384,    510,    413,    11),            // kick
671                 ui_button_info("DB_12",         613,    226,    -1,     -1,     12),            // medals
672                 ui_button_info("DB_13",         615,    329,    -1,     -1,     13),            // scroll pilots up
673                 ui_button_info("DB_14",         615,    371,    -1,     -1,     14),            // scroll pilots down
674                 ui_button_info("DB_15",         538,    431,    500,    440,    15),            // help
675                 ui_button_info("DB_16",         538,    455,    479,    464,    16),            // options
676                 ui_button_info("DB_17",         573,    432,    572,    413,    17),            // accept
677 #endif
678         },
679         { // GR_1024
680                 ui_button_info("2_DB_00",               10,     1,              59,     12,     0),             // debriefing
681                 ui_button_info("2_DB_01",               10,     33,     59,     37,     1),             // statistics
682                 ui_button_info("2_DB_02",               1,              312,    -1,     -1,     2),             // scroll stats up
683                 ui_button_info("2_DB_03",               1,              378,    -1,     -1,     3),             // scroll stats down
684                 ui_button_info("2_DB_04",               1,              685,    79,     715,    4),             // replay mission
685                 ui_button_info("2_DB_05",               28,     735,    79,     743,    5),             // recommendations
686                 ui_button_info("2_DB_06",               517,    726,    -1,     -1,     6),             // first page
687                 ui_button_info("2_DB_07",               556,    726,    -1,     -1,     7),             // prev page
688                 ui_button_info("2_DB_08",               595,    726,    -1,     -1,     8),             // next page
689                 ui_button_info("2_DB_09",               633,    726,    -1,     -1,     9),             // last page
690                 ui_button_info("2_DB_10",               706,    615,    700,    661,    10),            // pilot info
691                 ui_button_info("2_DB_11",               817,    615,    816,    661,    11),            // kick
692                 ui_button_info("2_DB_12",               981,    362,    -1,     -1,     12),            // medals
693                 ui_button_info("2_DB_13",               984,    526,    -1,     -1,     13),            // scroll pilots up
694                 ui_button_info("2_DB_14",               984,    594,    -1,     -1,     14),            // scroll pilots down
695                 ui_button_info("2_DB_15",               861,    689,    801,    705,    15),            // help
696                 ui_button_info("2_DB_16",               861,    728,    777,    744,    16),            // options
697                 ui_button_info("2_DB_17",               917,    692,    917,    692,    17),            // accept
698         }
699 };
700
701 // text
702 #ifndef MAKE_FS1
703 #define NUM_DEBRIEF_TEXT                        10
704 #define MP_TEXT_INDEX_1                                 4
705 #define MP_TEXT_INDEX_2                                 5
706 #define MP_TEXT_INDEX_3                                 6
707 UI_XSTR Debrief_strings[GR_NUM_RESOLUTIONS][NUM_DEBRIEF_TEXT] = {
708         { // GR_640
709                 { "Debriefing",         804,            37,     7,              UI_XSTR_COLOR_GREEN,    -1,     &Buttons[0][DEBRIEF_TAB].button },
710                 { "Statistics",         1333,           37,     26,     UI_XSTR_COLOR_GREEN,    -1,     &Buttons[0][STATS_TAB].button },
711                 { "Replay Mission",     444,            49,     447,    UI_XSTR_COLOR_PINK,     -1,     &Buttons[0][REPLAY_MISSION].button },
712                 { "Recommendations",    1334,           49,     464,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[0][RECOMMENDATIONS].button },
713                 { "Pilot",                              1310,           433,    413,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[0][MULTI_PINFO_POPUP].button },
714                 { "Info",                               1311,           433,    423,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[0][MULTI_PINFO_POPUP].button },
715                 { "Kick",                               1266,           510,    413,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[0][MULTI_KICK].button },
716                 { "Help",                               928,            500,    440,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[0][HELP_BUTTON].button },
717                 { "Options",                    1036,           479,    464,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[0][OPTIONS_BUTTON].button },
718                 { "Accept",                             1035,           572,    413,    UI_XSTR_COLOR_PINK,     -1,     &Buttons[0][ACCEPT_BUTTON].button },
719         },
720         { // GR_1024
721                 { "Debriefing",         804,            59,     12,     UI_XSTR_COLOR_GREEN,    -1,     &Buttons[1][DEBRIEF_TAB].button },
722                 { "Statistics",         1333,           59,     47,     UI_XSTR_COLOR_GREEN,    -1,     &Buttons[1][STATS_TAB].button },
723                 { "Replay Mission",     444,            79,     715,    UI_XSTR_COLOR_PINK,     -1,     &Buttons[1][REPLAY_MISSION].button },
724                 { "Recommendations",    1334,           79,     743,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[1][RECOMMENDATIONS].button },
725                 { "Pilot",                              1310,           700,    661,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[1][MULTI_PINFO_POPUP].button },
726                 { "Info",                               1311,           700,    679,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[1][MULTI_PINFO_POPUP].button },
727                 { "Kick",                               1266,           816,    661,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[1][MULTI_KICK].button },
728                 { "Help",                               928,            801,    705,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[1][HELP_BUTTON].button },
729                 { "Options",                    1036,           780,    744,    UI_XSTR_COLOR_GREEN,    -1,     &Buttons[1][OPTIONS_BUTTON].button },
730                 { "Accept",                             1035,           917,    672,    UI_XSTR_COLOR_PINK,     -1,     &Buttons[1][ACCEPT_BUTTON].button },
731         }
732 };
733 #endif
734
735
736 char Debrief_current_callsign[CALLSIGN_LEN+10];
737 player *Debrief_player;
738
739 static UI_WINDOW Debrief_ui_window;
740 static UI_BUTTON List_region;
741 static int Background_bitmap;                                   // bitmap for the background of the debriefing
742 static int Award_bg_bitmap;
743 static int Debrief_multi_loading_bitmap;
744 static int Rank_bitmap;
745 static int Medal_bitmap;
746 static int Badge_bitmap;
747 static int Wings_bitmap;
748 static int Crest_bitmap;
749 #ifdef MAKE_FS1
750 static int Rank_text_bitmap;
751 static int Medal_text_bitmap;
752 static int Badge_text_bitmap;
753 #endif
754 static int Promoted;
755 static int Debrief_accepted;
756 static int Turned_traitor;
757 static int Must_replay_mission;
758
759 static int Current_mode;
760 static int New_mode;
761 static int Recommend_active;
762 static int Award_active;
763 static int Text_offset;
764 static int Num_text_lines = 0;
765 static int Num_debrief_lines = 0;
766 static int Text_type[MAX_TOTAL_DEBRIEF_LINES];
767 static char *Text[MAX_TOTAL_DEBRIEF_LINES];
768
769 static int Debrief_inited = 0;
770 static int New_stage;
771 static int Current_stage;
772 static int Num_stages = 0;
773 static int Num_debrief_stages = 0;
774 static int Stage_voice = -1;
775
776 static int Multi_list_size;
777 static int Multi_list_offset;
778
779 int Debrief_multi_stages_loaded = 0;
780 int Debrief_multi_voice_loaded = 0;
781
782 // static int Debrief_voice_ask_for_cd;
783
784 // voice id's for debriefing text
785 static int Debrief_voices[MAX_DEBRIEF_STAGES];
786
787 #define DEBRIEF_VOICE_DELAY 400                         // time to delay voice playback when a new stage starts
788 static int Debrief_cue_voice;                                   // timestamp to cue the playback of the voice
789 static int Debrief_first_voice_flag = 1;        // used to delay the first voice playback extra long
790
791 // pointer used for getting to debriefing information
792 debriefing      Traitor_debriefing;                             // used when player is a traitor
793
794 // pointers to the active stages for this debriefing
795 static debrief_stage *Debrief_stages[MAX_DEBRIEF_STAGES];
796 static debrief_stage Promotion_stage, Badge_stage;
797 static debrief_stats_kill_info Debrief_stats_kills[MAX_SHIP_TYPES];
798 static debrief_multi_list_info Multi_list[MAX_PLAYERS];
799 int Multi_list_select;
800
801 // flag indicating if we should display info for the given player (in multiplayer)
802 int Debrief_should_show_popup = 1;
803
804 // already shown skip mission popup?
805 static int Debrief_skip_popup_already_shown = 0;
806
807 void debrief_text_init();
808 void debrief_accept(int ok_to_post_start_game_event = 1);
809 void debrief_kick_selected_player();
810
811
812 // promotion voice selection stuff
813 #define NUM_VOLITION_CAMPAIGNS  1
814 typedef struct {
815         char  campaign_name[32];
816         int     num_missions;
817 } v_campaign;
818
819 v_campaign Volition_campaigns[NUM_VOLITION_CAMPAIGNS] = {
820         {
821                 BUILTIN_CAMPAIGN,               // the only campaign for now, but this leaves room for a mission pack
822                 35                                              // make sure this is equal to the  number of missions you gave in the corresponding Debrief_promotion_voice_mapping
823         }
824 };
825
826 // data for which voice goes w/ which mission
827 typedef struct voice_map {
828         char  mission_file[32];
829         int     persona_index;
830 } voice_map;
831
832 voice_map Debrief_promotion_voice_mapping[NUM_VOLITION_CAMPAIGNS][MAX_CAMPAIGN_MISSIONS] = {
833         {               // FreeSpace2 campaign 
834                 { "SM1-01.fs2",                 1 },
835                 { "SM1-02.fs2",                 1 },
836                 { "SM1-03.fs2",                 1 },
837                 { "SM1-04.fs2",                 2 },
838                 { "SM1-05.fs2",                 2 },
839                 { "SM1-06.fs2",                 2 },
840                 { "SM1-07.fs2",                 2 },
841                 { "SM1-08.fs2",                 3 },
842                 { "SM1-09.fs2",                 3 },
843                 { "SM1-10.fs2",                 3 },
844
845                 { "SM2-01.fs2",                 6 },
846                 { "SM2-02.fs2",                 6 },
847                 { "SM2-03.fs2",                 6 },
848                 { "SM2-04.fs2",                 7 },
849                 { "SM2-05.fs2",                 7 },
850                 { "SM2-06.fs2",                 7 },
851                 { "SM2-07.fs2",                 8 },
852                 { "SM2-08.fs2",                 8 },
853                 { "SM2-09.fs2",                 8 },
854                 { "SM2-10.fs2",                 8 },
855
856                 { "SM3-01.fs2",                 8 },
857                 { "SM3-02.fs2",                 8 },
858                 { "SM3-03.fs2",                 8 },
859                 { "SM3-04.fs2",                 8 },
860                 { "SM3-05.fs2",                 8 },
861                 { "SM3-06.fs2",                 9 },
862                 { "SM3-07.fs2",                 9 },
863                 { "SM3-08.fs2",                 9 },
864                 { "SM3-09.fs2",                 9 },
865                 { "SM3-10.fs2",                 9 },                    // no debriefing for 3-10
866                 
867                 { "loop1-1.fs2",                        4 },
868                 { "loop1-2.fs2",                        4 },
869                 { "loop1-3.fs2",                        5 },
870                 { "loop2-1.fs2",                        4 },
871                 { "loop2-2.fs2",                        4 }
872         }
873 };
874
875 #define DB_AWARD_WINGS          0
876 #define DB_AWARD_MEDAL          1
877 #ifdef MAKE_FS1
878 #define DB_AWARD_RANK           2
879 #define DB_AWARD_BADGE          3
880 #define DB_AWARD_BG                     4
881 static const char* Debrief_award_filename[GR_NUM_RESOLUTIONS][5] = {
882         {
883                 "DebriefWings",
884                 "DebriefMedal",
885                 "DebriefRank",
886                 "DebriefBadge",
887                 "DebriefAward"
888         },
889         {
890                 "2_DebriefWings",
891                 "2_DebriefMedal",
892                 "2_DebriefRank",
893                 "2_DebriefBadge",
894                 "2_DebriefAward"
895         }
896 };
897 #else
898 #define DB_AWARD_SOC                    2
899 #define DB_AWARD_RANK           3
900 #define DB_AWARD_BADGE          4
901 #define DB_AWARD_BG                     5
902 static const char* Debrief_award_filename[GR_NUM_RESOLUTIONS][6] = {
903         {
904                 "DebriefWings",
905                 "DebriefMedal",
906                 "DebriefCrest",
907                 "DebriefRank",
908                 "DebriefBadge",
909                 "DebriefAward"
910         },
911         {
912                 "2_DebriefWings",
913                 "2_DebriefMedal",
914                 "2_DebriefCrest",
915                 "2_DebriefRank",
916                 "2_DebriefBadge",
917                 "2_DebriefAward"
918         }
919 };
920 #endif
921
922 #define AWARD_TEXT_MAX_LINES                            5
923 #define AWARD_TEXT_MAX_LINE_LENGTH              128
924 char Debrief_award_text[AWARD_TEXT_MAX_LINES][AWARD_TEXT_MAX_LINE_LENGTH];
925 int Debrief_award_text_num_lines = 0;
926
927
928
929 // prototypes, you know you love 'em
930 void debrief_add_award_text(char *str);
931 void debrief_award_text_clear();
932
933
934
935 // functions
936 const char *debrief_tooltip_handler(const char *str)
937 {
938         if (!SDL_strcasecmp(str, NOX("@.Medal"))) {
939                 if (Award_active){
940                         return XSTR( "Medal", 435);
941                 }
942
943         } else if (!SDL_strcasecmp(str, NOX("@.Rank"))) {
944                 if (Award_active){
945                         return XSTR( "Rank", 436);
946                 }
947
948         } else if (!SDL_strcasecmp(str, NOX("@.Badge"))) {
949                 if (Award_active){
950                         return XSTR( "Badge", 437);
951                 }
952
953         } else if (!SDL_strcasecmp(str, NOX("@Medal"))) {
954                 if (Medal_bitmap >= 0){
955                         return Medals[Player->stats.m_medal_earned].name;
956                 }
957
958         } else if (!SDL_strcasecmp(str, NOX("@Rank"))) {
959                 if (Rank_bitmap >= 0){
960                         return Ranks[Promoted].name;
961                 }
962
963         } else if (!SDL_strcasecmp(str, NOX("@Badge"))) {
964                 if (Badge_bitmap >= 0){
965                         return Medals[Badge_index[Player->stats.m_badge_earned]].name;
966                 }
967         }
968
969         return NULL;
970 }
971
972 // initialize the array of handles to the different voice streams
973 void debrief_voice_init()
974 {
975         int i;
976
977         for (i=0; i<MAX_DEBRIEF_STAGES; i++) {
978                 Debrief_voices[i] = -1;
979         }
980 }
981
982 void debrief_load_voice_file(int voice_num, char *name)
983 {
984         int load_attempts = 0;
985         while(1) {
986
987                 if ( load_attempts++ > 5 ) {
988                         break;
989                 }
990
991                 Debrief_voices[voice_num] = audiostream_open( name, ASF_VOICE );
992                 if ( Debrief_voices[voice_num] >= 0 ) {
993                         break;
994                 }
995
996                 // Don't bother to ask for the CD in multiplayer
997                 if ( Game_mode & GM_MULTIPLAYER ) {
998                         break;
999                 }
1000
1001                 // couldn't load voice, ask user to insert CD (if necessary)
1002
1003                 // if ( Debrief_voice_ask_for_cd ) {
1004                         // if ( game_do_cd_check() == 0 ) {
1005                                 // Debrief_voice_ask_for_cd = 0;
1006                                 // break;
1007                         // }
1008                 // }
1009         }
1010 }
1011
1012 // open and pre-load the stream buffers for the different voice streams
1013 void debrief_voice_load_all()
1014 {
1015         int i;
1016
1017         // Debrief_voice_ask_for_cd = 1;
1018
1019         for ( i=0; i<Num_debrief_stages; i++ ) {
1020                 if ( strlen(Debrief_stages[i]->voice) <= 0 ) {
1021                         continue;
1022                 }
1023                 if ( SDL_strncasecmp(Debrief_stages[i]->voice, NOX("none"), 4) ) {
1024                         debrief_load_voice_file(i, Debrief_stages[i]->voice);
1025 //                      Debrief_voices[i] = audiostream_open(Debrief_stages[i]->voice, ASF_VOICE);
1026                 }
1027         }
1028 }
1029
1030 // close all the briefing voice streams
1031 void debrief_voice_unload_all()
1032 {
1033         int i;
1034
1035         for ( i=0; i<MAX_DEBRIEF_STAGES; i++ ) {
1036                 if ( Debrief_voices[i] != -1 ) {
1037                         audiostream_close_file(Debrief_voices[i], 0);
1038                         Debrief_voices[i] = -1;
1039                 }
1040         }
1041 }
1042
1043 // start playback of the voice for a particular briefing stage
1044 void debrief_voice_play()
1045 {
1046         if (!Briefing_voice_enabled || (Current_mode != DEBRIEF_TAB)){
1047                 return;
1048         }
1049
1050         // no more stages?  We are done then.
1051         if (Stage_voice >= Num_debrief_stages){
1052                 return;
1053         }
1054
1055         // if in delayed start, see if delay has elapsed and start voice if so
1056         if (Debrief_cue_voice) {
1057                 if (!timestamp_elapsed(Debrief_cue_voice)){
1058                         return;
1059                 }
1060
1061                 Stage_voice++;  // move up to next voice
1062                 if ((Stage_voice < Num_debrief_stages) && (Debrief_voices[Stage_voice] >= 0)) {
1063                         audiostream_play(Debrief_voices[Stage_voice], Master_voice_volume, 0);
1064                         Debrief_cue_voice = 0;  // indicate no longer in delayed start checking
1065                 }
1066
1067                 return;
1068         }
1069
1070         // see if voice is still playing.  If so, do nothing yet.
1071         if ((Stage_voice >= 0) && audiostream_is_playing(Debrief_voices[Stage_voice])){
1072                 return;
1073         }
1074
1075         // set voice to play in a little while from now.
1076         Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY);
1077 }
1078
1079 // stop playback of the voice for a particular briefing stage
1080 void debrief_voice_stop()
1081 {
1082         if ((Stage_voice < 0) || (Stage_voice > Num_debrief_stages) || (Debrief_voices[Stage_voice] < 0))
1083                 return;
1084
1085         audiostream_stop(Debrief_voices[Stage_voice]);  // stream is automatically rewound
1086         Stage_voice = -1;
1087 }
1088
1089 // function to deal with inserting possible promition and badge stages into the debriefing
1090 // on the clients
1091 void debrief_multi_fixup_stages()
1092 {
1093         int i;
1094
1095         // possibly insert the badge stage first, them the promotion stage since they are
1096         // inserted at the front of the debrief stages.
1097         if ( Badge_bitmap >= 0 ) {
1098                 // move all stages forward one.  Don't 
1099                 for ( i = Num_debrief_stages; i > 0; i-- ) {
1100                         Debrief_stages[i] = Debrief_stages[i-1];
1101                 }
1102                 Debrief_stages[0] = &Badge_stage;
1103                 Num_debrief_stages++;
1104         }
1105
1106         if ( Promoted >= 0) {
1107                 // move all stages forward one
1108                 for ( i = Num_debrief_stages; i > 0; i-- ) {
1109                         Debrief_stages[i] = Debrief_stages[i-1];
1110                 }
1111                 Debrief_stages[0] = &Promotion_stage;
1112                 Num_debrief_stages++;
1113         }
1114 }
1115
1116
1117 // function called from multiplayer clients to set up the debriefing information for them
1118 // (sent from the server).  
1119 void debrief_set_multi_clients( int stage_count, int active_stages[] )
1120 {
1121         int i;
1122
1123         // set up the right briefing for this guy
1124         if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
1125                 Debriefing = &Debriefings[Net_player->p_info.team];
1126         } else {
1127                 Debriefing = &Debriefings[0];                   
1128         }
1129
1130         // see if this client was promoted -- if so, then add the first stage.
1131         Num_debrief_stages = 0;
1132
1133         // set the pointers to the debriefings for this client
1134         for (i = 0; i < stage_count; i++) {
1135                 Debrief_stages[Num_debrief_stages++] = &Debriefing->stages[active_stages[i]];
1136         }
1137
1138         Debrief_multi_stages_loaded = 1;
1139 }
1140
1141 // evaluate all stages for all teams.  Server of a multiplayer game will have to send that
1142 // information to all clients after leaving this screen.
1143 void debrief_multi_server_stuff()
1144 {
1145         debriefing *debriefp;
1146
1147         int stage_active[MAX_TEAMS][MAX_DEBRIEF_STAGES], *stages[MAX_TEAMS];
1148         int i, j, num_stages, stage_count[MAX_TEAMS];
1149
1150         memset( stage_active, 0, sizeof(stage_active) );
1151
1152         for (i=0; i<Num_teams; i++) {
1153                 debriefp = &Debriefings[i];
1154                 num_stages = 0;
1155                 stages[i] = stage_active[i];
1156                 for (j=0; j<debriefp->num_stages; j++) {
1157                         if ( eval_sexp(debriefp->stages[j].formula) ) {
1158                                 stage_active[i][num_stages] = j;
1159                                 num_stages++;
1160                         }
1161                 }
1162
1163                 stage_count[i] = num_stages;
1164         }
1165
1166         // if we're in campaign mode, evaluate campaign stuff
1167         if (Netgame.campaign_mode == MP_CAMPAIGN) {
1168                 multi_campaign_eval_debrief();
1169         }
1170
1171         // send the information to all clients.
1172         send_debrief_info( stage_count, stages );
1173 }
1174
1175
1176 // --------------------------------------------------------------------------------------
1177 //      debrief_set_stages_and_multi_stuff()
1178 //
1179 // Set up the active stages for this debriefing
1180 //
1181 // returns:             number of active debriefing stages
1182 //
1183 int debrief_set_stages_and_multi_stuff()
1184 {
1185         int i;
1186         debriefing      *debriefp;
1187
1188         if ( MULTIPLAYER_CLIENT ) {
1189                 return 0;
1190         }
1191
1192         Num_debrief_stages = 0;
1193
1194         if ( Game_mode & GM_MULTIPLAYER ) {
1195                 debrief_multi_server_stuff();
1196         }
1197
1198         // check to see if player is a traitor (looking at his team).  If so, use the special
1199         // traitor debriefing.  Only done in single player
1200         debriefp = Debriefing;
1201         if ( !(Game_mode & GM_MULTIPLAYER) ) {
1202                 if (Player_ship->team == TEAM_TRAITOR)
1203                         debriefp = &Traitor_debriefing;
1204         }
1205
1206         Num_debrief_stages = 0;
1207         if (Promoted >= 0) {
1208                 Debrief_stages[Num_debrief_stages++] = &Promotion_stage;
1209         }
1210
1211         if (Badge_bitmap >= 0) {
1212                 Debrief_stages[Num_debrief_stages++] = &Badge_stage;
1213         }
1214
1215         for (i=0; i<debriefp->num_stages; i++) {
1216                 if (eval_sexp(debriefp->stages[i].formula) == 1) {
1217                         Debrief_stages[Num_debrief_stages++] = &debriefp->stages[i];
1218                 }
1219         }
1220
1221         return Num_debrief_stages;
1222 }
1223
1224 // init the buttons that are specific to the debriefing screen
1225 void debrief_buttons_init()
1226 {
1227         ui_button_info *b;
1228         int i;
1229
1230         for ( i=0; i<NUM_BUTTONS; i++ ) {
1231                 b = &Buttons[gr_screen.res][i];
1232                 b->button.create( &Debrief_ui_window, "", b->x, b->y, 60, 30, 0 /*b->flags & REPEAT*/, 1 );
1233                 // set up callback for when a mouse first goes over a button
1234                 b->button.set_highlight_action( common_play_highlight_sound );
1235                 b->button.set_bmaps(b->filename);
1236                 b->button.link_hotspot(b->hotspot);
1237         }
1238
1239 #ifndef MAKE_FS1
1240         // add all xstrs
1241         for(i=0; i<NUM_DEBRIEF_TEXT; i++){
1242                 // multiplayer specific text
1243                 if((i == MP_TEXT_INDEX_1) || (i == MP_TEXT_INDEX_2) || (i == MP_TEXT_INDEX_3)){
1244                         // only add if in multiplayer mode
1245                         if(Game_mode & GM_MULTIPLAYER){
1246                                 Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
1247                         }
1248                 } 
1249                 // all other text
1250                 else {
1251                         Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
1252                 }
1253         }
1254 #endif
1255         
1256         // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1257         Buttons[gr_screen.res][NEXT_STAGE].button.set_hotkey(SDLK_RIGHT);
1258         Buttons[gr_screen.res][PREV_STAGE].button.set_hotkey(SDLK_LEFT);
1259         Buttons[gr_screen.res][LAST_STAGE].button.set_hotkey(KEY_SHIFTED | SDLK_RIGHT);
1260         Buttons[gr_screen.res][FIRST_STAGE].button.set_hotkey(KEY_SHIFTED | SDLK_LEFT);
1261         Buttons[gr_screen.res][TEXT_SCROLL_UP].button.set_hotkey(SDLK_UP);
1262         Buttons[gr_screen.res][TEXT_SCROLL_DOWN].button.set_hotkey(SDLK_DOWN);
1263         Buttons[gr_screen.res][ACCEPT_BUTTON].button.set_hotkey(KEY_CTRLED+SDLK_RETURN);
1264
1265         // if in multiplayer, disable the button for all players except the host
1266         // also disable for squad war matches
1267         if(Game_mode & GM_MULTIPLAYER){
1268                 if((Netgame.type_flags & NG_TYPE_SW) || !(Net_player->flags & NETINFO_FLAG_GAME_HOST)){
1269                         Buttons[gr_screen.res][REPLAY_MISSION].button.disable();
1270                 }
1271         }
1272 }
1273
1274 // --------------------------------------------------------------------------------------
1275 //      debrief_ui_init()
1276 //
1277 void debrief_ui_init()
1278 {
1279         // init ship selection masks and buttons
1280         common_set_interface_palette("DebriefPalette");         // set the interface palette
1281         Debrief_ui_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
1282         Debrief_ui_window.set_mask_bmap(Debrief_mask_name[gr_screen.res]);
1283         Debrief_ui_window.tooltip_handler = debrief_tooltip_handler;
1284         debrief_buttons_init();
1285
1286         // load in help overlay bitmap  
1287         help_overlay_load(DEBRIEFING_OVERLAY);
1288         help_overlay_set_state(DEBRIEFING_OVERLAY,0);
1289
1290         if ( Game_mode & GM_MULTIPLAYER ) {
1291                 // close down any old instances of the chatbox
1292                 chatbox_close();
1293
1294                 // create the new one
1295                 chatbox_create();
1296                 Background_bitmap = bm_load(Debrief_multi_name[gr_screen.res]);
1297                 List_region.create(&Debrief_ui_window, "", Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1], Debrief_list_coords[gr_screen.res][2], Debrief_list_coords[gr_screen.res][3], 0, 1);
1298                 List_region.hide();
1299         } else {
1300                 Background_bitmap = bm_load(Debrief_single_name[gr_screen.res]);
1301         }
1302
1303         if ( Background_bitmap < 0 ) {
1304                 Warning(LOCATION, "Could not load the background bitmap for debrief screen");
1305         }
1306
1307         Award_bg_bitmap = bm_load(Debrief_award_filename[gr_screen.res][DB_AWARD_BG]);
1308         Debrief_multi_loading_bitmap = bm_load(Debrief_loading_bitmap_fname[gr_screen.res]);
1309 }
1310
1311 // sets Promotion_stage.voice
1312 // defaults to number 9 (Petrarch) for non-volition missions
1313 // this is an ugly, nasty way of doing this, but it saves us changing the missions at this point
1314 void debrief_choose_promotion_voice()
1315 {
1316         int i, j;
1317
1318         if(Campaign.current_mission < 0){
1319                 SDL_snprintf(Promotion_stage.voice, SDL_arraysize(Promotion_stage.voice), NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
1320                 return;
1321         }
1322
1323         // search thru all official campaigns for our current campaign
1324         if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename)) {
1325                 for (i=0; i<NUM_VOLITION_CAMPAIGNS; i++) {
1326                         if ((Campaign.filename != NULL) && !SDL_strcasecmp(Campaign.filename, Volition_campaigns[i].campaign_name)) {   
1327                                 // now search thru the mission filenames, 
1328                                 for (j=0; j<Volition_campaigns[i].num_missions; j++) {
1329                                         if ((Campaign.missions[Campaign.current_mission].name != NULL) && !SDL_strcasecmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file)) {
1330                                                 // found it!  set the persona and bail
1331                                                 SDL_snprintf(Promotion_stage.voice, SDL_arraysize(Promotion_stage.voice), NOX("%d_%s"), Debrief_promotion_voice_mapping[i][j].persona_index, Ranks[Promoted].promotion_voice_base);
1332                                                 return;
1333                                         }
1334                                 }
1335                         }
1336                 }
1337         }
1338
1339         // default to petrarch
1340         SDL_snprintf(Promotion_stage.voice, SDL_arraysize(Promotion_stage.voice), NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
1341 }
1342
1343 // sets Promotion_stage.voice
1344 // defaults to number 9 (Petrarch) for non-volition missions
1345 // this is an ugly, nasty, hateful way of doing this, but it saves us changing the missions at this point
1346 void debrief_choose_badge_voice()
1347 {
1348 #ifndef MAKE_FS1
1349         int i, j;
1350 #endif
1351
1352         if(Campaign.current_mission < 0){
1353 #ifndef MAKE_FS1
1354                 // default to petrarch
1355                 SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1356 #else
1357                 // default to FS1 guy
1358                 SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1359 #endif
1360         }
1361
1362         if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename)) {
1363 #ifdef MAKE_FS1
1364                 if ( Player->on_bastion ) {
1365                         SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base2);
1366                         return;
1367                 } else {
1368                         SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1369                         return;
1370                 }
1371 #else
1372                 // search thru all official campaigns for our current campaign
1373                 for (i=0; i<NUM_VOLITION_CAMPAIGNS; i++) {
1374                         if ((Campaign.filename != NULL) && !SDL_strcasecmp(Campaign.filename, Volition_campaigns[i].campaign_name)) {   
1375                                 // now search thru the mission filenames, 
1376                                 for (j=0; j<Campaign.num_missions; j++) {
1377                                         if ((Campaign.missions[Campaign.current_mission].name != NULL) && !SDL_strcasecmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file)) {
1378                                                 // found it!  set the persona and bail
1379                                                 SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("%d_%s"), Debrief_promotion_voice_mapping[i][j].persona_index, Badge_info[Player->stats.m_badge_earned].voice_base);
1380                                                 return;
1381                                         }
1382                                 }
1383                         }
1384                 }
1385 #endif
1386         }
1387
1388 #ifndef MAKE_FS1
1389         // default to petrarch
1390         SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1391 #else
1392         // default to FS1 guy
1393         SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1394 #endif
1395 }
1396
1397
1398 void debrief_award_init()
1399 {
1400         char buf[80];
1401         int i;
1402
1403         Rank_bitmap = -1; 
1404         Medal_bitmap = -1;
1405         Badge_bitmap = -1;
1406         Wings_bitmap = -1;
1407         Crest_bitmap = -1;
1408         Promoted = -1;
1409
1410         // be sure there are no old award texts floating around
1411 #ifndef MAKE_FS1
1412         debrief_award_text_clear();
1413 #endif
1414
1415         // handle medal earned
1416         if (Player->stats.m_medal_earned != -1) {
1417                 if (Player->stats.m_medal_earned == 13) {  // special hack for the wings..
1418                         int ver;
1419                         if ( Player->stats.medals[13] > 1 ) {
1420                                 ver = 1;
1421                         } else {
1422                                 ver = 0;
1423                         }
1424                         SDL_snprintf(buf, SDL_arraysize(buf), NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_WINGS], ver);
1425                         Wings_bitmap = bm_load(buf);
1426 #ifndef MAKE_FS1
1427                 } else if (Player->stats.m_medal_earned == 17) {  // special hack for the soc crest
1428                         Crest_bitmap = bm_load(Debrief_award_filename[gr_screen.res][DB_AWARD_SOC]);
1429 #endif
1430                 } else {
1431                         SDL_snprintf(buf, SDL_arraysize(buf), NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_MEDAL], Player->stats.m_medal_earned);
1432                         Medal_bitmap = bm_load(buf);
1433                 }
1434
1435 #ifndef MAKE_FS1
1436                 debrief_add_award_text(Medals[Player->stats.m_medal_earned].name);
1437 #endif
1438         }
1439         
1440         // handle promotions
1441         if ( Player->stats.m_promotion_earned != -1 ) {
1442                 Promoted = Player->stats.m_promotion_earned;
1443                 SDL_snprintf(buf, SDL_arraysize(buf), NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_RANK], Promoted + 1);
1444                 Rank_bitmap = bm_load(buf);
1445
1446                 Promotion_stage.new_text = Ranks[Promoted].promotion_text;
1447                 Promotion_stage.new_recommendation_text = NULL;
1448
1449                 // choose appropriate promotion voice for this mission
1450                 debrief_choose_promotion_voice();
1451
1452 #ifndef MAKE_FS1
1453                 debrief_add_award_text(Ranks[Promoted].name);
1454 #endif
1455         }
1456
1457         // handle badge earned
1458         // only grant badge if earned and allowed.  (no_promotion really means no promotion and no badges)
1459         if ( Player->stats.m_badge_earned != -1 ) {
1460                 i = Player->stats.m_badge_earned;
1461                 SDL_snprintf(buf, SDL_arraysize(buf), NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_BADGE], i + 1);
1462                 Badge_bitmap = bm_load(buf);
1463
1464                 Badge_stage.new_text = Badge_info[i].promotion_text;
1465                 Badge_stage.new_recommendation_text = NULL;
1466
1467                 // choose appropriate voice
1468                 debrief_choose_badge_voice();
1469
1470 #ifndef MAKE_FS1
1471                 debrief_add_award_text(Medals[Badge_index[i]].name);
1472 #endif
1473         }
1474
1475         if ((Rank_bitmap >= 0) || (Medal_bitmap >= 0) || (Badge_bitmap >= 0) || (Wings_bitmap >= 0) || (Crest_bitmap >= 0)) {
1476                 Award_active = 1;
1477         } else {
1478                 Award_active = 0;
1479         }
1480 }
1481
1482 // debrief_traitor_init() initializes local data which could be used if the player leaves the 
1483 // mission a traitor.  The same debriefing always gets played
1484 void debrief_traitor_init()
1485 {
1486         static int inited = 0;
1487
1488         if ( !inited ) {
1489                 debriefing              *debrief;
1490                 debrief_stage   *stagep;
1491                 int stage_num;
1492
1493                 // open localization
1494                 lcl_ext_open();
1495
1496                 try {
1497                         read_file_text("traitor.tbl");
1498                         reset_parse();          
1499
1500                         // simplied form of the debriefing stuff.
1501                         debrief = &Traitor_debriefing;
1502                         required_string("#Debriefing_info");
1503
1504                         required_string("$Num stages:");
1505                         stuff_int(&debrief->num_stages);
1506                         SDL_assert(debrief->num_stages == 1);
1507
1508                         stage_num = 0;
1509                         stagep = &debrief->stages[stage_num++];
1510                         required_string("$Formula:");
1511                         stagep->formula = get_sexp_main();
1512                         required_string("$multi text");
1513                         if ( Fred_running )     {
1514                                 stuff_string( stagep->new_text, F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1515                         } else {
1516                                 stagep->new_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1517                         }
1518                         required_string("$Voice:");
1519                         char traitor_voice_file[NAME_LENGTH];
1520                         stuff_string(traitor_voice_file, F_FILESPEC, NULL);
1521
1522 // DKA 9/13/99 Only 1 traitor msg for FS2
1523 #ifdef MAKE_FS1
1524                         if ( Player->on_bastion ) {
1525                                 SDL_strlcpy(stagep->voice, NOX("3_"), SDL_arraysize(stagep->voice));
1526                         } else {
1527                                 SDL_strlcpy(stagep->voice, NOX("1_"), SDL_arraysize(stagep->voice));
1528                         }
1529 #endif
1530
1531                         SDL_strlcat(stagep->voice, traitor_voice_file, SDL_arraysize(stagep->voice));
1532
1533                         required_string("$Recommendation text:");
1534                         if ( Fred_running )     {
1535                                 stuff_string( stagep->new_recommendation_text, F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1536                         } else {
1537                                 stagep->new_recommendation_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1538                         }
1539
1540                         inited = 1;
1541                 } catch (parse_error_t rval) {
1542                         Error(LOCATION, "Unable to parse traitor.tbl!  Code = %i.\n", (int)rval);
1543                 }
1544
1545                 // close localization
1546                 lcl_ext_close();
1547         }
1548
1549         // disable the accept button if in single player and I am a traitor
1550         Debrief_accepted = 0;
1551         Turned_traitor = Must_replay_mission = 0;
1552         if (!(Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_CAMPAIGN_MODE)) {
1553                 if (Player_ship->team == TEAM_TRAITOR){
1554                         Turned_traitor = 1;
1555                 }
1556
1557                 if (Campaign.next_mission == Campaign.current_mission){
1558                         Must_replay_mission = 1;
1559                 }
1560         }
1561
1562         if (Turned_traitor || Must_replay_mission) {
1563                 Buttons[gr_screen.res][ACCEPT_BUTTON].button.hide();
1564
1565                 // kill off any stats
1566                 Player->flags &= ~PLAYER_FLAGS_PROMOTED;
1567                 scoring_level_init( &Player->stats );
1568         }
1569 }
1570
1571 // initialization for listing of players in game
1572 void debrief_multi_list_init()
1573 {
1574         Multi_list_size = 0;  // number of net players to choose from
1575         Multi_list_offset = 0;
1576
1577         Multi_list_select = -1;
1578
1579         if ( !(Game_mode & GM_MULTIPLAYER) ) 
1580                 return;
1581
1582         debrief_rebuild_player_list();
1583
1584         // switch stats display to this newly selected player
1585         set_player_stats(Multi_list[0].net_player_index);
1586         SDL_strlcpy(Debrief_current_callsign, Multi_list[0].callsign, SDL_arraysize(Debrief_current_callsign));
1587         Debrief_player = Player;
1588 }
1589
1590 void debrief_multi_list_scroll_up()
1591 {
1592         // if we're at the beginning of the list, don't do anything
1593         if(Multi_list_offset == 0){
1594                 gamesnd_play_iface(SND_GENERAL_FAIL);
1595                 return;
1596         }
1597
1598         // otherwise scroll up
1599         Multi_list_offset--;
1600         gamesnd_play_iface(SND_USER_SELECT);
1601 }
1602
1603 void debrief_multi_list_scroll_down()
1604 {               
1605         // if we can scroll down no further
1606         if(Multi_list_size < Debrief_multi_list_team_max_display[gr_screen.res]){
1607                 gamesnd_play_iface(SND_GENERAL_FAIL);
1608                 return;
1609         }
1610         if((Multi_list_offset + Debrief_multi_list_team_max_display[gr_screen.res]) >= Multi_list_size){
1611                 gamesnd_play_iface(SND_GENERAL_FAIL);
1612                 return;
1613         }
1614
1615         // otherwise scroll down
1616         Multi_list_offset++;
1617         gamesnd_play_iface(SND_USER_SELECT);
1618 }
1619
1620 // draw the connected net players
1621 void debrief_multi_list_draw()
1622 {
1623         int y, z, font_height,idx;
1624         char str[CALLSIGN_LEN+5];
1625         net_player *np;
1626         
1627         font_height = gr_get_font_height();     
1628
1629         // if we currently have no item picked, pick a reasonable one
1630         if((Multi_list_size >= 0) && (Multi_list_select == -1)){
1631                 // select the entry which corresponds to the local player
1632                 Multi_list_select = 0;                          
1633                 for(idx=0;idx<Multi_list_size;idx++){
1634                         if(Multi_list[idx].net_player_index == MY_NET_PLAYER_NUM){
1635                                 Multi_list_select = idx;
1636
1637                                 // switch stats display to this newly selected player
1638                                 set_player_stats(Multi_list[idx].net_player_index);
1639                                 SDL_strlcpy(Debrief_current_callsign, Multi_list[idx].callsign, SDL_arraysize(Debrief_current_callsign));
1640                                 Debrief_player = Net_players[Multi_list[idx].net_player_index].player;                          
1641                                 break;
1642                         }
1643                 }
1644         }
1645
1646         // draw the list itself
1647         y = 0;
1648         z = Multi_list_offset;
1649         while (y + font_height <= Debrief_list_coords[gr_screen.res][3]){
1650                 np = &Net_players[Multi_list[z].net_player_index];
1651
1652                 if (z >= Multi_list_size){
1653                         break;
1654                 }
1655                 // set the proper text color for the highlight
1656                 if(np->flags & NETINFO_FLAG_GAME_HOST){
1657                         if(Multi_list_select == z){
1658                                 gr_set_color_fast(&Color_text_active_hi);
1659                         } else {
1660                                 gr_set_color_fast(&Color_bright);
1661                         }
1662                 } else {
1663                         if(Multi_list_select == z){
1664                                 gr_set_color_fast(&Color_text_active);
1665                         } else {
1666                                 gr_set_color_fast(&Color_text_normal);
1667                         }
1668                 }
1669
1670                 // blit the proper indicator - skipping observers
1671                 if(!((np->flags & NETINFO_FLAG_OBSERVER) && !(np->flags & NETINFO_FLAG_OBS_PLAYER))){
1672                         if(Netgame.type_flags & NG_TYPE_TEAM){
1673                                 // team 0
1674                                 if(np->p_info.team == 0){
1675                                         // draw his "selected" icon
1676                                         if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM0_SELECT] != -1)){
1677                                                 gr_set_bitmap(Multi_common_icons[MICON_TEAM0_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1678                                                 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1679                                         } 
1680                                         // draw his "normal" icon
1681                                         else if(Multi_common_icons[MICON_TEAM0] != -1){
1682                                                 gr_set_bitmap(Multi_common_icons[MICON_TEAM0], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1683                                                 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1684                                         }                                       
1685                                 } else if(np->p_info.team == 1){
1686                                         // draw his "selected" icon
1687                                         if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM1_SELECT] != -1)){                                         
1688                                                 gr_set_bitmap(Multi_common_icons[MICON_TEAM1_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1689                                                 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1690                                         } 
1691                                         // draw his "normal" icon
1692                                         else if(Multi_common_icons[MICON_TEAM1] != -1){
1693                                                 gr_set_bitmap(Multi_common_icons[MICON_TEAM1], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1694                                                 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1695                                         }                                       
1696                                 }
1697                         } else {
1698                                 // draw the team 0 selected icon
1699                                 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM0_SELECT] != -1)){
1700                                         gr_set_bitmap(Multi_common_icons[MICON_TEAM0_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1701                                         gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1702                                 }
1703                         }
1704                 }
1705
1706                 SDL_strlcpy(str, Multi_list[z].callsign, SDL_arraysize(str));
1707                 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)){
1708                         SDL_strlcat(str, XSTR( "(O)", 438), SDL_arraysize(str));
1709                 }               
1710
1711                 // bli
1712                 gr_string(Debrief_list_coords[gr_screen.res][0] + MULTI_LIST_TEAM_OFFSET, Debrief_list_coords[gr_screen.res][1] + y, str);
1713
1714                 y += font_height;
1715                 z++;
1716         }
1717 }
1718
1719 void debrief_kick_selected_player()
1720 {
1721         if(Multi_list_select >= 0){
1722                 SDL_assert(Net_player->flags & NETINFO_FLAG_GAME_HOST);
1723                 multi_kick_player(Multi_list[Multi_list_select].net_player_index);
1724         }
1725 }
1726
1727 // get optional mission popup text 
1728 void debrief_assemble_optional_mission_popup_text(char *buffer, const int buf_len, char *mission_loop_desc)
1729 {
1730         SDL_assert(buffer != NULL);
1731         // base message
1732
1733         if (mission_loop_desc == NULL) {
1734                 SDL_strlcpy(buffer, XSTR("<No Mission Loop Description Available>", 1490), buf_len);
1735                 mprintf(("No mission loop description avail"));
1736         } else {
1737                 SDL_strlcpy(buffer, mission_loop_desc, buf_len);
1738         }
1739
1740         SDL_strlcat(buffer, XSTR("\n\n\nDo you want to play the optional mission?", 1491), buf_len);
1741 }
1742
1743 // what to do when the accept button is hit
1744 void debrief_accept(int ok_to_post_start_game_event)
1745 {
1746         int go_loop = 0;
1747
1748         if ( (/*Cheats_enabled ||*/ Turned_traitor || Must_replay_mission) && (Game_mode & GM_CAMPAIGN_MODE) ) {
1749                 const char *str;
1750                 int z;
1751
1752                 if (Game_mode & GM_MULTIPLAYER) {
1753                         return;
1754                 }
1755
1756                 if (Player_ship->team == TEAM_TRAITOR){
1757                         str = XSTR( "Your career is over, Traitor!  You can't accept new missions!", 439);
1758                 }/* else if (Cheats_enabled) {
1759                         str = XSTR( "You are a cheater.  You cannot accept this mission!", 440);
1760                 }*/ else {
1761                         str = XSTR( "You have failed this mission and cannot accept.  What do you you wish to do instead?", 441);
1762                 }
1763
1764                 z = popup(0, 3, XSTR( "Return to &Debriefing", 442), XSTR( "Go to &Flight Deck", 443), XSTR( "&Replay Mission", 444), str);
1765                 if (z == 2){
1766                         gameseq_post_event(GS_EVENT_START_BRIEFING);  // cycle back to briefing
1767                 } else if ( z == 1 ) {
1768                         gameseq_post_event(GS_EVENT_END_GAME);  // return to main hall, tossing stats
1769                 }
1770
1771                 return;
1772         }
1773
1774         Debrief_accepted = 1;
1775         // save mission stats
1776         if (Game_mode & GM_MULTIPLAYER) {
1777                 // note that multi_debrief_accept_hit() will handle all mission_campaign_* calls on its own
1778                 // as well as doing stats transfers, etc.
1779                 multi_debrief_accept_hit();
1780
1781         } else {
1782
1783                 int play_commit_sound = 1;
1784                 // only write the player's stats if he's accepted
1785
1786                 // if we are just playing a single mission, then don't do many of the things
1787                 // that need to be done.  Nothing much should happen when just playing a single
1788                 // mission that isn't in a campaign.
1789                 if ( Game_mode & GM_CAMPAIGN_MODE ) {
1790
1791                         // check for possible mission loop
1792                         // check for (1) mission loop available, (2) dont have to repeat last mission
1793                         if(!(Game_mode & GM_MULTIPLAYER)){
1794                                 int cur = Campaign.current_mission;
1795                                 bool require_repeat_mission = (Campaign.current_mission == Campaign.next_mission);
1796                                 if (Campaign.missions[cur].has_mission_loop) {
1797                                         SDL_assert(Campaign.loop_mission != CAMPAIGN_LOOP_MISSION_UNINITIALIZED);
1798                                 }
1799
1800                                 if ( (Campaign.missions[cur].has_mission_loop && (Campaign.loop_mission != -1)) && !require_repeat_mission ) {
1801                                         /*
1802                                         char buffer[512];
1803                                         debrief_assemble_optional_mission_popup_text(buffer, Campaign.missions[cur].mission_loop_desc);
1804
1805                                         int choice = popup(0 , 2, POPUP_NO, POPUP_YES, buffer);
1806                                         if (choice == 1) {
1807                                                 Campaign.loop_enabled = 1;
1808                                                 Campaign.next_mission = Campaign.loop_mission;
1809                                         }
1810                                         */
1811                                         go_loop = 1;
1812                                 }
1813                         }                       
1814
1815                         // loopy loopy time
1816                         if (go_loop) {
1817                                 if(ok_to_post_start_game_event){
1818                                         gameseq_post_event(GS_EVENT_LOOP_BRIEF);
1819                                 } else {
1820                                         play_commit_sound = 0;
1821                                 }
1822                         }
1823                         // continue as normal
1824                         else {
1825                                 // end the mission
1826                                 mission_campaign_mission_over();
1827
1828                                 // check to see if we are out of the loop now
1829                                 if ( Campaign.next_mission == Campaign.loop_reentry ) {
1830                                         Campaign.loop_enabled = 0;
1831                                 }
1832
1833                                 // check if campaign is over
1834                                 if ( Campaign.next_mission == -1 ) {
1835         #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
1836                                         gameseq_post_event(GS_EVENT_END_DEMO);
1837         #else
1838                                         gameseq_post_event(GS_EVENT_MAIN_MENU);
1839         #endif
1840                                 } else {
1841                                         if ( ok_to_post_start_game_event ) {
1842                                                 gameseq_post_event(GS_EVENT_START_GAME);
1843                                         } else {
1844                                                 play_commit_sound = 0;
1845                                         }
1846                                 }
1847                         }
1848                 } else {
1849                         gameseq_post_event(GS_EVENT_MAIN_MENU);
1850                 }
1851
1852                 if ( play_commit_sound ) {
1853                         gamesnd_play_iface(SND_COMMIT_PRESSED);
1854                 }
1855
1856                 game_flush();
1857         }
1858 }
1859
1860 void debrief_next_tab()
1861 {
1862         New_mode = Current_mode + 1;
1863         if (New_mode >= NUM_TABS)
1864                 New_mode = 0;
1865 }
1866
1867 void debrief_prev_tab()
1868 {
1869         New_mode = Current_mode - 1;
1870         if (New_mode < 0)
1871                 New_mode = NUM_TABS - 1;
1872 }
1873
1874 // --------------------------------------------------------------------------------------
1875 //      debrief_next_stage()
1876 //
1877 void debrief_next_stage()
1878 {
1879         if (Current_stage < Num_stages - 1) {
1880                 New_stage = Current_stage + 1;
1881                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1882
1883         } else
1884                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1885 }
1886
1887 // --------------------------------------------------------------------------------------
1888 //      debrief_prev_stage()
1889 //
1890 void debrief_prev_stage()
1891 {
1892         if (Current_stage) {
1893                 New_stage = Current_stage - 1;
1894                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1895
1896         } else
1897                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1898 }
1899
1900 // --------------------------------------------------------------------------------------
1901 //      debrief_first_stage()
1902 void debrief_first_stage()
1903 {
1904         if (Current_stage) {
1905                 New_stage = 0;
1906                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1907
1908         } else
1909                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1910 }
1911
1912 // --------------------------------------------------------------------------------------
1913 //      debrief_last_stage()
1914 void debrief_last_stage()
1915 {
1916         if (Current_stage != Num_stages - 1) {
1917                 New_stage = Num_stages - 1;
1918                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1919
1920         } else
1921                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1922 }
1923
1924 // draw what stage number the debriefing is on
1925 void debrief_render_stagenum()
1926 {
1927         int w;
1928         char buf[64];
1929         
1930         if (Num_stages < 2)
1931                 return;
1932                 
1933         SDL_snprintf(buf, SDL_arraysize(buf), XSTR( "%d of %d", 445), Current_stage + 1, Num_stages);
1934         gr_get_string_size(&w, NULL, buf);
1935         gr_set_color_fast(&Color_bright_blue);
1936         gr_string(Debrief_stage_info_coords[gr_screen.res][0] - w, Debrief_stage_info_coords[gr_screen.res][1], buf);
1937         gr_set_color_fast(&Color_white);
1938 }
1939
1940 // render the mission time at the specified y location
1941 void debrief_render_mission_time(int y_loc)
1942 {
1943         char time_str[30];
1944         
1945         game_format_time(Missiontime, time_str, SDL_arraysize(time_str));
1946         gr_string(0, y_loc, XSTR( "Mission Time", 446));
1947         gr_string(Debrief_text_x2[gr_screen.res], y_loc, time_str);     
1948 }
1949
1950 // render out the debriefing text to the scroll window
1951 void debrief_render()
1952 {
1953         int y, z, font_height;
1954
1955         if ( Num_stages <= 0 )
1956                 return;
1957
1958         font_height = gr_get_font_height();
1959
1960         gr_set_clip(Debrief_text_wnd_coords[gr_screen.res][0], Debrief_text_wnd_coords[gr_screen.res][1], Debrief_text_wnd_coords[gr_screen.res][2], Debrief_text_wnd_coords[gr_screen.res][3]);
1961         y = 0;
1962         z = Text_offset;
1963         while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
1964                 if (z >= Num_text_lines)
1965                         break;
1966
1967                 if (Text_type[z] == TEXT_TYPE_NORMAL)
1968                         gr_set_color_fast(&Color_white);
1969                 else
1970                         gr_set_color_fast(&Color_bright_red);
1971
1972                 if (Text[z])
1973                         gr_string(0, y, Text[z]);
1974
1975                 y += font_height;
1976                 z++;
1977         }
1978
1979         gr_reset_clip();
1980 }
1981
1982 // render out the stats info to the scroll window
1983 //
1984 void debrief_stats_render()
1985 {       
1986         int i, y, font_height;  
1987
1988         gr_set_color_fast(&Color_blue);
1989         gr_set_clip(Debrief_text_wnd_coords[gr_screen.res][0], Debrief_text_wnd_coords[gr_screen.res][1], Debrief_text_wnd_coords[gr_screen.res][2], Debrief_text_wnd_coords[gr_screen.res][3]);
1990         gr_string(0, 0, Debrief_current_callsign);
1991         font_height = gr_get_font_height();
1992         y = 30;
1993         
1994         switch ( Current_stage ) {
1995                 case DEBRIEF_MISSION_STATS:
1996                         i = Current_stage - 1;
1997                         if ( i < 0 )
1998                                 i = 0;
1999
2000                         gr_set_color_fast(&Color_white);
2001
2002                         // display mission completion time
2003                         debrief_render_mission_time(y);
2004
2005                         y += 20;
2006                         show_stats_label(i, 0, y, font_height);
2007                         show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2008                         break;
2009                 case DEBRIEF_ALLTIME_STATS:
2010                         i = Current_stage - 1;
2011                         if ( i < 0 )
2012                                 i = 0;
2013
2014                         gr_set_color_fast(&Color_white);
2015                         show_stats_label(i, 0, y, font_height);
2016                         show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2017                         break;
2018
2019                 case DEBRIEF_ALLTIME_KILLS:
2020                 case DEBRIEF_MISSION_KILLS:
2021                         gr_set_color_fast(&Color_white);
2022                         i = Text_offset;
2023                         while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
2024                                 if (i >= Num_text_lines)
2025                                         break;
2026
2027                                 if (!i) {
2028                                         if ( Current_stage == DEBRIEF_MISSION_KILLS )
2029                                                 gr_printf(0, y, XSTR( "Mission Kills by Ship Type", 447));
2030                                         else
2031                                                 gr_printf(0, y, XSTR( "All-time Kills by Ship Type", 448));
2032
2033                                 } else if (i > 1) {
2034                                         gr_printf(0, y, "%s", Debrief_stats_kills[i - 2].text);
2035                                         gr_printf(Debrief_text_x2[gr_screen.res], y, "%d", Debrief_stats_kills[i - 2].num);
2036                                 }
2037
2038                                 y += font_height;
2039                                 i++;
2040                         }
2041
2042                         if (Num_text_lines == 2) {
2043                                 if ( Current_stage == DEBRIEF_MISSION_KILLS )
2044                                         gr_printf(0, y, XSTR( "(No ship kills this mission)", 449));
2045                                 else
2046                                         gr_printf(0, y, XSTR( "(No ship kills)", 450));
2047                         }
2048
2049                         break;
2050
2051                 default:
2052                         Int3();
2053                         break;
2054         } 
2055
2056         gr_reset_clip();
2057 }
2058
2059 // do action for when the replay button is pressed
2060 void debrief_replay_pressed()
2061 {       
2062         if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2063                 int choice;
2064                 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));
2065
2066                 if (choice != 1){
2067                         return;
2068                 }
2069         }
2070
2071         gameseq_post_event(GS_EVENT_START_BRIEFING);            // take us to the briefing
2072         gamesnd_play_iface(SND_COMMIT_PRESSED);
2073 }
2074
2075 // -------------------------------------------------------------------
2076 // debrief_redraw_pressed_buttons()
2077 //
2078 // Redraw any debriefing buttons that are pressed down.  This function is needed
2079 // since we sometimes need to draw pressed buttons last to ensure the entire
2080 // button gets drawn (and not overlapped by other buttons)
2081 //
2082 void debrief_redraw_pressed_buttons()
2083 {
2084         int i;
2085         UI_BUTTON *b;
2086         
2087         for ( i=0; i<NUM_BUTTONS; i++ ) {
2088                 b = &Buttons[gr_screen.res][i].button;
2089                 // don't draw the recommendations button if we're in stats mode
2090                 if ( b->button_down() ) {
2091                         b->draw_forced(2);
2092                 }
2093         }
2094 }
2095
2096 // debrief specific button with hotspot 'i' has been pressed, so perform the associated action
2097 //
2098 void debrief_button_pressed(int num)
2099 {
2100         switch (num) {
2101                 case DEBRIEF_TAB:
2102                         Buttons[gr_screen.res][RECOMMENDATIONS].button.enable();                        
2103                         // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
2104                         if (num != Current_mode){
2105                                 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
2106                         }
2107                         New_mode = num;
2108                         break;
2109                 case STATS_TAB:
2110                         // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 1;                    // allows failure sound to be played
2111                         Buttons[gr_screen.res][RECOMMENDATIONS].button.disable();                       
2112                         if (num != Current_mode){
2113                                 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
2114                         }
2115                         New_mode = num;
2116                         break;
2117
2118                 case TEXT_SCROLL_UP:
2119                         if (Text_offset) {
2120                                 Text_offset--;
2121                                 gamesnd_play_iface(SND_SCROLL);
2122                         } else {
2123                                 gamesnd_play_iface(SND_GENERAL_FAIL);
2124                         }
2125                         break;
2126
2127                 case TEXT_SCROLL_DOWN:
2128                         if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
2129                                 Text_offset++;
2130                                 gamesnd_play_iface(SND_SCROLL);
2131                         } else {
2132                                 gamesnd_play_iface(SND_GENERAL_FAIL);
2133                         }
2134                         break;
2135
2136                 case REPLAY_MISSION:
2137                         if(Game_mode & GM_MULTIPLAYER){
2138                                 multi_debrief_replay_hit();
2139                         } else {                        
2140                                 debrief_replay_pressed();       
2141                         }
2142                         break;
2143
2144                 case RECOMMENDATIONS:
2145                         gamesnd_play_iface(SND_USER_SELECT);
2146                         Recommend_active = !Recommend_active;
2147                         debrief_text_init();
2148                         break;
2149
2150                 case FIRST_STAGE:
2151                         debrief_first_stage();
2152                         break;
2153
2154                 case PREV_STAGE:
2155                         debrief_prev_stage();
2156                         break;
2157
2158                 case NEXT_STAGE:
2159                         debrief_next_stage();
2160                         break;
2161
2162                 case LAST_STAGE:
2163                         debrief_last_stage();
2164                         break;
2165
2166                 case HELP_BUTTON:
2167                         gamesnd_play_iface(SND_HELP_PRESSED);
2168                         launch_context_help();
2169                         break;
2170
2171                 case OPTIONS_BUTTON:
2172                         gamesnd_play_iface(SND_SWITCH_SCREENS);
2173                         gameseq_post_event( GS_EVENT_OPTIONS_MENU );
2174                         break;
2175
2176                 case ACCEPT_BUTTON:
2177                         debrief_accept();
2178                         break;
2179
2180                 case MEDALS_BUTTON:
2181                         gamesnd_play_iface(SND_SWITCH_SCREENS);
2182                         gameseq_post_event(GS_EVENT_VIEW_MEDALS);
2183                         break;
2184
2185                 case PLAYER_SCROLL_UP:
2186                         debrief_multi_list_scroll_up();
2187                         break;
2188
2189                 case PLAYER_SCROLL_DOWN:
2190                         debrief_multi_list_scroll_down();
2191                         break;
2192
2193                 case MULTI_PINFO_POPUP:
2194                         Debrief_should_show_popup = 1;
2195                         break;
2196
2197                 case MULTI_KICK:
2198                         debrief_kick_selected_player();
2199                         break;
2200         } // end swtich
2201 }
2202
2203 void debrief_setup_ship_kill_stats(int stage_num)
2204 {
2205         int i;
2206 #ifndef MAKE_FS1
2207         ushort *kill_arr;
2208 #else
2209         int *kill_arr;
2210 #endif
2211         debrief_stats_kill_info *kill_info;
2212
2213         SDL_assert(Current_stage < DEBRIEF_NUM_STATS_PAGES);
2214         if ( Current_stage == DEBRIEF_MISSION_STATS || Current_stage == DEBRIEF_ALLTIME_STATS )
2215                 return;
2216
2217         SDL_assert(Debrief_player != NULL);
2218
2219         // kill_ar points to an array of MAX_SHIP_TYPE ints
2220         if ( Current_stage == DEBRIEF_MISSION_KILLS ) {
2221                 kill_arr = Debrief_player->stats.m_okKills;
2222         } else {                
2223                 kill_arr = Debrief_player->stats.kills;
2224         }
2225
2226         Num_text_lines = 0;
2227         for ( i=0; i<MAX_SHIP_TYPES; i++ ) {
2228
2229                 // code used to add in mission kills, but the new system assumes that the player will accept, so
2230                 // all time stats already have mission stats added in.
2231                 if ( kill_arr[i] <= 0 ){
2232                         continue;
2233                 }
2234
2235
2236                 kill_info = &Debrief_stats_kills[Num_text_lines++];
2237
2238                 kill_info->num = kill_arr[i];
2239
2240                 SDL_strlcpy(kill_info->text, Ship_info[i].name, SDL_arraysize(kill_info->text));
2241                 SDL_strlcat(kill_info->text, NOX(":"), SDL_arraysize(kill_info->text));
2242         }
2243
2244         Num_text_lines += 2;
2245 }
2246
2247 // Iterate through the debriefing buttons, checking if they are pressed
2248 void debrief_check_buttons()
2249 {
2250         int i, y, z;
2251
2252         for ( i=0; i<NUM_BUTTONS; i++ ) {
2253                 if ( Buttons[gr_screen.res][i].button.pressed() ) {
2254                         debrief_button_pressed(i);
2255                 }
2256         }
2257
2258         if ( !(Game_mode & GM_MULTIPLAYER) ) 
2259                 return;
2260
2261         if (List_region.pressed()) {
2262                 List_region.get_mouse_pos(NULL, &y);
2263                 z = Multi_list_offset + y / gr_get_font_height();
2264                 if ((z >= 0) && (z < Multi_list_size)) {
2265                         // switch stats display to this newly selected player
2266                         set_player_stats(Multi_list[z].net_player_index);
2267                         SDL_strlcpy(Debrief_current_callsign, Multi_list[z].callsign, SDL_arraysize(Debrief_current_callsign));
2268                         Debrief_player = Net_players[Multi_list[z].net_player_index].player;
2269                         Multi_list_select = z;
2270                         debrief_setup_ship_kill_stats(Current_stage);
2271                         gamesnd_play_iface(SND_USER_SELECT);                    
2272                 }
2273         }       
2274
2275         // if the player was double clicked on - we should popup a player info popup
2276         /*
2277         if (List_region.double_clicked()) {
2278                 Debrief_should_show_popup = 1;
2279         }
2280         */
2281 }
2282
2283 void debrief_text_stage_init(const char *src, int type)
2284 {
2285         int i, n_lines, n_chars[MAX_DEBRIEF_LINES];
2286         char line[MAX_DEBRIEF_LINE_LEN];
2287         char *p_str[MAX_DEBRIEF_LINES];
2288         int len;
2289
2290         n_lines = split_str(src, Debrief_text_wnd_coords[gr_screen.res][2], n_chars, p_str, MAX_DEBRIEF_LINES);
2291         SDL_assert(n_lines >= 0);
2292
2293         // if you hit this, you proba   
2294         if(n_lines >= MAX_DEBRIEF_LINES){
2295                 Warning(LOCATION, "You have come close to the limit of debriefing lines, try adding more stages");      
2296         }
2297
2298         for ( i=0; i<n_lines; i++ ) {
2299                 SDL_assert(n_chars[i] < MAX_DEBRIEF_LINE_LEN);
2300                 SDL_assert(Num_text_lines < MAX_TOTAL_DEBRIEF_LINES);
2301                 len = min(n_chars[i] + 1, MAX_DEBRIEF_LINE_LEN);
2302                 SDL_strlcpy(line, p_str[i], len);
2303                 line[n_chars[i]] = 0;
2304                 drop_white_space(line);
2305                 Text_type[Num_text_lines] = type;
2306                 Text[Num_text_lines++] = strdup(line);
2307         }
2308
2309         return;
2310 }
2311
2312 void debrief_free_text()
2313 {
2314         int i;
2315
2316         for (i=0; i<Num_debrief_lines; i++)
2317                 if (Text[i])
2318                         free(Text[i]);
2319
2320         Num_debrief_lines = 0;
2321 }
2322
2323 // setup the debriefing text lines for rendering
2324 void debrief_text_init()
2325 {
2326         int i, r_count = 0;
2327         const char *src;
2328
2329         // release old text lines first
2330         debrief_free_text();
2331         Num_text_lines = Text_offset = 0;
2332
2333         if (Current_mode == DEBRIEF_TAB) {
2334                 for (i=0; i<Num_debrief_stages; i++) {
2335                         if (i)
2336                                 Text[Num_text_lines++] = NULL;  // add a blank line between stages
2337
2338                         src = Debrief_stages[i]->new_text;
2339                         if (src)
2340                                 debrief_text_stage_init(src, TEXT_TYPE_NORMAL);
2341
2342                         if (Recommend_active) {
2343                                 src = Debrief_stages[i]->new_recommendation_text;
2344                                 if (!src && (i == Num_debrief_stages - 1) && !r_count)
2345                                         src = XSTR( "We have no recommendations for you.", 1054);
2346
2347                                 if (src) {
2348                                         Text[Num_text_lines++] = NULL;
2349                                         debrief_text_stage_init(src, TEXT_TYPE_RECOMMENDATION);
2350                                         r_count++;
2351                                 }
2352                         }
2353                 }
2354
2355                 Num_debrief_lines = Num_text_lines;
2356                 return;
2357         }
2358
2359         // not in debriefing mode, must be in stats mode
2360         Num_text_lines = 0;
2361         debrief_setup_ship_kill_stats(Current_stage);
2362 }
2363
2364
2365 // --------------------------------------------------------------------------------------
2366 //
2367 void debrief_init()
2368 {
2369         SDL_assert(!Debrief_inited);
2370 //      Campaign.loop_enabled = 0;
2371         Campaign.loop_mission = CAMPAIGN_LOOP_MISSION_UNINITIALIZED;
2372
2373         // set up the right briefing for this guy
2374         if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
2375                 Debriefing = &Debriefings[Net_player->p_info.team];
2376         } else {
2377                 Debriefing = &Debriefings[0];                   
2378         }
2379
2380         // no longer is mission
2381         Game_mode &= ~(GM_IN_MISSION);  
2382
2383         game_flush();
2384         Current_mode = -1;
2385         New_mode = DEBRIEF_TAB;
2386         Recommend_active = Award_active = 0;
2387         Current_stage = 0;
2388
2389         Current_stage = -1;
2390         New_stage = 0;
2391         Debrief_cue_voice = 0;
2392         Num_text_lines = Num_debrief_lines = 0;
2393         Debrief_first_voice_flag = 1;
2394
2395         Debrief_multi_voice_loaded = 0;
2396
2397 #ifdef MAKE_FS1
2398         Medal_text_bitmap = bm_load(NOX("DebriefText01"));
2399         Rank_text_bitmap = bm_load(NOX("DebriefText02"));
2400         Badge_text_bitmap = bm_load(NOX("DebriefText03"));
2401 #endif
2402
2403         if ( (Game_mode & GM_CAMPAIGN_MODE) && ( !MULTIPLAYER_CLIENT )  ) {
2404                 // MUST store goals and events first - may be used to evaluate next mission
2405                 // store goals and events
2406                 mission_campaign_store_goals_and_events();
2407
2408                 // evaluate next mission
2409                 mission_campaign_eval_next_mission();
2410         }
2411
2412         // call traitor init before calling scoring_level_close.  traitor init will essentially nullify
2413         // any stats
2414         if ( !(Game_mode & GM_MULTIPLAYER) ) {  // only do for single player
2415                 debrief_traitor_init();                                 // initialize data needed if player becomes traitor.
2416         }
2417
2418         // call scoring level close for my stats.  Needed for award_init.  The stats will
2419         // be backed out if used chooses to replace them.
2420         scoring_level_close();
2421
2422         debrief_ui_init();  // init UI items
2423         debrief_award_init();
2424         show_stats_init();
2425         debrief_voice_init();
2426         debrief_multi_list_init();
2427 //      rank_bitmaps_clear();
2428 //      rank_bitmaps_load();
2429
2430         SDL_strlcpy(Debrief_current_callsign, Player->callsign, SDL_arraysize(Debrief_current_callsign));
2431         Debrief_player = Player;
2432 //      Debrief_current_net_player_index = debrief_multi_list[0].net_player_index;
2433
2434         // set up the Debrief_stages[] and Recommendations[] arrays.  Only do the following stuff
2435         // for non-clients (i.e. single and game server).  Multiplayer clients will get their debriefing
2436         // info directly from the server.
2437         if ( !MULTIPLAYER_CLIENT ) {
2438                 debrief_set_stages_and_multi_stuff();
2439
2440                 if ( Num_debrief_stages <= 0 ) {
2441                         Num_debrief_stages = 0;
2442                 } else {
2443                         debrief_voice_load_all();
2444                 }
2445         } else {
2446                 // multiplayer client may have already received their debriefing info.  If they have not,
2447                 // then set the num debrief stages to 0
2448                 if ( !Debrief_multi_stages_loaded ) {
2449                         Num_debrief_stages = 0;
2450                 }
2451         }
2452
2453         /*
2454         if (mission_evaluate_primary_goals() == PRIMARY_GOALS_COMPLETE) {
2455                 common_music_init(SCORE_DEBRIEF_SUCCESS);
2456         } else {
2457                 common_music_init(SCORE_DEBRIEF_FAIL);
2458         }
2459         */
2460
2461         // start up the appropriate music
2462         if (Campaign.next_mission == Campaign.current_mission) {
2463                 // you failed the mission because you suck, so you get the suck music
2464                 common_music_init(SCORE_DEBRIEF_FAIL);
2465         } else if (mission_goals_met()) {
2466                 // you completed all primaries and secondaries, thus you are a stud boy and you get stud boy music
2467                 common_music_init(SCORE_DEBRIEF_SUCCESS);
2468         } else {
2469                 // you somehow passed the mission, so you get a little something for your efforts.
2470                 common_music_init(SCORE_DEBRIEF_AVERAGE);
2471         }
2472
2473         if (Campaign.next_mission == Campaign.current_mission) {
2474                 // better luck next time, increase his retries
2475                 Player->failures_this_session++;
2476         } else { 
2477                 // clear his retries info regardless of whether or not he accepts
2478                 Player->failures_this_session = 0;
2479         }
2480
2481         if (Game_mode & GM_MULTIPLAYER) {
2482                 multi_debrief_init();
2483
2484                 // if i'm not the host of the game, disable the multi kick button
2485                 if (!(Net_player->flags & NETINFO_FLAG_GAME_HOST)) {
2486                         Buttons[gr_screen.res][MULTI_KICK].button.disable();
2487                 }
2488         } else {
2489                 Buttons[gr_screen.res][PLAYER_SCROLL_UP].button.disable();
2490                 Buttons[gr_screen.res][PLAYER_SCROLL_DOWN].button.disable();
2491                 Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.disable();
2492                 Buttons[gr_screen.res][MULTI_KICK].button.disable();
2493                 Buttons[gr_screen.res][PLAYER_SCROLL_UP].button.hide();
2494                 Buttons[gr_screen.res][PLAYER_SCROLL_DOWN].button.hide();
2495                 Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.hide();                
2496                 Buttons[gr_screen.res][MULTI_KICK].button.hide();
2497         }
2498
2499         if (!Award_active) {
2500                 Buttons[gr_screen.res][MEDALS_BUTTON].button.disable();
2501                 Buttons[gr_screen.res][MEDALS_BUTTON].button.hide();
2502         }
2503
2504         Debrief_skip_popup_already_shown = 0;
2505
2506         Debrief_inited = 1;
2507 }
2508
2509 // --------------------------------------------------------------------------------------
2510 //      debrief_close()
2511 void debrief_close()
2512 {
2513         int i, idx;
2514
2515         SDL_assert(Debrief_inited);
2516
2517         // if the mission wasn't accepted, clear out my stats
2518         // we need to evaluate a little differently for multiplayer since the conditions for "accepting" 
2519         // are a little bit different
2520         if (Game_mode & GM_MULTIPLAYER) {
2521                 // if stats weren't accepted, backout my own stats
2522                 if (multi_debrief_stats_accept_code() != 1) {
2523                         if(MULTIPLAYER_MASTER){
2524                                 for(idx=0; idx<MAX_PLAYERS; idx++){
2525                                         if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) && (Net_players[idx].player != NULL)){
2526                                                 scoring_backout_accept(&Net_players[idx].player->stats);
2527                                         }
2528                                 }
2529                         } else {
2530                                 scoring_backout_accept( &Player->stats );
2531                         }
2532                 }
2533         } else {
2534                 // single player
2535                 if( !Debrief_accepted || !(Game_mode & GM_CAMPAIGN_MODE) ){
2536                         scoring_backout_accept( &Player->stats );
2537                 }
2538         }
2539
2540         // if dude passed the misson and accepted, reset his show skip popup flag
2541         if (Debrief_accepted) {
2542                 Player->show_skip_popup = 1;
2543         }
2544
2545         if (Num_debrief_lines) {
2546                 for (i=0; i<Num_debrief_lines; i++){
2547                         if (Text[i]){
2548                                 free(Text[i]);
2549                         }
2550                 }
2551         }
2552
2553         // clear out debrief info parsed from mission file
2554         mission_debrief_common_reset();
2555
2556         // unload the overlay bitmap
2557 #ifdef MAKE_FS1
2558         help_overlay_unload(DEBRIEFING_OVERLAY);
2559 #endif
2560
2561         // clear out award text 
2562         Debrief_award_text_num_lines = 0;
2563
2564         debrief_voice_unload_all();
2565         common_music_close();
2566         chatbox_close();
2567
2568 //      rank_bitmaps_release();
2569
2570         // unload bitmaps
2571         if (Background_bitmap >= 0){
2572                 bm_unload(Background_bitmap);
2573         }
2574
2575         if (Award_bg_bitmap >= 0){
2576                 bm_unload(Award_bg_bitmap);
2577         }
2578
2579         if (Rank_bitmap >= 0){
2580                 bm_unload(Rank_bitmap);
2581         }
2582
2583         if (Medal_bitmap >= 0){
2584                 bm_unload(Medal_bitmap);
2585         }
2586
2587         if (Badge_bitmap >= 0){
2588                 bm_unload(Badge_bitmap);
2589         }
2590
2591         if (Wings_bitmap >= 0) {
2592                 bm_unload(Wings_bitmap);
2593         }
2594         
2595         if (Crest_bitmap >= 0) {
2596                 bm_unload(Crest_bitmap);
2597         }
2598
2599 #ifdef MAKE_FS1
2600         if (Medal_text_bitmap >= 0) {
2601                 bm_unload(Medal_text_bitmap);
2602         }
2603
2604         if (Badge_text_bitmap >= 0) {
2605                 bm_unload(Badge_text_bitmap);
2606         }
2607
2608         if (Rank_text_bitmap >= 0) {
2609                 bm_unload(Rank_text_bitmap);
2610         }
2611 #endif
2612
2613         Debrief_ui_window.destroy();
2614         common_free_interface_palette();                // restore game palette
2615         show_stats_close();
2616
2617         if (Game_mode & GM_MULTIPLAYER){
2618                 multi_debrief_close();
2619         }
2620
2621         game_flush();
2622
2623         Stage_voice = -1;
2624
2625         Debrief_inited = 0;
2626 }
2627
2628 // handle keypresses in debriefing
2629 void debrief_do_keys(int new_k)
2630 {
2631         switch (new_k) {
2632                 case SDLK_TAB:
2633                         debrief_next_tab();
2634                         break;
2635
2636                 case KEY_SHIFTED | SDLK_TAB:
2637                         debrief_prev_tab();
2638                         break;
2639
2640                 case SDLK_ESCAPE: {
2641                         int pf_flags;
2642                         int choice;
2643
2644                         // multiplayer accept popup is a little bit different
2645                         if (Game_mode & GM_MULTIPLAYER) {               
2646                                 multi_debrief_esc_hit();
2647
2648                         // display the normal debrief popup
2649                         } else {
2650                                 if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2651                                         pf_flags = PF_BODY_BIG; // | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON;
2652                                         choice = popup(pf_flags, 3, POPUP_CANCEL, XSTR( "&Yes", 454), XSTR( "&No, retry later", 455), XSTR( "Accept this mission outcome?", 456));
2653                                         if (choice == 1) {  // accept and continue on
2654                                                 debrief_accept(0);
2655                                                 gameseq_post_event(GS_EVENT_MAIN_MENU);
2656                                         }
2657
2658                                         if (choice < 1)
2659                                                 break;
2660
2661                                 } else if (Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2662                                         // need to popup saying that mission was a failure and must be replayed
2663                                         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));
2664                                         if (choice <= 0)
2665                                                 break;
2666                                 }
2667
2668                                 // Return to Main Hall
2669                                 gameseq_post_event(GS_EVENT_END_GAME);
2670                         }
2671                 }
2672
2673                 default:
2674                         break;
2675         }       // end switch
2676 }
2677
2678 #ifndef MAKE_FS1
2679 // uuuuuugly
2680 void debrief_draw_award_text()
2681 {
2682         int start_y, curr_y, i, x, sw;
2683         int fh = gr_get_font_height();
2684         int field_width = (Medal_bitmap > 0) ? Debrief_award_text_width[gr_screen.res][DB_WITH_MEDAL] : Debrief_award_text_width[gr_screen.res][DB_WITHOUT_MEDAL];
2685
2686         // vertically centered within field
2687         start_y = Debrief_award_text_coords[gr_screen.res][1] + ((Debrief_award_text_coords[gr_screen.res][2] - (fh * Debrief_award_text_num_lines)) / 2);
2688         curr_y = start_y;
2689
2690         // draw the strings
2691         for (i=0; i<Debrief_award_text_num_lines; i++) {
2692                 gr_get_string_size(&sw, NULL, Debrief_award_text[i]);
2693                 x = (Medal_bitmap < 0) ? (Debrief_award_text_coords[gr_screen.res][0] + (field_width - sw) / 2) : Debrief_award_text_coords[gr_screen.res][0];
2694                 if (i==AWARD_TEXT_MAX_LINES-1) x += 7;                          // hack because of the shape of the box
2695                 gr_set_color_fast(&Color_white);
2696                 gr_string(x, curr_y, Debrief_award_text[i]);
2697
2698                 // adjust y pos, including a little extra between the "pairs"
2699                 curr_y += fh;
2700                 if ((i == 1) || (i == 3)) { 
2701                         curr_y += ((gr_screen.res == GR_640) ? 2 : 6);
2702                 }
2703         }
2704 }
2705
2706 // clears out text array so we dont have old award text showing up on new awards.
2707 void debrief_award_text_clear() {
2708         int i;
2709         
2710         Debrief_award_text_num_lines = 0;
2711         for (i=0; i<AWARD_TEXT_MAX_LINES; i++) {
2712                 //Debrief_award_text[i][0] = 0;
2713                 memset(Debrief_award_text[i], 0, sizeof(char)*AWARD_TEXT_MAX_LINE_LENGTH);
2714         }
2715 }
2716
2717 // this is the nastiest code I have ever written.  if you are modifying this, i feel bad for you.
2718 void debrief_add_award_text(char *str)
2719 {
2720         SDL_assert(Debrief_award_text_num_lines <= AWARD_TEXT_MAX_LINES);
2721         if (Debrief_award_text_num_lines > AWARD_TEXT_MAX_LINES) {
2722                 return;
2723         }
2724
2725         char *line2;
2726         int field_width = (Medal_bitmap > 0) ? Debrief_award_text_width[gr_screen.res][DB_WITH_MEDAL] : Debrief_award_text_width[gr_screen.res][DB_WITHOUT_MEDAL];
2727
2728         // copy in the line
2729         SDL_strlcpy(Debrief_award_text[Debrief_award_text_num_lines], str, AWARD_TEXT_MAX_LINE_LENGTH);
2730
2731         // maybe translate for displaying
2732         if (Lcl_gr) {
2733                 medals_translate_name(Debrief_award_text[Debrief_award_text_num_lines], AWARD_TEXT_MAX_LINE_LENGTH);
2734         } else if (Lcl_pl) {
2735                 medals_translate_name_pl(Debrief_award_text[Debrief_award_text_num_lines], AWARD_TEXT_MAX_LINE_LENGTH);
2736         }
2737
2738         Debrief_award_text_num_lines++;
2739
2740         // if its too long, split once ONLY
2741         // assumes text isnt > 2 lines, but this is a safe assumption due to the char limits of the ranks/badges/etc
2742         if (Debrief_award_text_num_lines < AWARD_TEXT_MAX_LINES) {
2743                 line2 = split_str_once(Debrief_award_text[Debrief_award_text_num_lines-1], field_width);
2744                 if (line2 != NULL) {
2745                         SDL_snprintf(Debrief_award_text[Debrief_award_text_num_lines], AWARD_TEXT_MAX_LINE_LENGTH, " %s", line2);  // indent a space
2746                 }
2747                 Debrief_award_text_num_lines++;         // leave blank line even if it all fits into 1
2748         }
2749 }
2750 #endif  // !MAKE_FS1: No text for FS1, it's all bitmaps
2751
2752 //      called once per frame to drive all the input reading and rendering
2753 void debrief_do_frame(float frametime)
2754 {
2755         int k=0, new_k=0;
2756         const char *please_wait_str = XSTR("Please Wait", 1242);
2757         int str_w, str_h;
2758         char buf[256];
2759
2760         SDL_assert(Debrief_inited);     
2761
2762         // first thing is to load the files
2763         if ( MULTIPLAYER_CLIENT && !Debrief_multi_stages_loaded ) {
2764                 // draw the background, etc
2765                 GR_MAYBE_CLEAR_RES(Background_bitmap);
2766                 if (Background_bitmap >= 0) {
2767                         gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2768                         gr_bitmap(0, 0);
2769                 }
2770
2771                 Debrief_ui_window.draw();
2772                 chatbox_render();
2773                 if ( Debrief_multi_loading_bitmap > -1 ){
2774                         gr_set_bitmap(Debrief_multi_loading_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2775                         gr_bitmap( Please_wait_coords[gr_screen.res][0], Please_wait_coords[gr_screen.res][1] );
2776                 }
2777
2778                 // draw "Please Wait"           
2779                 gr_set_color_fast(&Color_normal);
2780                 gr_set_font(FONT2);
2781                 gr_get_string_size(&str_w, &str_h, please_wait_str);
2782                 gr_string((gr_screen.max_w - str_w) / 2, (gr_screen.max_h - str_h) / 2, please_wait_str);
2783                 gr_set_font(FONT1);
2784
2785                 gr_flip();
2786
2787                 // make sure we run the debrief do frame
2788                 if (Game_mode & GM_MULTIPLAYER) {
2789                         multi_debrief_do_frame();
2790                 }
2791
2792                 // esc pressed?         
2793                 os_poll();      
2794                 int keypress = game_check_key();        
2795                 if(keypress == SDLK_ESCAPE){
2796                         // popup to leave
2797                         multi_quit_game(PROMPT_CLIENT);
2798                 }
2799
2800                 return;
2801         }
2802
2803         // if multiplayer client, and not loaded voice, then load it
2804         if ( MULTIPLAYER_CLIENT && !Debrief_multi_voice_loaded ) {
2805                 debrief_multi_fixup_stages();
2806                 debrief_voice_load_all();
2807                 Debrief_multi_voice_loaded = 1;
2808         }
2809
2810         if ( help_overlay_active(DEBRIEFING_OVERLAY) ) {
2811                 Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
2812                 Debrief_ui_window.set_ignore_gadgets(1);
2813         }
2814
2815         k = chatbox_process();
2816         if ( Game_mode & GM_NORMAL ) {
2817                 new_k = Debrief_ui_window.process(k);
2818         } else {
2819                 new_k = Debrief_ui_window.process(k, 0);
2820         }
2821
2822         if ( (k > 0) || (new_k > 0) || B1_JUST_RELEASED ) {
2823                 if ( help_overlay_active(DEBRIEFING_OVERLAY) ) {
2824                         help_overlay_set_state(DEBRIEFING_OVERLAY, 0);
2825                         Debrief_ui_window.set_ignore_gadgets(0);
2826                         //k = 0;
2827                         new_k = 0;
2828                 }
2829         }
2830
2831         if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
2832                 Debrief_ui_window.set_ignore_gadgets(0);
2833         }
2834
2835         // don't show pilot info popup by default
2836         Debrief_should_show_popup = 0;
2837
2838         // see if the mode has changed and handle it if so.
2839         if ( Current_mode != New_mode ) {
2840                 debrief_voice_stop();
2841                 Current_mode = New_mode;
2842                 Current_stage = -1;
2843                 New_stage = 0;
2844                 if (New_mode == DEBRIEF_TAB) {
2845                         Num_stages = 1;
2846                         Debrief_cue_voice = 0;
2847                         Stage_voice = -1;
2848                         if (Debrief_first_voice_flag) {
2849                                 Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY * 3);
2850                                 Debrief_first_voice_flag = 0;
2851                         }
2852                 } else {
2853                         Num_stages = DEBRIEF_NUM_STATS_PAGES;
2854                 }
2855         }
2856
2857         if ((Num_stages > 0) &&  (New_stage != Current_stage)) {
2858                 Current_stage = New_stage;
2859                 debrief_text_init();
2860         }
2861
2862         debrief_voice_play();
2863         common_music_do();
2864
2865         if (Game_mode & GM_MULTIPLAYER) {
2866                 multi_debrief_do_frame();
2867         }
2868
2869         // Now do all the rendering for the frame
2870         GR_MAYBE_CLEAR_RES(Background_bitmap);
2871         if (Background_bitmap >= 0) {
2872                 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2873                 gr_bitmap(0, 0);
2874         } 
2875
2876         // draw the damn awarded stuff, G
2877         if ( Award_active && (Award_bg_bitmap >= 0) ) {
2878                 gr_set_bitmap(Award_bg_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2879                 gr_bitmap(Debrief_award_wnd_coords[gr_screen.res][0], Debrief_award_wnd_coords[gr_screen.res][1]);
2880                 if (Rank_bitmap >= 0) {
2881                         gr_set_bitmap(Rank_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2882 #ifdef MAKE_FS1
2883                         gr_bitmap(Debrief_rank_coords[0], Debrief_rank_coords[1]);
2884 #else
2885                         gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2886 #endif
2887                 }
2888
2889                 if (Medal_bitmap >= 0) {
2890                         gr_set_bitmap(Medal_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2891                         gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2892                 }
2893
2894                 if (Badge_bitmap >= 0) {
2895                         gr_set_bitmap(Badge_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2896 #ifdef MAKE_FS1
2897                         gr_bitmap(Debrief_badge_coords[0], Debrief_badge_coords[1]);
2898 #else
2899                         gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2900 #endif
2901                 }
2902
2903                 if (Wings_bitmap >= 0) {
2904                         gr_set_bitmap(Wings_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2905 #ifdef MAKE_FS1
2906                         gr_bitmap(Debrief_badge_coords[0], Debrief_badge_coords[1]);
2907 #else
2908                         gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2909 #endif
2910                 }
2911
2912                 // this isn't used in FS1 but doesn't hurt to leave it
2913                 if (Crest_bitmap >= 0) {
2914                         gr_set_bitmap(Crest_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2915                         gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2916                 }
2917
2918                 //  draw medal/badge/rank labels
2919 #ifndef MAKE_FS1
2920                 debrief_draw_award_text();
2921 #else
2922                 if (Rank_text_bitmap >= 0) {
2923                         gr_set_bitmap(Rank_text_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2924                         gr_bitmap(Debrief_rank_text_coords[gr_screen.res][0], Debrief_rank_text_coords[gr_screen.res][1]);
2925                 }
2926
2927                 if (Medal_text_bitmap >= 0) {
2928                         gr_set_bitmap(Medal_text_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2929                         gr_bitmap(Debrief_medal_text_coords[gr_screen.res][0], Debrief_medal_text_coords[gr_screen.res][1]);
2930                 }
2931
2932                 if (Badge_text_bitmap >= 0) {
2933                         gr_set_bitmap(Badge_text_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2934                         gr_bitmap(Debrief_badge_text_coords[gr_screen.res][0], Debrief_badge_text_coords[gr_screen.res][1]);
2935                 }
2936 #endif
2937         }
2938         
2939         Debrief_ui_window.draw();
2940         debrief_redraw_pressed_buttons();
2941         Buttons[gr_screen.res][Current_mode].button.draw_forced(2);
2942         if (Recommend_active && (Current_mode != STATS_TAB)) {
2943                 Buttons[gr_screen.res][RECOMMENDATIONS].button.draw_forced(2);
2944         }
2945
2946         // draw the title of the mission
2947         gr_set_color_fast(&Color_bright_white);
2948         SDL_strlcpy(buf, The_mission.name, SDL_arraysize(buf));
2949         gr_force_fit_string(buf, 255, Debrief_title_coords[gr_screen.res][2]);
2950         gr_string(Debrief_title_coords[gr_screen.res][0], Debrief_title_coords[gr_screen.res][1], buf); 
2951
2952 #if !defined(NDEBUG) || defined(INTERPLAYQA)
2953         gr_set_color_fast(&Color_normal);
2954         gr_printf(Debrief_title_coords[gr_screen.res][0], Debrief_title_coords[gr_screen.res][1] - 10, NOX("[name: %s, mod: %s]"), Mission_filename, The_mission.modified);
2955 #endif
2956
2957         // draw the screen-specific text
2958         switch (Current_mode) {
2959                 case DEBRIEF_TAB:
2960                         if ( Num_debrief_stages <= 0 ) {
2961                                 gr_set_color_fast(&Color_white);
2962                                 SDL_assert( Game_current_mission_filename != NULL );
2963                                 gr_printf(Debrief_text_wnd_coords[gr_screen.res][0], Debrief_text_wnd_coords[gr_screen.res][1], XSTR( "No Debriefing for mission: %s", 458), Game_current_mission_filename);
2964
2965                         } else {
2966                                 debrief_render();
2967                         }
2968
2969                         break;
2970
2971                 case STATS_TAB:
2972                         debrief_stats_render();
2973                         break;
2974         } // end switch
2975
2976         if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
2977                 int w;
2978
2979                 gr_set_color_fast(&Color_red);
2980                 gr_get_string_size(&w, NULL, XSTR( "More", 459));
2981                 gr_printf(Debrief_text_wnd_coords[gr_screen.res][0] + Debrief_text_wnd_coords[gr_screen.res][2] / 2 - w / 2, Debrief_text_wnd_coords[gr_screen.res][1] + Debrief_text_wnd_coords[gr_screen.res][3], XSTR( "More", 459));
2982         }
2983
2984         debrief_render_stagenum();
2985         debrief_multi_list_draw();
2986
2987         // render some extra stuff in multiplayer
2988         if (Game_mode & GM_MULTIPLAYER) {
2989                 // render the chatbox last
2990                 chatbox_render();
2991
2992                 // draw tooltips
2993                 Debrief_ui_window.draw_tooltip();
2994
2995                 // render the status indicator for the voice system
2996                 multi_common_voice_display_status();
2997         }
2998
2999         // AL 3-6-98: Needed to move key reading here, since popups are launched from this code, and we don't
3000         //                                want to include the mouse pointer which is drawn in the flip
3001
3002         if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
3003                 debrief_check_buttons();
3004                 debrief_do_keys(new_k); 
3005         }
3006
3007         // blit help overlay if active
3008         help_overlay_maybe_blit(DEBRIEFING_OVERLAY);
3009
3010         gr_flip();
3011
3012         // dont let dude skip 3-09.  hack.      
3013         if(Game_mode & GM_CAMPAIGN_MODE){
3014                 if((Campaign.current_mission >= 0) && (Campaign.current_mission < MAX_CAMPAIGN_MISSIONS)){
3015                         if ((Campaign.missions[Campaign.current_mission].name != NULL) && !SDL_strcasecmp(Campaign.missions[Campaign.current_mission].name, "sm3-09.fs2")) {
3016                                 Debrief_skip_popup_already_shown = 1;
3017                         }
3018                 }
3019         }       
3020
3021         // maybe show skip mission popup
3022         if ((!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)) {
3023                 int popup_choice = popup(0, 3, XSTR("Do Not Skip This Mission", 1473),
3024                                                                                                  XSTR("Advance To The Next Mission", 1474),
3025                                                                                                  XSTR("Don't Show Me This Again", 1475),
3026                                                                                                  XSTR("You have failed this mission five times.  If you like, you may advance to the next mission.", 1472) );
3027                 switch (popup_choice) {
3028                 case 0:
3029                         // stay on this mission, so proceed to normal debrief
3030                         // in other words, do nothing.
3031                         break;
3032                 case 1:
3033                         // skip this mission
3034                         mission_campaign_skip_to_next();
3035                         gameseq_post_event(GS_EVENT_START_GAME);
3036                         break;
3037                 case 2:
3038                         // dont show this again
3039                         Player->show_skip_popup = 0;
3040                         break;
3041                 }
3042
3043                 Debrief_skip_popup_already_shown = 1;
3044         }
3045
3046         // check to see if we should be showing a pilot info popup in multiplayer (if a guy was double clicked)
3047         if ((Game_mode & GM_MULTIPLAYER) && Debrief_should_show_popup) {
3048                 SDL_assert((Multi_list_select >= 0) && (Multi_list_select < Multi_list_size));
3049                 multi_pinfo_popup(&Net_players[Multi_list[Multi_list_select].net_player_index]);
3050
3051                 Debrief_should_show_popup = 0;
3052         }
3053 }
3054
3055 void debrief_rebuild_player_list()
3056 {
3057         int i;
3058         net_player *np;
3059         debrief_multi_list_info *list;
3060
3061         Multi_list_size = 0;  // number of net players to choose from
3062
3063         for ( i=0; i<MAX_PLAYERS; i++ ) {
3064                 np = &Net_players[i];
3065                 // remember not to include the standalone.
3066                 if ( MULTI_CONNECTED((*np)) && !MULTI_STANDALONE((*np))){
3067                         list = &Multi_list[Multi_list_size++];
3068                         list->net_player_index = i;
3069                         SDL_strlcpy(list->callsign, np->player->callsign, SDL_arraysize(list->callsign));
3070                         
3071                         // make sure to leave some room to blit the team indicator
3072                         gr_force_fit_string(list->callsign, CALLSIGN_LEN - 1, Debrief_list_coords[gr_screen.res][2] - MULTI_LIST_TEAM_OFFSET);
3073                 }
3074         } // end for
3075 }
3076
3077 void debrief_handle_player_drop()
3078 {
3079         debrief_rebuild_player_list();
3080 }
3081
3082 void debrief_disable_accept()
3083 {
3084 }
3085