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