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