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