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