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