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