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