2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/MissionUI/MissionDebrief.cpp $
15 * C module for running the debriefing
18 * Revision 1.13 2005/08/12 08:52:32 taylor
19 * various GCC4 warning fixes
21 * Revision 1.12 2005/03/29 02:18:47 taylor
22 * Various 64-bit platform fixes
23 * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
24 * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
25 * Streaming audio support (big thanks to Pierre Willenbrock!!)
26 * Removed dependance on strings.tbl for FS1 since we don't actually need it now
28 * Revision 1.11 2004/09/20 01:31:44 theoddone33
31 * Revision 1.10 2004/07/04 11:39:06 taylor
32 * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
34 * Revision 1.9 2003/08/03 16:10:29 taylor
35 * cleanup; compile warning fixes
37 * Revision 1.8 2003/06/03 04:00:40 taylor
38 * Polish language support (Janusz Dziemidowicz)
40 * Revision 1.7 2003/05/25 02:30:43 taylor
43 * Revision 1.6 2002/07/13 06:46:48 theoddone33
46 * Revision 1.5 2002/06/09 04:41:23 relnev
47 * added copyright header
49 * Revision 1.4 2002/06/02 04:26:34 relnev
52 * Revision 1.3 2002/05/26 22:06:17 relnev
53 * makefile: disable stand_gui for now.
55 * rest: staticize some globals
57 * Revision 1.2 2002/05/07 03:16:46 theoddone33
58 * The Great Newline Fix
60 * Revision 1.1.1.1 2002/05/03 03:28:10 root
64 * 57 10/29/99 10:40p Jefff
65 * hack to make german medal names display without actually changing them
67 * 56 10/13/99 3:26p Jefff
68 * fixed unnumbered XSTRs
70 * 55 10/06/99 10:28a Jefff
73 * 54 9/30/99 5:57p Jefff
74 * show upsell at end of campaign in OEM builds
76 * 53 9/15/99 3:42a Jefff
79 * 52 9/14/99 4:35a Dave
80 * Argh. Added all kinds of code to handle potential crashes in debriefing
83 * 51 9/14/99 3:26a Dave
84 * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
85 * respawn-too-early problem. Made a few crash points safe.
87 * 50 9/14/99 12:51a Jefff
89 * 49 9/13/99 6:01p Jefff
90 * fixed wrong promotion voice mapping for sm1-08
92 * 48 9/13/99 11:15a Jefff
93 * clear out award text bug fixed
95 * 47 9/13/99 12:17p Andsager
96 * Fix traitor debrief not playinf for FS2. Don't append _3 or _1 as in
99 * 46 9/07/99 9:35p Jefff
100 * fixed bug where award text was not getting cleared properly between
103 * 45 9/07/99 6:56p Jefff
104 * a few adjustments to loop detection
106 * 44 9/07/99 1:54p Jefff
107 * skip mission cleanup
109 * 43 9/06/99 9:45p Jefff
110 * skip mission support
112 * 42 9/06/99 6:38p Dave
113 * Improved CD detection code.
115 * 41 9/03/99 1:32a Dave
116 * CD checking by act. Added support to play 2 cutscenes in a row
117 * seamlessly. Fixed super low level cfile bug related to files in the
118 * root directory of a CD. Added cheat code to set campaign mission # in
121 * 40 9/02/99 3:45p Jefff
122 * forgot to remove some debug code. doh.
124 * 39 9/02/99 3:41p Jefff
125 * changed badge voice handling to be similar to promotion voice handling
127 * 38 9/01/99 4:41p Jefff
128 * fixed stoopid text color bug
130 * 37 8/31/99 11:54a Jefff
131 * minor debrief music tweak
133 * 36 8/27/99 9:57a Dave
134 * Enabled standard cheat codes. Allow player to continue in a campaing
135 * after using cheat codes.
137 * 35 8/27/99 12:04a Dave
138 * Campaign loop screen.
140 * 34 8/26/99 8:49p Jefff
141 * Updated medals screen and about everything that ever touches medals in
142 * one way or another. Sheesh.
144 * 33 8/20/99 4:20p Jefff
145 * hack for choosing the correct promotion voice
147 * 32 8/16/99 4:05p Dave
148 * Big honking checkin.
150 * 31 8/16/99 9:49a Jefff
151 * mission title length fix in multi
153 * 30 8/11/99 5:33p Jefff
154 * added 3rd debrief music track
156 * 29 8/10/99 7:28p Jefff
157 * shuffled some text around
159 * 28 8/04/99 5:36p Andsager
160 * Show upsell screens at end of demo campaign before returning to main
163 * 27 8/04/99 2:07p Jefff
164 * mission title no longer overwrites popup
166 * 26 8/02/99 5:37p Jefff
168 * 25 8/02/99 4:52p Jefff
169 * negative feedback sound when recommendations button pressed and
172 * 24 7/21/99 6:21p Jefff
173 * added hotkeys to the "you cannot accept" popup
175 * 23 6/15/99 12:04p Anoop
176 * Added a warning for running out of debrief text lines.
178 * 22 6/09/99 2:17p Dave
179 * Fixed up pleasewait bitmap rendering.
181 * 21 6/01/99 6:07p Dave
182 * New loading/pause/please wait bar.
184 * 20 5/22/99 6:05p Dave
185 * Fixed a few localization # problems.
187 * 19 5/22/99 5:35p Dave
188 * Debrief and chatbox screens. Fixed small hi-res HUD bug.
190 * 18 3/20/99 3:47p Andsager
191 * Fix crash with no mission loop description.
193 * 17 2/23/99 2:29p Dave
194 * First run of oldschool dogfight mode.
196 * 16 2/21/99 6:01p Dave
197 * Fixed standalone WSS packets.
199 * 15 2/11/99 3:08p Dave
200 * PXO refresh button. Very preliminary squad war support.
202 * 14 1/30/99 5:08p Dave
203 * More new hi-res stuff.Support for nice D3D textures.
205 * 13 1/29/99 2:08a Dave
206 * Fixed beam weapon collisions with players. Reduced size of scoring
207 * struct for multiplayer. Disabled PXO.
209 * 12 1/14/99 5:15p Neilk
210 * changed credits, command debrief interfaces to high resolution support
212 * 11 1/13/99 2:11p Andsager
213 * change default debriefing string text
215 * 10 12/17/98 4:50p Andsager
216 * Added debrief_assemble_optional_mission_popup_text() for single and
219 * 9 12/12/98 3:17p Andsager
220 * Clean up mission eval, goal, event and mission scoring.
222 * 8 12/10/98 10:19a Andsager
223 * Fix mission loop assert
225 * 7 12/10/98 9:59a Andsager
226 * Fix some bugs with mission loops
228 * 6 12/09/98 1:56p Andsager
229 * Initial checkin of mission loop
231 * 5 11/05/98 4:18p Dave
232 * First run nebula support. Beefed up localization a bit. Removed all
233 * conditional compiles for foreign versions. Modified mission file
236 * 4 10/23/98 3:51p Dave
237 * Full support for tstrings.tbl and foreign languages. All that remains
238 * is to make it active in Fred.
240 * 3 10/13/98 9:28a Dave
241 * Started neatening up freespace.h. Many variables renamed and
242 * reorganized. Added AlphaColors.[h,cpp]
244 * 2 10/07/98 10:53a Dave
247 * 1 10/07/98 10:49a Dave
249 * 178 9/17/98 3:08p Dave
250 * PXO to non-pxo game warning popup. Player icon stuff in create and join
251 * game screens. Upped server count refresh time in PXO to 35 secs (from
254 * 177 7/07/98 1:46p Dave
255 * Fixed nasty debriefing badge/promotion bug. Added extra physics info
258 * 175 6/09/98 10:31a Hoffoss
259 * Created index numbers for all xstr() references. Any new xstr() stuff
260 * added from here on out should be added to the end if the list. The
261 * current list count can be found in FreeSpace.cpp (search for
264 * 174 6/07/98 3:26p Lawrance
265 * Fix bug with cut-off popup text
267 * 173 6/05/98 9:54a Lawrance
270 * 172 6/01/98 11:43a John
271 * JAS & MK: Classified all strings for localization.
273 * 171 5/27/98 1:24p Allender
274 * make targeting dots work (as well as other targeting features) properly
275 * in multiplayer. Don't query for CD when entering debrief in
278 * 170 5/26/98 11:10a Lawrance
279 * Fix bug where window controls get disabled when F1 pressed twice
281 * 169 5/24/98 12:55a Mike
282 * Prevent Assert() when no debriefing text for a stage.
284 * 168 5/23/98 10:38p Lawrance
285 * Avoid doing a cfile refresh when running debug
287 * 167 5/23/98 6:49p Lawrance
288 * Fix problems with refreshing the file list when a CD is inserted
290 * 166 5/21/98 6:57p Lawrance
291 * Don't prompt for the CD if voice not found
293 * 165 5/20/98 2:24a Dave
294 * Fixed server side voice muting. Tweaked multi debrief/endgame
295 * sequencing a bit. Much friendlier for stats tossing/accepting now.
297 * 164 5/19/98 8:35p Dave
298 * Revamp PXO channel listing system. Send campaign goals/events to
299 * clients for evaluation. Made lock button pressable on all screens.
301 * 163 5/19/98 11:13a Hoffoss
302 * Fixed bug where wrong wings award was being displayed in debriefing.
304 * 162 5/19/98 12:28a Mike
307 * 161 5/18/98 8:08p Hoffoss
308 * Moved placement of 'More' text.
310 * 160 5/18/98 3:50p Dan
311 * AL: Pick correct traitor debriefing voice file
313 * 159 5/17/98 6:32p Dave
314 * Make sure clients/servers aren't kicked out of the debriefing when team
315 * captains leave a game. Fixed chatbox off-by-one error. Fixed image
316 * xfer/pilot info popup stuff.
318 * 158 5/16/98 9:14p Allender
319 * fix scoring ckise fir training missions to actually count medals, but
320 * nothing else. Code used to Assert when wings were granted then taken
321 * away because they were actually never granted in scoring structure
323 * 157 5/15/98 5:15p Dave
324 * Fix a standalone resetting bug.Tweaked PXO interface. Display captaincy
325 * status for team vs. team. Put in asserts to check for invalid team vs.
328 * 156 5/15/98 4:36p Allender
329 * fixed minor bug with wings
331 * 155 5/15/98 4:12p Allender
332 * removed redbook code. Put back in ingame join timer. Major fixups for
333 * stats in multiplayer. Pass correct score, medals, etc when leaving
334 * game. Be sure clients display medals, badges, etc.
336 * 154 5/15/98 2:25p Jasen
337 * temporarily disable granting of promotion and badges for clients
339 * 153 5/15/98 10:57a Allender
340 * fixed client side debriefings
342 * 152 5/15/98 10:36a Dave
343 * Removed 2 bogus bitmap drawing Int3()'s
345 * 151 5/14/98 2:44p Hoffoss
346 * Added wings awarding to debrief screen.
348 * 150 5/13/98 9:11p Lawrance
349 * Make 'replay mission' popup warn users about the loss of mission stats.
354 #include "missiondebrief.h"
355 #include "missionbriefcommon.h"
356 #include "missionscreencommon.h"
357 #include "missiongoals.h"
358 #include "missionpause.h"
359 #include "freespace.h"
360 #include "gamesequence.h"
368 #include "audiostr.h"
371 #include "contexthelp.h"
377 #include "multimsgs.h"
378 #include "multiutil.h"
379 #include "multiteamselect.h"
381 #include "eventmusic.h"
385 #include "multi_pinfo.h"
386 #include "contexthelp.h"
387 #include "multi_kick.h"
388 #include "multi_campaign.h"
389 #include "alphacolors.h"
390 #include "localize.h"
391 #include "multi_endgame.h"
394 #define MAX_TOTAL_DEBRIEF_LINES 200
396 #define TEXT_TYPE_NORMAL 1
397 #define TEXT_TYPE_RECOMMENDATION 2
399 #define DEBRIEF_NUM_STATS_PAGES 4
400 #define DEBRIEF_MISSION_STATS 0
401 #define DEBRIEF_MISSION_KILLS 1
402 #define DEBRIEF_ALLTIME_STATS 2
403 #define DEBRIEF_ALLTIME_KILLS 3
405 // 3rd coord is max width in pixels
406 int Debrief_title_coords[GR_NUM_RESOLUTIONS][3] = {
419 int Debrief_text_wnd_coords[GR_NUM_RESOLUTIONS][4] = {
432 int Debrief_text_x2[GR_NUM_RESOLUTIONS] = {
437 int Debrief_stage_info_coords[GR_NUM_RESOLUTIONS][2] = {
450 int Debrief_more_coords[GR_NUM_RESOLUTIONS][2] = {
463 #define MULTI_LIST_TEAM_OFFSET 16
465 int Debrief_multi_list_team_max_display[GR_NUM_RESOLUTIONS] = {
470 int Debrief_list_coords[GR_NUM_RESOLUTIONS][4] = {
479 int Debrief_award_wnd_coords[GR_NUM_RESOLUTIONS][2] = {
492 int Debrief_award_coords[GR_NUM_RESOLUTIONS][2] = {
506 int Debrief_rank_coords[2] = {
510 int Debrief_badge_coords[2] = {
516 // 0=x, 1=y, 2=width of the field
517 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][3] = {
526 // 0=x, 1=y, 2=height of the field
527 int Debrief_award_text_coords[GR_NUM_RESOLUTIONS][3] = {
536 // the medal text in FS1 is a bitmap
537 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][2] = {
546 int Debrief_rank_text_coords[GR_NUM_RESOLUTIONS][2] = {
555 int Debrief_badge_text_coords[GR_NUM_RESOLUTIONS][2] = {
566 // 1 = without medal (text will use medal space)
567 #define DB_WITH_MEDAL 0
568 #define DB_WITHOUT_MEDAL 1
569 int Debrief_award_text_width[GR_NUM_RESOLUTIONS][2] = {
578 char *Debrief_single_name[GR_NUM_RESOLUTIONS] = {
579 "DebriefSingle", // GR_640
580 "2_DebriefSingle" // GR_1024
582 char *Debrief_multi_name[GR_NUM_RESOLUTIONS] = {
583 "DebriefMulti", // GR_640
584 "2_DebriefMulti" // GR_1024
586 char *Debrief_mask_name[GR_NUM_RESOLUTIONS] = {
587 "Debrief-m", // GR_640
588 "2_Debrief-m" // GR_1024
591 #define NUM_BUTTONS 18
594 #define DEBRIEF_TAB 0
596 #define TEXT_SCROLL_UP 2
597 #define TEXT_SCROLL_DOWN 3
598 #define REPLAY_MISSION 4
599 #define RECOMMENDATIONS 5
600 #define FIRST_STAGE 6
604 #define MULTI_PINFO_POPUP 10
605 #define MULTI_KICK 11
606 #define MEDALS_BUTTON 12
607 #define PLAYER_SCROLL_UP 13
608 #define PLAYER_SCROLL_DOWN 14
609 #define HELP_BUTTON 15
610 #define OPTIONS_BUTTON 16
611 #define ACCEPT_BUTTON 17
616 char* Debrief_loading_bitmap_fname[GR_NUM_RESOLUTIONS] = {
617 "PleaseWait", // GR_640
618 "2_PleaseWait" // GR_1024
624 char text[NAME_LENGTH+1]; // name of ship type with a colon
625 int num; // how many ships of this type player has killed
626 } debrief_stats_kill_info;
629 int net_player_index; // index into Net_players[] array
630 int rank_bitmap; // bitmap id for rank
631 char callsign[CALLSIGN_LEN];
632 } debrief_multi_list_info;
634 static ui_button_info Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
637 ui_button_info("DB_00", 0, 2, -1, -1, 0), // debriefing
638 ui_button_info("DB_01", 0, 20, -1, -1, 1), // statistics
639 ui_button_info("DB_02", 0, 195, -1, -1, 2), // scroll stats up
640 ui_button_info("DB_03", 0, 232, -1, -1, 3), // scroll stats down
641 ui_button_info("DB_04", 24, 424, -1, -1, 4), // replay mission
642 ui_button_info("DB_05", 30, 451, -1, -1, 5), // recommendations
643 ui_button_info("DB_06", 211, 445, -1, -1, 6), // first page
644 ui_button_info("DB_07", 234, 445, -1, -1, 7), // prev page
645 ui_button_info("DB_08", 259, 445, -1, -1, 8), // next page
646 ui_button_info("DB_09", 283, 445, -1, -1, 9), // last page
647 ui_button_info("DB_21", 441, 384, -1, -1, 21), // pilot info
648 ui_button_info("DB_25", 511, 384, -1, -1, 25), // kick
649 ui_button_info("DB_15", 604, 224, -1, -1, 15), // medals
650 ui_button_info("DB_16", 615, 329, -1, -1, 16), // scroll pilots up
651 ui_button_info("DB_17", 615, 371, -1, -1, 17), // scroll pilots down
652 ui_button_info("DB_10", 469, 428, -1, -1, 10), // help
653 ui_button_info("DB_11", 447, 452, -1, -1, 11), // options
654 ui_button_info("DB_12", 562, 410, -1, -1, 12), // accept
656 ui_button_info("DB_00", 6, 1, 37, 7, 0), // debriefing
657 ui_button_info("DB_01", 6, 21, 37, 23, 1), // statistics
658 ui_button_info("DB_02", 1, 195, -1, -1, 2), // scroll stats up
659 ui_button_info("DB_03", 1, 236, -1, -1, 3), // scroll stats down
660 ui_button_info("DB_04", 1, 428, 49, 447, 4), // replay mission
661 ui_button_info("DB_05", 17, 459, 49, 464, 5), // recommendations
662 ui_button_info("DB_06", 323, 454, -1, -1, 6), // first page
663 ui_button_info("DB_07", 348, 454, -1, -1, 7), // prev page
664 ui_button_info("DB_08", 372, 454, -1, -1, 8), // next page
665 ui_button_info("DB_09", 396, 454, -1, -1, 9), // last page
666 ui_button_info("DB_10", 441, 384, 433, 413, 10), // pilot info
667 ui_button_info("DB_11", 511, 384, 510, 413, 11), // kick
668 ui_button_info("DB_12", 613, 226, -1, -1, 12), // medals
669 ui_button_info("DB_13", 615, 329, -1, -1, 13), // scroll pilots up
670 ui_button_info("DB_14", 615, 371, -1, -1, 14), // scroll pilots down
671 ui_button_info("DB_15", 538, 431, 500, 440, 15), // help
672 ui_button_info("DB_16", 538, 455, 479, 464, 16), // options
673 ui_button_info("DB_17", 573, 432, 572, 413, 17), // accept
677 ui_button_info("2_DB_00", 10, 1, 59, 12, 0), // debriefing
678 ui_button_info("2_DB_01", 10, 33, 59, 37, 1), // statistics
679 ui_button_info("2_DB_02", 1, 312, -1, -1, 2), // scroll stats up
680 ui_button_info("2_DB_03", 1, 378, -1, -1, 3), // scroll stats down
681 ui_button_info("2_DB_04", 1, 685, 79, 715, 4), // replay mission
682 ui_button_info("2_DB_05", 28, 735, 79, 743, 5), // recommendations
683 ui_button_info("2_DB_06", 517, 726, -1, -1, 6), // first page
684 ui_button_info("2_DB_07", 556, 726, -1, -1, 7), // prev page
685 ui_button_info("2_DB_08", 595, 726, -1, -1, 8), // next page
686 ui_button_info("2_DB_09", 633, 726, -1, -1, 9), // last page
687 ui_button_info("2_DB_10", 706, 615, 700, 661, 10), // pilot info
688 ui_button_info("2_DB_11", 817, 615, 816, 661, 11), // kick
689 ui_button_info("2_DB_12", 981, 362, -1, -1, 12), // medals
690 ui_button_info("2_DB_13", 984, 526, -1, -1, 13), // scroll pilots up
691 ui_button_info("2_DB_14", 984, 594, -1, -1, 14), // scroll pilots down
692 ui_button_info("2_DB_15", 861, 689, 801, 705, 15), // help
693 ui_button_info("2_DB_16", 861, 728, 777, 744, 16), // options
694 ui_button_info("2_DB_17", 917, 692, 917, 692, 17), // accept
700 #define NUM_DEBRIEF_TEXT 10
701 #define MP_TEXT_INDEX_1 4
702 #define MP_TEXT_INDEX_2 5
703 #define MP_TEXT_INDEX_3 6
704 UI_XSTR Debrief_strings[GR_NUM_RESOLUTIONS][NUM_DEBRIEF_TEXT] = {
706 { "Debriefing", 804, 37, 7, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][DEBRIEF_TAB].button },
707 { "Statistics", 1333, 37, 26, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][STATS_TAB].button },
708 { "Replay Mission", 444, 49, 447, UI_XSTR_COLOR_PINK, -1, &Buttons[0][REPLAY_MISSION].button },
709 { "Recommendations", 1334, 49, 464, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][RECOMMENDATIONS].button },
710 { "Pilot", 1310, 433, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_PINFO_POPUP].button },
711 { "Info", 1311, 433, 423, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_PINFO_POPUP].button },
712 { "Kick", 1266, 510, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_KICK].button },
713 { "Help", 928, 500, 440, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][HELP_BUTTON].button },
714 { "Options", 1036, 479, 464, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][OPTIONS_BUTTON].button },
715 { "Accept", 1035, 572, 413, UI_XSTR_COLOR_PINK, -1, &Buttons[0][ACCEPT_BUTTON].button },
718 { "Debriefing", 804, 59, 12, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][DEBRIEF_TAB].button },
719 { "Statistics", 1333, 59, 47, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][STATS_TAB].button },
720 { "Replay Mission", 444, 79, 715, UI_XSTR_COLOR_PINK, -1, &Buttons[1][REPLAY_MISSION].button },
721 { "Recommendations", 1334, 79, 743, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][RECOMMENDATIONS].button },
722 { "Pilot", 1310, 700, 661, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_PINFO_POPUP].button },
723 { "Info", 1311, 700, 679, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_PINFO_POPUP].button },
724 { "Kick", 1266, 816, 661, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_KICK].button },
725 { "Help", 928, 801, 705, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][HELP_BUTTON].button },
726 { "Options", 1036, 780, 744, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][OPTIONS_BUTTON].button },
727 { "Accept", 1035, 917, 672, UI_XSTR_COLOR_PINK, -1, &Buttons[1][ACCEPT_BUTTON].button },
733 char Debrief_current_callsign[CALLSIGN_LEN+10];
734 player *Debrief_player;
736 static UI_WINDOW Debrief_ui_window;
737 static UI_BUTTON List_region;
738 static int Background_bitmap; // bitmap for the background of the debriefing
739 static int Award_bg_bitmap;
740 static int Debrief_multi_loading_bitmap;
741 static int Rank_bitmap;
742 static int Medal_bitmap;
743 static int Badge_bitmap;
744 static int Wings_bitmap;
745 static int Crest_bitmap;
747 static int Rank_text_bitmap;
748 static int Medal_text_bitmap;
749 static int Badge_text_bitmap;
752 static int Debrief_accepted;
753 static int Turned_traitor;
754 static int Must_replay_mission;
756 static int Current_mode;
758 static int Recommend_active;
759 static int Award_active;
760 static int Text_offset;
761 static int Num_text_lines = 0;
762 static int Num_debrief_lines = 0;
763 static int Text_type[MAX_TOTAL_DEBRIEF_LINES];
764 static char *Text[MAX_TOTAL_DEBRIEF_LINES];
766 static int Debrief_inited = 0;
767 static int New_stage;
768 static int Current_stage;
769 static int Num_stages;
770 static int Num_debrief_stages;
771 static int Stage_voice;
773 static int Multi_list_size;
774 static int Multi_list_offset;
776 int Debrief_multi_stages_loaded = 0;
777 int Debrief_multi_voice_loaded = 0;
779 // static int Debrief_voice_ask_for_cd;
781 // voice id's for debriefing text
782 static int Debrief_voices[MAX_DEBRIEF_STAGES];
784 #define DEBRIEF_VOICE_DELAY 400 // time to delay voice playback when a new stage starts
785 static int Debrief_cue_voice; // timestamp to cue the playback of the voice
786 static int Debrief_first_voice_flag = 1; // used to delay the first voice playback extra long
788 // pointer used for getting to debriefing information
789 debriefing Traitor_debriefing; // used when player is a traitor
791 // pointers to the active stages for this debriefing
792 static debrief_stage *Debrief_stages[MAX_DEBRIEF_STAGES];
793 static debrief_stage Promotion_stage, Badge_stage;
794 static debrief_stats_kill_info Debrief_stats_kills[MAX_SHIP_TYPES];
795 static debrief_multi_list_info Multi_list[MAX_PLAYERS];
796 int Multi_list_select;
798 // flag indicating if we should display info for the given player (in multiplayer)
799 int Debrief_should_show_popup = 1;
801 // already shown skip mission popup?
802 static int Debrief_skip_popup_already_shown = 0;
804 void debrief_text_init();
805 void debrief_accept(int ok_to_post_start_game_event = 1);
806 void debrief_kick_selected_player();
809 // promotion voice selection stuff
810 #define NUM_VOLITION_CAMPAIGNS 1
812 char campaign_name[32];
816 v_campaign Volition_campaigns[NUM_VOLITION_CAMPAIGNS] = {
818 BUILTIN_CAMPAIGN, // the only campaign for now, but this leaves room for a mission pack
819 35 // make sure this is equal to the number of missions you gave in the corresponding Debrief_promotion_voice_mapping
823 // data for which voice goes w/ which mission
824 typedef struct voice_map {
825 char mission_file[32];
829 voice_map Debrief_promotion_voice_mapping[NUM_VOLITION_CAMPAIGNS][MAX_CAMPAIGN_MISSIONS] = {
830 { // FreeSpace2 campaign
862 { "SM3-10.fs2", 9 }, // no debriefing for 3-10
864 { "loop1-1.fs2", 4 },
865 { "loop1-2.fs2", 4 },
866 { "loop1-3.fs2", 5 },
867 { "loop2-1.fs2", 4 },
872 #define DB_AWARD_WINGS 0
873 #define DB_AWARD_MEDAL 1
875 #define DB_AWARD_RANK 2
876 #define DB_AWARD_BADGE 3
877 #define DB_AWARD_BG 4
878 static char* Debrief_award_filename[GR_NUM_RESOLUTIONS][5] = {
895 #define DB_AWARD_SOC 2
896 #define DB_AWARD_RANK 3
897 #define DB_AWARD_BADGE 4
898 #define DB_AWARD_BG 5
899 static char* Debrief_award_filename[GR_NUM_RESOLUTIONS][6] = {
919 #define AWARD_TEXT_MAX_LINES 5
920 #define AWARD_TEXT_MAX_LINE_LENGTH 128
921 char Debrief_award_text[AWARD_TEXT_MAX_LINES][AWARD_TEXT_MAX_LINE_LENGTH];
922 int Debrief_award_text_num_lines = 0;
926 // prototypes, you know you love 'em
927 void debrief_add_award_text(char *str);
928 void debrief_award_text_clear();
933 char *debrief_tooltip_handler(char *str)
935 if (!stricmp(str, NOX("@.Medal"))) {
937 return XSTR( "Medal", 435);
940 } else if (!stricmp(str, NOX("@.Rank"))) {
942 return XSTR( "Rank", 436);
945 } else if (!stricmp(str, NOX("@.Badge"))) {
947 return XSTR( "Badge", 437);
950 } else if (!stricmp(str, NOX("@Medal"))) {
951 if (Medal_bitmap >= 0){
952 return Medals[Player->stats.m_medal_earned].name;
955 } else if (!stricmp(str, NOX("@Rank"))) {
956 if (Rank_bitmap >= 0){
957 return Ranks[Promoted].name;
960 } else if (!stricmp(str, NOX("@Badge"))) {
961 if (Badge_bitmap >= 0){
962 return Medals[Badge_index[Player->stats.m_badge_earned]].name;
969 // initialize the array of handles to the different voice streams
970 void debrief_voice_init()
974 for (i=0; i<MAX_DEBRIEF_STAGES; i++) {
975 Debrief_voices[i] = -1;
979 void debrief_load_voice_file(int voice_num, char *name)
981 int load_attempts = 0;
984 if ( load_attempts++ > 5 ) {
988 Debrief_voices[voice_num] = audiostream_open( name, ASF_VOICE );
989 if ( Debrief_voices[voice_num] >= 0 ) {
993 // Don't bother to ask for the CD in multiplayer
994 if ( Game_mode & GM_MULTIPLAYER ) {
998 // couldn't load voice, ask user to insert CD (if necessary)
1000 // if ( Debrief_voice_ask_for_cd ) {
1001 // if ( game_do_cd_check() == 0 ) {
1002 // Debrief_voice_ask_for_cd = 0;
1009 // open and pre-load the stream buffers for the different voice streams
1010 void debrief_voice_load_all()
1014 // Debrief_voice_ask_for_cd = 1;
1016 for ( i=0; i<Num_debrief_stages; i++ ) {
1017 if ( strlen(Debrief_stages[i]->voice) <= 0 ) {
1020 if ( strnicmp(Debrief_stages[i]->voice, NOX("none"), 4) ) {
1021 debrief_load_voice_file(i, Debrief_stages[i]->voice);
1022 // Debrief_voices[i] = audiostream_open(Debrief_stages[i]->voice, ASF_VOICE);
1027 // close all the briefing voice streams
1028 void debrief_voice_unload_all()
1032 for ( i=0; i<MAX_DEBRIEF_STAGES; i++ ) {
1033 if ( Debrief_voices[i] != -1 ) {
1034 audiostream_close_file(Debrief_voices[i], 0);
1035 Debrief_voices[i] = -1;
1040 // start playback of the voice for a particular briefing stage
1041 void debrief_voice_play()
1043 if (!Briefing_voice_enabled || (Current_mode != DEBRIEF_TAB)){
1047 // no more stages? We are done then.
1048 if (Stage_voice >= Num_debrief_stages){
1052 // if in delayed start, see if delay has elapsed and start voice if so
1053 if (Debrief_cue_voice) {
1054 if (!timestamp_elapsed(Debrief_cue_voice)){
1058 Stage_voice++; // move up to next voice
1059 if ((Stage_voice < Num_debrief_stages) && (Debrief_voices[Stage_voice] >= 0)) {
1060 audiostream_play(Debrief_voices[Stage_voice], Master_voice_volume, 0);
1061 Debrief_cue_voice = 0; // indicate no longer in delayed start checking
1067 // see if voice is still playing. If so, do nothing yet.
1068 if ((Stage_voice >= 0) && audiostream_is_playing(Debrief_voices[Stage_voice])){
1072 // set voice to play in a little while from now.
1073 Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY);
1076 // stop playback of the voice for a particular briefing stage
1077 void debrief_voice_stop()
1079 if ((Stage_voice < 0) || (Stage_voice > Num_debrief_stages) || (Debrief_voices[Stage_voice] < 0))
1082 audiostream_stop(Debrief_voices[Stage_voice]); // stream is automatically rewound
1086 // function to deal with inserting possible promition and badge stages into the debriefing
1088 void debrief_multi_fixup_stages()
1092 // possibly insert the badge stage first, them the promotion stage since they are
1093 // inserted at the front of the debrief stages.
1094 if ( Badge_bitmap >= 0 ) {
1095 // move all stages forward one. Don't
1096 for ( i = Num_debrief_stages; i > 0; i-- ) {
1097 Debrief_stages[i] = Debrief_stages[i-1];
1099 Debrief_stages[0] = &Badge_stage;
1100 Num_debrief_stages++;
1103 if ( Promoted >= 0) {
1104 // move all stages forward one
1105 for ( i = Num_debrief_stages; i > 0; i-- ) {
1106 Debrief_stages[i] = Debrief_stages[i-1];
1108 Debrief_stages[0] = &Promotion_stage;
1109 Num_debrief_stages++;
1114 // function called from multiplayer clients to set up the debriefing information for them
1115 // (sent from the server).
1116 void debrief_set_multi_clients( int stage_count, int active_stages[] )
1120 // set up the right briefing for this guy
1121 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
1122 Debriefing = &Debriefings[Net_player->p_info.team];
1124 Debriefing = &Debriefings[0];
1127 // see if this client was promoted -- if so, then add the first stage.
1128 Num_debrief_stages = 0;
1130 // set the pointers to the debriefings for this client
1131 for (i = 0; i < stage_count; i++) {
1132 Debrief_stages[Num_debrief_stages++] = &Debriefing->stages[active_stages[i]];
1135 Debrief_multi_stages_loaded = 1;
1138 // evaluate all stages for all teams. Server of a multiplayer game will have to send that
1139 // information to all clients after leaving this screen.
1140 void debrief_multi_server_stuff()
1142 debriefing *debriefp;
1144 int stage_active[MAX_TEAMS][MAX_DEBRIEF_STAGES], *stages[MAX_TEAMS];
1145 int i, j, num_stages, stage_count[MAX_TEAMS];
1147 memset( stage_active, 0, sizeof(stage_active) );
1149 for (i=0; i<Num_teams; i++) {
1150 debriefp = &Debriefings[i];
1152 stages[i] = stage_active[i];
1153 for (j=0; j<debriefp->num_stages; j++) {
1154 if ( eval_sexp(debriefp->stages[j].formula) ) {
1155 stage_active[i][num_stages] = j;
1160 stage_count[i] = num_stages;
1163 // if we're in campaign mode, evaluate campaign stuff
1164 if (Netgame.campaign_mode == MP_CAMPAIGN) {
1165 multi_campaign_eval_debrief();
1168 // send the information to all clients.
1169 send_debrief_info( stage_count, stages );
1173 // --------------------------------------------------------------------------------------
1174 // debrief_set_stages_and_multi_stuff()
1176 // Set up the active stages for this debriefing
1178 // returns: number of active debriefing stages
1180 int debrief_set_stages_and_multi_stuff()
1183 debriefing *debriefp;
1185 if ( MULTIPLAYER_CLIENT ) {
1189 Num_debrief_stages = 0;
1191 if ( Game_mode & GM_MULTIPLAYER ) {
1192 debrief_multi_server_stuff();
1195 // check to see if player is a traitor (looking at his team). If so, use the special
1196 // traitor debriefing. Only done in single player
1197 debriefp = Debriefing;
1198 if ( !(Game_mode & GM_MULTIPLAYER) ) {
1199 if (Player_ship->team == TEAM_TRAITOR)
1200 debriefp = &Traitor_debriefing;
1203 Num_debrief_stages = 0;
1204 if (Promoted >= 0) {
1205 Debrief_stages[Num_debrief_stages++] = &Promotion_stage;
1208 if (Badge_bitmap >= 0) {
1209 Debrief_stages[Num_debrief_stages++] = &Badge_stage;
1212 for (i=0; i<debriefp->num_stages; i++) {
1213 if (eval_sexp(debriefp->stages[i].formula) == 1) {
1214 Debrief_stages[Num_debrief_stages++] = &debriefp->stages[i];
1218 return Num_debrief_stages;
1221 // init the buttons that are specific to the debriefing screen
1222 void debrief_buttons_init()
1227 for ( i=0; i<NUM_BUTTONS; i++ ) {
1228 b = &Buttons[gr_screen.res][i];
1229 b->button.create( &Debrief_ui_window, "", b->x, b->y, 60, 30, 0 /*b->flags & REPEAT*/, 1 );
1230 // set up callback for when a mouse first goes over a button
1231 b->button.set_highlight_action( common_play_highlight_sound );
1232 b->button.set_bmaps(b->filename);
1233 b->button.link_hotspot(b->hotspot);
1238 for(i=0; i<NUM_DEBRIEF_TEXT; i++){
1239 // multiplayer specific text
1240 if((i == MP_TEXT_INDEX_1) || (i == MP_TEXT_INDEX_2) || (i == MP_TEXT_INDEX_3)){
1241 // only add if in multiplayer mode
1242 if(Game_mode & GM_MULTIPLAYER){
1243 Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
1248 Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
1253 // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1254 Buttons[gr_screen.res][NEXT_STAGE].button.set_hotkey(KEY_RIGHT);
1255 Buttons[gr_screen.res][PREV_STAGE].button.set_hotkey(KEY_LEFT);
1256 Buttons[gr_screen.res][LAST_STAGE].button.set_hotkey(KEY_SHIFTED | KEY_RIGHT);
1257 Buttons[gr_screen.res][FIRST_STAGE].button.set_hotkey(KEY_SHIFTED | KEY_LEFT);
1258 Buttons[gr_screen.res][TEXT_SCROLL_UP].button.set_hotkey(KEY_UP);
1259 Buttons[gr_screen.res][TEXT_SCROLL_DOWN].button.set_hotkey(KEY_DOWN);
1260 Buttons[gr_screen.res][ACCEPT_BUTTON].button.set_hotkey(KEY_CTRLED+KEY_ENTER);
1262 // if in multiplayer, disable the button for all players except the host
1263 // also disable for squad war matches
1264 if(Game_mode & GM_MULTIPLAYER){
1265 if((Netgame.type_flags & NG_TYPE_SW) || !(Net_player->flags & NETINFO_FLAG_GAME_HOST)){
1266 Buttons[gr_screen.res][REPLAY_MISSION].button.disable();
1271 // --------------------------------------------------------------------------------------
1272 // debrief_ui_init()
1274 void debrief_ui_init()
1276 // init ship selection masks and buttons
1277 common_set_interface_palette("DebriefPalette"); // set the interface palette
1278 Debrief_ui_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
1279 Debrief_ui_window.set_mask_bmap(Debrief_mask_name[gr_screen.res]);
1280 Debrief_ui_window.tooltip_handler = debrief_tooltip_handler;
1281 debrief_buttons_init();
1283 // load in help overlay bitmap
1284 help_overlay_load(DEBRIEFING_OVERLAY);
1285 help_overlay_set_state(DEBRIEFING_OVERLAY,0);
1287 if ( Game_mode & GM_MULTIPLAYER ) {
1288 // close down any old instances of the chatbox
1291 // create the new one
1293 Background_bitmap = bm_load(Debrief_multi_name[gr_screen.res]);
1294 List_region.create(&Debrief_ui_window, "", Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1], Debrief_list_coords[gr_screen.res][2], Debrief_list_coords[gr_screen.res][3], 0, 1);
1297 Background_bitmap = bm_load(Debrief_single_name[gr_screen.res]);
1300 if ( Background_bitmap < 0 ) {
1301 Warning(LOCATION, "Could not load the background bitmap for debrief screen");
1304 Award_bg_bitmap = bm_load(Debrief_award_filename[gr_screen.res][DB_AWARD_BG]);
1305 Debrief_multi_loading_bitmap = bm_load(Debrief_loading_bitmap_fname[gr_screen.res]);
1308 // sets Promotion_stage.voice
1309 // defaults to number 9 (Petrarch) for non-volition missions
1310 // this is an ugly, nasty way of doing this, but it saves us changing the missions at this point
1311 void debrief_choose_promotion_voice()
1315 if(Campaign.current_mission < 0){
1316 sprintf(Promotion_stage.voice, NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
1320 // search thru all official campaigns for our current campaign
1321 if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename)) {
1322 for (i=0; i<NUM_VOLITION_CAMPAIGNS; i++) {
1323 if ((Campaign.filename != NULL) && !stricmp(Campaign.filename, Volition_campaigns[i].campaign_name)) {
1324 // now search thru the mission filenames,
1325 for (j=0; j<Volition_campaigns[i].num_missions; j++) {
1326 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !stricmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file)) {
1327 // found it! set the persona and bail
1328 sprintf(Promotion_stage.voice, NOX("%d_%s"), Debrief_promotion_voice_mapping[i][j].persona_index, Ranks[Promoted].promotion_voice_base);
1336 // default to petrarch
1337 sprintf(Promotion_stage.voice, NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
1340 // sets Promotion_stage.voice
1341 // defaults to number 9 (Petrarch) for non-volition missions
1342 // this is an ugly, nasty, hateful way of doing this, but it saves us changing the missions at this point
1343 void debrief_choose_badge_voice()
1349 if(Campaign.current_mission < 0){
1351 // default to petrarch
1352 sprintf(Badge_stage.voice, NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1354 // default to FS1 guy
1355 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1359 if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename)) {
1361 if ( Player->on_bastion ) {
1362 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base2);
1365 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1369 // search thru all official campaigns for our current campaign
1370 for (i=0; i<NUM_VOLITION_CAMPAIGNS; i++) {
1371 if ((Campaign.filename != NULL) && !stricmp(Campaign.filename, Volition_campaigns[i].campaign_name)) {
1372 // now search thru the mission filenames,
1373 for (j=0; j<Campaign.num_missions; j++) {
1374 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !stricmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file)) {
1375 // found it! set the persona and bail
1376 sprintf(Badge_stage.voice, NOX("%d_%s"), Debrief_promotion_voice_mapping[i][j].persona_index, Badge_info[Player->stats.m_badge_earned].voice_base);
1386 // default to petrarch
1387 sprintf(Badge_stage.voice, NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1389 // default to FS1 guy
1390 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1395 void debrief_award_init()
1407 // be sure there are no old award texts floating around
1409 debrief_award_text_clear();
1412 // handle medal earned
1413 if (Player->stats.m_medal_earned != -1) {
1414 if (Player->stats.m_medal_earned == 13) { // special hack for the wings..
1416 if ( Player->stats.medals[13] > 1 ) {
1421 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_WINGS], ver);
1422 Wings_bitmap = bm_load(buf);
1424 } else if (Player->stats.m_medal_earned == 17) { // special hack for the soc crest
1425 Crest_bitmap = bm_load(Debrief_award_filename[gr_screen.res][DB_AWARD_SOC]);
1428 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_MEDAL], Player->stats.m_medal_earned);
1429 Medal_bitmap = bm_load(buf);
1433 debrief_add_award_text(Medals[Player->stats.m_medal_earned].name);
1437 // handle promotions
1438 if ( Player->stats.m_promotion_earned != -1 ) {
1439 Promoted = Player->stats.m_promotion_earned;
1440 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_RANK], Promoted + 1);
1441 Rank_bitmap = bm_load(buf);
1443 Promotion_stage.new_text = Ranks[Promoted].promotion_text;
1444 Promotion_stage.new_recommendation_text = NULL;
1446 // choose appropriate promotion voice for this mission
1447 debrief_choose_promotion_voice();
1450 debrief_add_award_text(Ranks[Promoted].name);
1454 // handle badge earned
1455 // only grant badge if earned and allowed. (no_promotion really means no promotion and no badges)
1456 if ( Player->stats.m_badge_earned != -1 ) {
1457 i = Player->stats.m_badge_earned;
1458 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_BADGE], i + 1);
1459 Badge_bitmap = bm_load(buf);
1461 Badge_stage.new_text = Badge_info[i].promotion_text;
1462 Badge_stage.new_recommendation_text = NULL;
1464 // choose appropriate voice
1465 debrief_choose_badge_voice();
1468 debrief_add_award_text(Medals[Badge_index[i]].name);
1472 if ((Rank_bitmap >= 0) || (Medal_bitmap >= 0) || (Badge_bitmap >= 0) || (Wings_bitmap >= 0) || (Crest_bitmap >= 0)) {
1479 // debrief_traitor_init() initializes local data which could be used if the player leaves the
1480 // mission a traitor. The same debriefing always gets played
1481 void debrief_traitor_init()
1483 static int inited = 0;
1486 debriefing *debrief;
1487 debrief_stage *stagep;
1491 if ((rval = setjmp(parse_abort)) != 0) {
1492 Error(LOCATION, "Unable to parse traitor.tbl! Code = %i.\n", rval);
1495 read_file_text("traitor.tbl");
1499 // open localization
1502 // simplied form of the debriefing stuff.
1503 debrief = &Traitor_debriefing;
1504 required_string("#Debriefing_info");
1506 required_string("$Num stages:");
1507 stuff_int(&debrief->num_stages);
1508 Assert(debrief->num_stages == 1);
1511 stagep = &debrief->stages[stage_num++];
1512 required_string("$Formula:");
1513 stagep->formula = get_sexp_main();
1514 required_string("$multi text");
1515 if ( Fred_running ) {
1516 stuff_string( stagep->new_text, F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1518 stagep->new_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1520 required_string("$Voice:");
1521 char traitor_voice_file[NAME_LENGTH];
1522 stuff_string(traitor_voice_file, F_FILESPEC, NULL);
1524 // DKA 9/13/99 Only 1 traitor msg for FS2
1526 if ( Player->on_bastion ) {
1527 strcpy(stagep->voice, NOX("3_"));
1529 strcpy(stagep->voice, NOX("1_"));
1533 strcat(stagep->voice, traitor_voice_file);
1535 required_string("$Recommendation text:");
1536 if ( Fred_running ) {
1537 stuff_string( stagep->new_recommendation_text, F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1539 stagep->new_recommendation_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1543 // close localization
1547 // disable the accept button if in single player and I am a traitor
1548 Debrief_accepted = 0;
1549 Turned_traitor = Must_replay_mission = 0;
1550 if (!(Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_CAMPAIGN_MODE)) {
1551 if (Player_ship->team == TEAM_TRAITOR){
1555 if (Campaign.next_mission == Campaign.current_mission){
1556 Must_replay_mission = 1;
1560 if (Turned_traitor || Must_replay_mission) {
1561 Buttons[gr_screen.res][ACCEPT_BUTTON].button.hide();
1563 // kill off any stats
1564 Player->flags &= ~PLAYER_FLAGS_PROMOTED;
1565 scoring_level_init( &Player->stats );
1569 // initialization for listing of players in game
1570 void debrief_multi_list_init()
1572 Multi_list_size = 0; // number of net players to choose from
1573 Multi_list_offset = 0;
1575 Multi_list_select = -1;
1577 if ( !(Game_mode & GM_MULTIPLAYER) )
1580 debrief_rebuild_player_list();
1582 // switch stats display to this newly selected player
1583 set_player_stats(Multi_list[0].net_player_index);
1584 strcpy(Debrief_current_callsign, Multi_list[0].callsign);
1585 Debrief_player = Player;
1588 void debrief_multi_list_scroll_up()
1590 // if we're at the beginning of the list, don't do anything
1591 if(Multi_list_offset == 0){
1592 gamesnd_play_iface(SND_GENERAL_FAIL);
1596 // otherwise scroll up
1597 Multi_list_offset--;
1598 gamesnd_play_iface(SND_USER_SELECT);
1601 void debrief_multi_list_scroll_down()
1603 // if we can scroll down no further
1604 if(Multi_list_size < Debrief_multi_list_team_max_display[gr_screen.res]){
1605 gamesnd_play_iface(SND_GENERAL_FAIL);
1608 if((Multi_list_offset + Debrief_multi_list_team_max_display[gr_screen.res]) >= Multi_list_size){
1609 gamesnd_play_iface(SND_GENERAL_FAIL);
1613 // otherwise scroll down
1614 Multi_list_offset++;
1615 gamesnd_play_iface(SND_USER_SELECT);
1618 // draw the connected net players
1619 void debrief_multi_list_draw()
1621 int y, z, font_height,idx;
1622 char str[CALLSIGN_LEN+5];
1625 font_height = gr_get_font_height();
1627 // if we currently have no item picked, pick a reasonable one
1628 if((Multi_list_size >= 0) && (Multi_list_select == -1)){
1629 // select the entry which corresponds to the local player
1630 Multi_list_select = 0;
1631 for(idx=0;idx<Multi_list_size;idx++){
1632 if(Multi_list[idx].net_player_index == MY_NET_PLAYER_NUM){
1633 Multi_list_select = idx;
1635 // switch stats display to this newly selected player
1636 set_player_stats(Multi_list[idx].net_player_index);
1637 strcpy(Debrief_current_callsign, Multi_list[idx].callsign);
1638 Debrief_player = Net_players[Multi_list[idx].net_player_index].player;
1644 // draw the list itself
1646 z = Multi_list_offset;
1647 while (y + font_height <= Debrief_list_coords[gr_screen.res][3]){
1648 np = &Net_players[Multi_list[z].net_player_index];
1650 if (z >= Multi_list_size){
1653 // set the proper text color for the highlight
1654 if(np->flags & NETINFO_FLAG_GAME_HOST){
1655 if(Multi_list_select == z){
1656 gr_set_color_fast(&Color_text_active_hi);
1658 gr_set_color_fast(&Color_bright);
1661 if(Multi_list_select == z){
1662 gr_set_color_fast(&Color_text_active);
1664 gr_set_color_fast(&Color_text_normal);
1668 // blit the proper indicator - skipping observers
1669 if(!((np->flags & NETINFO_FLAG_OBSERVER) && !(np->flags & NETINFO_FLAG_OBS_PLAYER))){
1670 if(Netgame.type_flags & NG_TYPE_TEAM){
1672 if(np->p_info.team == 0){
1673 // draw his "selected" icon
1674 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM0_SELECT] != -1)){
1675 gr_set_bitmap(Multi_common_icons[MICON_TEAM0_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1676 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1678 // draw his "normal" icon
1679 else if(Multi_common_icons[MICON_TEAM0] != -1){
1680 gr_set_bitmap(Multi_common_icons[MICON_TEAM0], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1681 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1683 } else if(np->p_info.team == 1){
1684 // draw his "selected" icon
1685 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM1_SELECT] != -1)){
1686 gr_set_bitmap(Multi_common_icons[MICON_TEAM1_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1687 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1689 // draw his "normal" icon
1690 else if(Multi_common_icons[MICON_TEAM1] != -1){
1691 gr_set_bitmap(Multi_common_icons[MICON_TEAM1], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1692 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1696 // draw the team 0 selected icon
1697 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM0_SELECT] != -1)){
1698 gr_set_bitmap(Multi_common_icons[MICON_TEAM0_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1699 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1704 strcpy(str,Multi_list[z].callsign);
1705 if(Net_players[Multi_list[z].net_player_index].flags & NETINFO_FLAG_OBSERVER && !(Net_players[Multi_list[z].net_player_index].flags & NETINFO_FLAG_OBS_PLAYER)){
1706 strcat(str,XSTR( "(O)", 438));
1710 gr_string(Debrief_list_coords[gr_screen.res][0] + MULTI_LIST_TEAM_OFFSET, Debrief_list_coords[gr_screen.res][1] + y, str);
1717 void debrief_kick_selected_player()
1719 if(Multi_list_select >= 0){
1720 Assert(Net_player->flags & NETINFO_FLAG_GAME_HOST);
1721 multi_kick_player(Multi_list[Multi_list_select].net_player_index);
1725 // get optional mission popup text
1726 void debrief_assemble_optional_mission_popup_text(char *buffer, char *mission_loop_desc)
1728 Assert(buffer != NULL);
1731 if (mission_loop_desc == NULL) {
1732 strcpy(buffer, XSTR("<No Mission Loop Description Available>", 1490));
1733 mprintf(("No mission loop description avail"));
1735 strcpy(buffer, mission_loop_desc);
1738 strcat(buffer, XSTR("\n\n\nDo you want to play the optional mission?", 1491));
1741 // what to do when the accept button is hit
1742 void debrief_accept(int ok_to_post_start_game_event)
1746 if ( (/*Cheats_enabled ||*/ Turned_traitor || Must_replay_mission) && (Game_mode & GM_CAMPAIGN_MODE) ) {
1750 if (Game_mode & GM_MULTIPLAYER) {
1754 if (Player_ship->team == TEAM_TRAITOR){
1755 str = XSTR( "Your career is over, Traitor! You can't accept new missions!", 439);
1756 }/* else if (Cheats_enabled) {
1757 str = XSTR( "You are a cheater. You cannot accept this mission!", 440);
1759 str = XSTR( "You have failed this mission and cannot accept. What do you you wish to do instead?", 441);
1762 z = popup(0, 3, XSTR( "Return to &Debriefing", 442), XSTR( "Go to &Flight Deck", 443), XSTR( "&Replay Mission", 444), str);
1764 gameseq_post_event(GS_EVENT_START_BRIEFING); // cycle back to briefing
1765 } else if ( z == 1 ) {
1766 gameseq_post_event(GS_EVENT_END_GAME); // return to main hall, tossing stats
1772 Debrief_accepted = 1;
1773 // save mission stats
1774 if (Game_mode & GM_MULTIPLAYER) {
1775 // note that multi_debrief_accept_hit() will handle all mission_campaign_* calls on its own
1776 // as well as doing stats transfers, etc.
1777 multi_debrief_accept_hit();
1781 int play_commit_sound = 1;
1782 // only write the player's stats if he's accepted
1784 // if we are just playing a single mission, then don't do many of the things
1785 // that need to be done. Nothing much should happen when just playing a single
1786 // mission that isn't in a campaign.
1787 if ( Game_mode & GM_CAMPAIGN_MODE ) {
1789 // check for possible mission loop
1790 // check for (1) mission loop available, (2) dont have to repeat last mission
1791 if(!(Game_mode & GM_MULTIPLAYER)){
1792 int cur = Campaign.current_mission;
1793 bool require_repeat_mission = (Campaign.current_mission == Campaign.next_mission);
1794 if (Campaign.missions[cur].has_mission_loop) {
1795 Assert(Campaign.loop_mission != CAMPAIGN_LOOP_MISSION_UNINITIALIZED);
1798 if ( (Campaign.missions[cur].has_mission_loop && (Campaign.loop_mission != -1)) && !require_repeat_mission ) {
1801 debrief_assemble_optional_mission_popup_text(buffer, Campaign.missions[cur].mission_loop_desc);
1803 int choice = popup(0 , 2, POPUP_NO, POPUP_YES, buffer);
1805 Campaign.loop_enabled = 1;
1806 Campaign.next_mission = Campaign.loop_mission;
1815 if(ok_to_post_start_game_event){
1816 gameseq_post_event(GS_EVENT_LOOP_BRIEF);
1818 play_commit_sound = 0;
1821 // continue as normal
1824 mission_campaign_mission_over();
1826 // check to see if we are out of the loop now
1827 if ( Campaign.next_mission == Campaign.loop_reentry ) {
1828 Campaign.loop_enabled = 0;
1831 // check if campaign is over
1832 if ( Campaign.next_mission == -1 ) {
1833 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
1834 gameseq_post_event(GS_EVENT_END_DEMO);
1836 gameseq_post_event(GS_EVENT_MAIN_MENU);
1839 if ( ok_to_post_start_game_event ) {
1841 if(game_do_cd_mission_check(Game_current_mission_filename)){
1842 gameseq_post_event(GS_EVENT_START_GAME);
1844 gameseq_post_event(GS_EVENT_MAIN_MENU);
1847 play_commit_sound = 0;
1852 gameseq_post_event(GS_EVENT_MAIN_MENU);
1855 if ( play_commit_sound ) {
1856 gamesnd_play_iface(SND_COMMIT_PRESSED);
1863 void debrief_next_tab()
1865 New_mode = Current_mode + 1;
1866 if (New_mode >= NUM_TABS)
1870 void debrief_prev_tab()
1872 New_mode = Current_mode - 1;
1874 New_mode = NUM_TABS - 1;
1877 // --------------------------------------------------------------------------------------
1878 // debrief_next_stage()
1880 void debrief_next_stage()
1882 if (Current_stage < Num_stages - 1) {
1883 New_stage = Current_stage + 1;
1884 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1887 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1890 // --------------------------------------------------------------------------------------
1891 // debrief_prev_stage()
1893 void debrief_prev_stage()
1895 if (Current_stage) {
1896 New_stage = Current_stage - 1;
1897 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1900 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1903 // --------------------------------------------------------------------------------------
1904 // debrief_first_stage()
1905 void debrief_first_stage()
1907 if (Current_stage) {
1909 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1912 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1915 // --------------------------------------------------------------------------------------
1916 // debrief_last_stage()
1917 void debrief_last_stage()
1919 if (Current_stage != Num_stages - 1) {
1920 New_stage = Num_stages - 1;
1921 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1924 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1927 // draw what stage number the debriefing is on
1928 void debrief_render_stagenum()
1936 sprintf(buf, XSTR( "%d of %d", 445), Current_stage + 1, Num_stages);
1937 gr_get_string_size(&w, NULL, buf);
1938 gr_set_color_fast(&Color_bright_blue);
1939 gr_string(Debrief_stage_info_coords[gr_screen.res][0] - w, Debrief_stage_info_coords[gr_screen.res][1], buf);
1940 gr_set_color_fast(&Color_white);
1943 // render the mission time at the specified y location
1944 void debrief_render_mission_time(int y_loc)
1948 game_format_time(Missiontime, time_str);
1949 gr_string(0, y_loc, XSTR( "Mission Time", 446));
1950 gr_string(Debrief_text_x2[gr_screen.res], y_loc, time_str);
1953 // render out the debriefing text to the scroll window
1954 void debrief_render()
1956 int y, z, font_height;
1958 if ( Num_stages <= 0 )
1961 font_height = gr_get_font_height();
1963 gr_set_clip(Debrief_text_wnd_coords[gr_screen.res][0], Debrief_text_wnd_coords[gr_screen.res][1], Debrief_text_wnd_coords[gr_screen.res][2], Debrief_text_wnd_coords[gr_screen.res][3]);
1966 while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
1967 if (z >= Num_text_lines)
1970 if (Text_type[z] == TEXT_TYPE_NORMAL)
1971 gr_set_color_fast(&Color_white);
1973 gr_set_color_fast(&Color_bright_red);
1976 gr_string(0, y, Text[z]);
1985 // render out the stats info to the scroll window
1987 void debrief_stats_render()
1989 int i, y, font_height;
1991 gr_set_color_fast(&Color_blue);
1992 gr_set_clip(Debrief_text_wnd_coords[gr_screen.res][0], Debrief_text_wnd_coords[gr_screen.res][1], Debrief_text_wnd_coords[gr_screen.res][2], Debrief_text_wnd_coords[gr_screen.res][3]);
1993 gr_string(0, 0, Debrief_current_callsign);
1994 font_height = gr_get_font_height();
1997 switch ( Current_stage ) {
1998 case DEBRIEF_MISSION_STATS:
1999 i = Current_stage - 1;
2003 gr_set_color_fast(&Color_white);
2005 // display mission completion time
2006 debrief_render_mission_time(y);
2009 show_stats_label(i, 0, y, font_height);
2010 show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2012 case DEBRIEF_ALLTIME_STATS:
2013 i = Current_stage - 1;
2017 gr_set_color_fast(&Color_white);
2018 show_stats_label(i, 0, y, font_height);
2019 show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2022 case DEBRIEF_ALLTIME_KILLS:
2023 case DEBRIEF_MISSION_KILLS:
2024 gr_set_color_fast(&Color_white);
2026 while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
2027 if (i >= Num_text_lines)
2031 if ( Current_stage == DEBRIEF_MISSION_KILLS )
2032 gr_printf(0, y, XSTR( "Mission Kills by Ship Type", 447));
2034 gr_printf(0, y, XSTR( "All-time Kills by Ship Type", 448));
2037 gr_printf(0, y, "%s", Debrief_stats_kills[i - 2].text);
2038 gr_printf(Debrief_text_x2[gr_screen.res], y, "%d", Debrief_stats_kills[i - 2].num);
2045 if (Num_text_lines == 2) {
2046 if ( Current_stage == DEBRIEF_MISSION_KILLS )
2047 gr_printf(0, y, XSTR( "(No ship kills this mission)", 449));
2049 gr_printf(0, y, XSTR( "(No ship kills)", 450));
2062 // do action for when the replay button is pressed
2063 void debrief_replay_pressed()
2065 if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2067 choice = popup(0, 2, POPUP_CANCEL, XSTR( "&Replay", 451), XSTR( "If you choose to replay this mission, you will be required to complete it again before proceeding to future missions.\n\nIn addition, any statistics gathered during this mission will be discarded if you choose to replay.", 452));
2074 gameseq_post_event(GS_EVENT_START_BRIEFING); // take us to the briefing
2075 gamesnd_play_iface(SND_COMMIT_PRESSED);
2078 // -------------------------------------------------------------------
2079 // debrief_redraw_pressed_buttons()
2081 // Redraw any debriefing buttons that are pressed down. This function is needed
2082 // since we sometimes need to draw pressed buttons last to ensure the entire
2083 // button gets drawn (and not overlapped by other buttons)
2085 void debrief_redraw_pressed_buttons()
2090 for ( i=0; i<NUM_BUTTONS; i++ ) {
2091 b = &Buttons[gr_screen.res][i].button;
2092 // don't draw the recommendations button if we're in stats mode
2093 if ( b->button_down() ) {
2099 // debrief specific button with hotspot 'i' has been pressed, so perform the associated action
2101 void debrief_button_pressed(int num)
2105 Buttons[gr_screen.res][RECOMMENDATIONS].button.enable();
2106 // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
2107 if (num != Current_mode){
2108 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
2113 // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 1; // allows failure sound to be played
2114 Buttons[gr_screen.res][RECOMMENDATIONS].button.disable();
2115 if (num != Current_mode){
2116 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
2121 case TEXT_SCROLL_UP:
2124 gamesnd_play_iface(SND_SCROLL);
2126 gamesnd_play_iface(SND_GENERAL_FAIL);
2130 case TEXT_SCROLL_DOWN:
2131 if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
2133 gamesnd_play_iface(SND_SCROLL);
2135 gamesnd_play_iface(SND_GENERAL_FAIL);
2139 case REPLAY_MISSION:
2140 if(Game_mode & GM_MULTIPLAYER){
2141 multi_debrief_replay_hit();
2143 debrief_replay_pressed();
2147 case RECOMMENDATIONS:
2148 gamesnd_play_iface(SND_USER_SELECT);
2149 Recommend_active = !Recommend_active;
2150 debrief_text_init();
2154 debrief_first_stage();
2158 debrief_prev_stage();
2162 debrief_next_stage();
2166 debrief_last_stage();
2170 gamesnd_play_iface(SND_HELP_PRESSED);
2171 launch_context_help();
2174 case OPTIONS_BUTTON:
2175 gamesnd_play_iface(SND_SWITCH_SCREENS);
2176 gameseq_post_event( GS_EVENT_OPTIONS_MENU );
2184 gamesnd_play_iface(SND_SWITCH_SCREENS);
2185 gameseq_post_event(GS_EVENT_VIEW_MEDALS);
2188 case PLAYER_SCROLL_UP:
2189 debrief_multi_list_scroll_up();
2192 case PLAYER_SCROLL_DOWN:
2193 debrief_multi_list_scroll_down();
2196 case MULTI_PINFO_POPUP:
2197 Debrief_should_show_popup = 1;
2201 debrief_kick_selected_player();
2206 void debrief_setup_ship_kill_stats(int stage_num)
2210 debrief_stats_kill_info *kill_info;
2212 Assert(Current_stage < DEBRIEF_NUM_STATS_PAGES);
2213 if ( Current_stage == DEBRIEF_MISSION_STATS || Current_stage == DEBRIEF_ALLTIME_STATS )
2216 Assert(Debrief_player != NULL);
2218 // kill_ar points to an array of MAX_SHIP_TYPE ints
2219 if ( Current_stage == DEBRIEF_MISSION_KILLS ) {
2220 kill_arr = Debrief_player->stats.m_okKills;
2222 kill_arr = Debrief_player->stats.kills;
2226 for ( i=0; i<MAX_SHIP_TYPES; i++ ) {
2228 // code used to add in mission kills, but the new system assumes that the player will accept, so
2229 // all time stats already have mission stats added in.
2230 if ( kill_arr[i] <= 0 ){
2235 kill_info = &Debrief_stats_kills[Num_text_lines++];
2237 kill_info->num = kill_arr[i];
2239 strcpy(kill_info->text, Ship_info[i].name);
2240 strcat(kill_info->text, NOX(":"));
2243 Num_text_lines += 2;
2246 // Iterate through the debriefing buttons, checking if they are pressed
2247 void debrief_check_buttons()
2251 for ( i=0; i<NUM_BUTTONS; i++ ) {
2252 if ( Buttons[gr_screen.res][i].button.pressed() ) {
2253 debrief_button_pressed(i);
2257 if ( !(Game_mode & GM_MULTIPLAYER) )
2260 if (List_region.pressed()) {
2261 List_region.get_mouse_pos(NULL, &y);
2262 z = Multi_list_offset + y / gr_get_font_height();
2263 if ((z >= 0) && (z < Multi_list_size)) {
2264 // switch stats display to this newly selected player
2265 set_player_stats(Multi_list[z].net_player_index);
2266 strcpy(Debrief_current_callsign, Multi_list[z].callsign);
2267 Debrief_player = Net_players[Multi_list[z].net_player_index].player;
2268 Multi_list_select = z;
2269 debrief_setup_ship_kill_stats(Current_stage);
2270 gamesnd_play_iface(SND_USER_SELECT);
2274 // if the player was double clicked on - we should popup a player info popup
2276 if (List_region.double_clicked()) {
2277 Debrief_should_show_popup = 1;
2282 void debrief_text_stage_init(char *src, int type)
2284 int i, n_lines, n_chars[MAX_DEBRIEF_LINES];
2285 char line[MAX_DEBRIEF_LINE_LEN];
2286 char *p_str[MAX_DEBRIEF_LINES];
2288 n_lines = split_str(src, Debrief_text_wnd_coords[gr_screen.res][2], n_chars, p_str, MAX_DEBRIEF_LINES);
2289 Assert(n_lines >= 0);
2291 // if you hit this, you proba
2292 if(n_lines >= MAX_DEBRIEF_LINES){
2293 Warning(LOCATION, "You have come close to the limit of debriefing lines, try adding more stages");
2296 for ( i=0; i<n_lines; i++ ) {
2297 Assert(n_chars[i] < MAX_DEBRIEF_LINE_LEN);
2298 Assert(Num_text_lines < MAX_TOTAL_DEBRIEF_LINES);
2299 strncpy(line, p_str[i], n_chars[i]);
2300 line[n_chars[i]] = 0;
2301 drop_white_space(line);
2302 Text_type[Num_text_lines] = type;
2303 Text[Num_text_lines++] = strdup(line);
2309 void debrief_free_text()
2313 for (i=0; i<Num_debrief_lines; i++)
2317 Num_debrief_lines = 0;
2320 // setup the debriefing text lines for rendering
2321 void debrief_text_init()
2326 // release old text lines first
2327 debrief_free_text();
2328 Num_text_lines = Text_offset = 0;
2330 if (Current_mode == DEBRIEF_TAB) {
2331 for (i=0; i<Num_debrief_stages; i++) {
2333 Text[Num_text_lines++] = NULL; // add a blank line between stages
2335 src = Debrief_stages[i]->new_text;
2337 debrief_text_stage_init(src, TEXT_TYPE_NORMAL);
2339 if (Recommend_active) {
2340 src = Debrief_stages[i]->new_recommendation_text;
2341 if (!src && (i == Num_debrief_stages - 1) && !r_count)
2342 src = XSTR( "We have no recommendations for you.", 1054);
2345 Text[Num_text_lines++] = NULL;
2346 debrief_text_stage_init(src, TEXT_TYPE_RECOMMENDATION);
2352 Num_debrief_lines = Num_text_lines;
2356 // not in debriefing mode, must be in stats mode
2358 debrief_setup_ship_kill_stats(Current_stage);
2362 // --------------------------------------------------------------------------------------
2366 Assert(!Debrief_inited);
2367 // Campaign.loop_enabled = 0;
2368 Campaign.loop_mission = CAMPAIGN_LOOP_MISSION_UNINITIALIZED;
2370 // set up the right briefing for this guy
2371 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
2372 Debriefing = &Debriefings[Net_player->p_info.team];
2374 Debriefing = &Debriefings[0];
2377 // no longer is mission
2378 Game_mode &= ~(GM_IN_MISSION);
2382 New_mode = DEBRIEF_TAB;
2383 Recommend_active = Award_active = 0;
2388 Debrief_cue_voice = 0;
2389 Num_text_lines = Num_debrief_lines = 0;
2390 Debrief_first_voice_flag = 1;
2392 Debrief_multi_voice_loaded = 0;
2395 Medal_text_bitmap = bm_load(NOX("DebriefText01"));
2396 Rank_text_bitmap = bm_load(NOX("DebriefText02"));
2397 Badge_text_bitmap = bm_load(NOX("DebriefText03"));
2400 if ( (Game_mode & GM_CAMPAIGN_MODE) && ( !MULTIPLAYER_CLIENT ) ) {
2401 // MUST store goals and events first - may be used to evaluate next mission
2402 // store goals and events
2403 mission_campaign_store_goals_and_events();
2405 // evaluate next mission
2406 mission_campaign_eval_next_mission();
2409 // call traitor init before calling scoring_level_close. traitor init will essentially nullify
2411 if ( !(Game_mode & GM_MULTIPLAYER) ) { // only do for single player
2412 debrief_traitor_init(); // initialize data needed if player becomes traitor.
2415 // call scoring level close for my stats. Needed for award_init. The stats will
2416 // be backed out if used chooses to replace them.
2417 scoring_level_close();
2419 debrief_ui_init(); // init UI items
2420 debrief_award_init();
2422 debrief_voice_init();
2423 debrief_multi_list_init();
2424 // rank_bitmaps_clear();
2425 // rank_bitmaps_load();
2427 strcpy(Debrief_current_callsign, Player->callsign);
2428 Debrief_player = Player;
2429 // Debrief_current_net_player_index = debrief_multi_list[0].net_player_index;
2431 // set up the Debrief_stages[] and Recommendations[] arrays. Only do the following stuff
2432 // for non-clients (i.e. single and game server). Multiplayer clients will get their debriefing
2433 // info directly from the server.
2434 if ( !MULTIPLAYER_CLIENT ) {
2435 debrief_set_stages_and_multi_stuff();
2437 if ( Num_debrief_stages <= 0 ) {
2438 Num_debrief_stages = 0;
2440 debrief_voice_load_all();
2443 // multiplayer client may have already received their debriefing info. If they have not,
2444 // then set the num debrief stages to 0
2445 if ( !Debrief_multi_stages_loaded ) {
2446 Num_debrief_stages = 0;
2451 if (mission_evaluate_primary_goals() == PRIMARY_GOALS_COMPLETE) {
2452 common_music_init(SCORE_DEBRIEF_SUCCESS);
2454 common_music_init(SCORE_DEBRIEF_FAIL);
2458 // start up the appropriate music
2459 if (Campaign.next_mission == Campaign.current_mission) {
2460 // you failed the mission because you suck, so you get the suck music
2461 common_music_init(SCORE_DEBRIEF_FAIL);
2462 } else if (mission_goals_met()) {
2463 // you completed all primaries and secondaries, thus you are a stud boy and you get stud boy music
2464 common_music_init(SCORE_DEBRIEF_SUCCESS);
2466 // you somehow passed the mission, so you get a little something for your efforts.
2467 common_music_init(SCORE_DEBRIEF_AVERAGE);
2470 if (Campaign.next_mission == Campaign.current_mission) {
2471 // better luck next time, increase his retries
2472 Player->failures_this_session++;
2474 // clear his retries info regardless of whether or not he accepts
2475 Player->failures_this_session = 0;
2478 if (Game_mode & GM_MULTIPLAYER) {
2479 multi_debrief_init();
2481 // if i'm not the host of the game, disable the multi kick button
2482 if (!(Net_player->flags & NETINFO_FLAG_GAME_HOST)) {
2483 Buttons[gr_screen.res][MULTI_KICK].button.disable();
2486 Buttons[gr_screen.res][PLAYER_SCROLL_UP].button.disable();
2487 Buttons[gr_screen.res][PLAYER_SCROLL_DOWN].button.disable();
2488 Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.disable();
2489 Buttons[gr_screen.res][MULTI_KICK].button.disable();
2490 Buttons[gr_screen.res][PLAYER_SCROLL_UP].button.hide();
2491 Buttons[gr_screen.res][PLAYER_SCROLL_DOWN].button.hide();
2492 Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.hide();
2493 Buttons[gr_screen.res][MULTI_KICK].button.hide();
2496 if (!Award_active) {
2497 Buttons[gr_screen.res][MEDALS_BUTTON].button.disable();
2498 Buttons[gr_screen.res][MEDALS_BUTTON].button.hide();
2501 Debrief_skip_popup_already_shown = 0;
2506 // --------------------------------------------------------------------------------------
2508 void debrief_close()
2512 Assert(Debrief_inited);
2514 // if the mission wasn't accepted, clear out my stats
2515 // we need to evaluate a little differently for multiplayer since the conditions for "accepting"
2516 // are a little bit different
2517 if (Game_mode & GM_MULTIPLAYER) {
2518 // if stats weren't accepted, backout my own stats
2519 if (multi_debrief_stats_accept_code() != 1) {
2520 if(MULTIPLAYER_MASTER){
2521 for(idx=0; idx<MAX_PLAYERS; idx++){
2522 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) && (Net_players[idx].player != NULL)){
2523 scoring_backout_accept(&Net_players[idx].player->stats);
2527 scoring_backout_accept( &Player->stats );
2532 if( !Debrief_accepted || !(Game_mode & GM_CAMPAIGN_MODE) ){
2533 scoring_backout_accept( &Player->stats );
2537 // if dude passed the misson and accepted, reset his show skip popup flag
2538 if (Debrief_accepted) {
2539 Player->show_skip_popup = 1;
2542 if (Num_debrief_lines) {
2543 for (i=0; i<Num_debrief_lines; i++){
2550 // clear out debrief info parsed from mission file
2551 mission_debrief_common_reset();
2553 // unload the overlay bitmap
2555 help_overlay_unload(DEBRIEFING_OVERLAY);
2558 // clear out award text
2559 Debrief_award_text_num_lines = 0;
2561 debrief_voice_unload_all();
2562 common_music_close();
2565 // rank_bitmaps_release();
2568 if (Background_bitmap >= 0){
2569 bm_unload(Background_bitmap);
2572 if (Award_bg_bitmap >= 0){
2573 bm_unload(Award_bg_bitmap);
2576 if (Rank_bitmap >= 0){
2577 bm_unload(Rank_bitmap);
2580 if (Medal_bitmap >= 0){
2581 bm_unload(Medal_bitmap);
2584 if (Badge_bitmap >= 0){
2585 bm_unload(Badge_bitmap);
2588 if (Wings_bitmap >= 0) {
2589 bm_unload(Wings_bitmap);
2592 if (Crest_bitmap >= 0) {
2593 bm_unload(Crest_bitmap);
2597 if (Medal_text_bitmap >= 0) {
2598 bm_unload(Medal_text_bitmap);
2601 if (Badge_text_bitmap >= 0) {
2602 bm_unload(Badge_text_bitmap);
2605 if (Rank_text_bitmap >= 0) {
2606 bm_unload(Rank_text_bitmap);
2610 Debrief_ui_window.destroy();
2611 common_free_interface_palette(); // restore game palette
2614 if (Game_mode & GM_MULTIPLAYER){
2615 multi_debrief_close();
2623 // handle keypresses in debriefing
2624 void debrief_do_keys(int new_k)
2631 case KEY_SHIFTED | KEY_TAB:
2639 // multiplayer accept popup is a little bit different
2640 if (Game_mode & GM_MULTIPLAYER) {
2641 multi_debrief_esc_hit();
2643 // display the normal debrief popup
2645 if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2646 pf_flags = PF_BODY_BIG; // | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON;
2647 choice = popup(pf_flags, 3, POPUP_CANCEL, XSTR( "&Yes", 454), XSTR( "&No, retry later", 455), XSTR( "Accept this mission outcome?", 456));
2648 if (choice == 1) { // accept and continue on
2650 gameseq_post_event(GS_EVENT_MAIN_MENU);
2656 } else if (Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2657 // need to popup saying that mission was a failure and must be replayed
2658 choice = popup(0, 2, POPUP_NO, POPUP_YES, XSTR( "Because this mission was a failure, you must replay this mission when you continue your campaign.\n\nReturn to the Flight Deck?", 457));
2663 // Return to Main Hall
2664 gameseq_post_event(GS_EVENT_END_GAME);
2675 void debrief_draw_award_text()
2677 int start_y, curr_y, i, x, sw;
2678 int fh = gr_get_font_height();
2679 int field_width = (Medal_bitmap > 0) ? Debrief_award_text_width[gr_screen.res][DB_WITH_MEDAL] : Debrief_award_text_width[gr_screen.res][DB_WITHOUT_MEDAL];
2681 // vertically centered within field
2682 start_y = Debrief_award_text_coords[gr_screen.res][1] + ((Debrief_award_text_coords[gr_screen.res][2] - (fh * Debrief_award_text_num_lines)) / 2);
2686 for (i=0; i<Debrief_award_text_num_lines; i++) {
2687 gr_get_string_size(&sw, NULL, Debrief_award_text[i]);
2688 x = (Medal_bitmap < 0) ? (Debrief_award_text_coords[gr_screen.res][0] + (field_width - sw) / 2) : Debrief_award_text_coords[gr_screen.res][0];
2689 if (i==AWARD_TEXT_MAX_LINES-1) x += 7; // hack because of the shape of the box
2690 gr_set_color_fast(&Color_white);
2691 gr_string(x, curr_y, Debrief_award_text[i]);
2693 // adjust y pos, including a little extra between the "pairs"
2695 if ((i == 1) || (i == 3)) {
2696 curr_y += ((gr_screen.res == GR_640) ? 2 : 6);
2701 // clears out text array so we dont have old award text showing up on new awards.
2702 void debrief_award_text_clear() {
2705 Debrief_award_text_num_lines = 0;
2706 for (i=0; i<AWARD_TEXT_MAX_LINES; i++) {
2707 //Debrief_award_text[i][0] = 0;
2708 memset(Debrief_award_text[i], 0, sizeof(char)*AWARD_TEXT_MAX_LINE_LENGTH);
2712 // this is the nastiest code I have ever written. if you are modifying this, i feel bad for you.
2713 void debrief_add_award_text(char *str)
2715 Assert(Debrief_award_text_num_lines <= AWARD_TEXT_MAX_LINES);
2716 if (Debrief_award_text_num_lines > AWARD_TEXT_MAX_LINES) {
2721 int field_width = (Medal_bitmap > 0) ? Debrief_award_text_width[gr_screen.res][DB_WITH_MEDAL] : Debrief_award_text_width[gr_screen.res][DB_WITHOUT_MEDAL];
2724 strcpy(Debrief_award_text[Debrief_award_text_num_lines], str);
2726 // maybe translate for displaying
2728 medals_translate_name(Debrief_award_text[Debrief_award_text_num_lines], AWARD_TEXT_MAX_LINE_LENGTH);
2729 } else if (Lcl_pl) {
2730 medals_translate_name_pl(Debrief_award_text[Debrief_award_text_num_lines], AWARD_TEXT_MAX_LINE_LENGTH);
2733 Debrief_award_text_num_lines++;
2735 // if its too long, split once ONLY
2736 // assumes text isnt > 2 lines, but this is a safe assumption due to the char limits of the ranks/badges/etc
2737 if (Debrief_award_text_num_lines < AWARD_TEXT_MAX_LINES) {
2738 line2 = split_str_once(Debrief_award_text[Debrief_award_text_num_lines-1], field_width);
2739 if (line2 != NULL) {
2740 sprintf(Debrief_award_text[Debrief_award_text_num_lines], " %s", line2); // indent a space
2742 Debrief_award_text_num_lines++; // leave blank line even if it all fits into 1
2745 #endif // !MAKE_FS1: No text for FS1, it's all bitmaps
2747 // called once per frame to drive all the input reading and rendering
2748 void debrief_do_frame(float frametime)
2751 char *please_wait_str = XSTR("Please Wait", 1242);
2755 Assert(Debrief_inited);
2757 // first thing is to load the files
2758 if ( MULTIPLAYER_CLIENT && !Debrief_multi_stages_loaded ) {
2759 // draw the background, etc
2760 GR_MAYBE_CLEAR_RES(Background_bitmap);
2761 if (Background_bitmap >= 0) {
2762 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2766 Debrief_ui_window.draw();
2768 if ( Debrief_multi_loading_bitmap > -1 ){
2769 gr_set_bitmap(Debrief_multi_loading_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2770 gr_bitmap( Please_wait_coords[gr_screen.res][0], Please_wait_coords[gr_screen.res][1] );
2773 // draw "Please Wait"
2774 gr_set_color_fast(&Color_normal);
2776 gr_get_string_size(&str_w, &str_h, please_wait_str);
2777 gr_string((gr_screen.max_w - str_w) / 2, (gr_screen.max_h - str_h) / 2, please_wait_str);
2782 // make sure we run the debrief do frame
2783 if (Game_mode & GM_MULTIPLAYER) {
2784 multi_debrief_do_frame();
2789 int keypress = game_check_key();
2790 if(keypress == KEY_ESC){
2792 multi_quit_game(PROMPT_CLIENT);
2798 // if multiplayer client, and not loaded voice, then load it
2799 if ( MULTIPLAYER_CLIENT && !Debrief_multi_voice_loaded ) {
2800 debrief_multi_fixup_stages();
2801 debrief_voice_load_all();
2802 Debrief_multi_voice_loaded = 1;
2805 if ( help_overlay_active(DEBRIEFING_OVERLAY) ) {
2806 Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
2807 Debrief_ui_window.set_ignore_gadgets(1);
2810 k = chatbox_process();
2811 if ( Game_mode & GM_NORMAL ) {
2812 new_k = Debrief_ui_window.process(k);
2814 new_k = Debrief_ui_window.process(k, 0);
2817 if ( (k > 0) || (new_k > 0) || B1_JUST_RELEASED ) {
2818 if ( help_overlay_active(DEBRIEFING_OVERLAY) ) {
2819 help_overlay_set_state(DEBRIEFING_OVERLAY, 0);
2820 Debrief_ui_window.set_ignore_gadgets(0);
2826 if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
2827 Debrief_ui_window.set_ignore_gadgets(0);
2830 // don't show pilot info popup by default
2831 Debrief_should_show_popup = 0;
2833 // see if the mode has changed and handle it if so.
2834 if ( Current_mode != New_mode ) {
2835 debrief_voice_stop();
2836 Current_mode = New_mode;
2839 if (New_mode == DEBRIEF_TAB) {
2841 Debrief_cue_voice = 0;
2843 if (Debrief_first_voice_flag) {
2844 Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY * 3);
2845 Debrief_first_voice_flag = 0;
2848 Num_stages = DEBRIEF_NUM_STATS_PAGES;
2852 if ((Num_stages > 0) && (New_stage != Current_stage)) {
2853 Current_stage = New_stage;
2854 debrief_text_init();
2857 debrief_voice_play();
2860 if (Game_mode & GM_MULTIPLAYER) {
2861 multi_debrief_do_frame();
2864 // Now do all the rendering for the frame
2865 GR_MAYBE_CLEAR_RES(Background_bitmap);
2866 if (Background_bitmap >= 0) {
2867 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2871 // draw the damn awarded stuff, G
2872 if ( Award_active && (Award_bg_bitmap >= 0) ) {
2873 gr_set_bitmap(Award_bg_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2874 gr_bitmap(Debrief_award_wnd_coords[gr_screen.res][0], Debrief_award_wnd_coords[gr_screen.res][1]);
2875 if (Rank_bitmap >= 0) {
2876 gr_set_bitmap(Rank_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2878 gr_bitmap(Debrief_rank_coords[0], Debrief_rank_coords[1]);
2880 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2884 if (Medal_bitmap >= 0) {
2885 gr_set_bitmap(Medal_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2886 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2889 if (Badge_bitmap >= 0) {
2890 gr_set_bitmap(Badge_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2892 gr_bitmap(Debrief_badge_coords[0], Debrief_badge_coords[1]);
2894 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2898 if (Wings_bitmap >= 0) {
2899 gr_set_bitmap(Wings_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2901 gr_bitmap(Debrief_badge_coords[0], Debrief_badge_coords[1]);
2903 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2907 // this isn't used in FS1 but doesn't hurt to leave it
2908 if (Crest_bitmap >= 0) {
2909 gr_set_bitmap(Crest_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2910 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2913 // draw medal/badge/rank labels
2915 debrief_draw_award_text();
2917 if (Rank_text_bitmap >= 0) {
2918 gr_set_bitmap(Rank_text_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2919 gr_bitmap(Debrief_rank_text_coords[gr_screen.res][0], Debrief_rank_text_coords[gr_screen.res][1]);
2922 if (Medal_text_bitmap >= 0) {
2923 gr_set_bitmap(Medal_text_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2924 gr_bitmap(Debrief_medal_text_coords[gr_screen.res][0], Debrief_medal_text_coords[gr_screen.res][1]);
2927 if (Badge_text_bitmap >= 0) {
2928 gr_set_bitmap(Badge_text_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2929 gr_bitmap(Debrief_badge_text_coords[gr_screen.res][0], Debrief_badge_text_coords[gr_screen.res][1]);
2934 Debrief_ui_window.draw();
2935 debrief_redraw_pressed_buttons();
2936 Buttons[gr_screen.res][Current_mode].button.draw_forced(2);
2937 if (Recommend_active && (Current_mode != STATS_TAB)) {
2938 Buttons[gr_screen.res][RECOMMENDATIONS].button.draw_forced(2);
2941 // draw the title of the mission
2942 gr_set_color_fast(&Color_bright_white);
2943 strcpy(buf, The_mission.name);
2944 gr_force_fit_string(buf, 255, Debrief_title_coords[gr_screen.res][2]);
2945 gr_string(Debrief_title_coords[gr_screen.res][0], Debrief_title_coords[gr_screen.res][1], buf);
2947 #if !defined(NDEBUG) || defined(INTERPLAYQA)
2948 gr_set_color_fast(&Color_normal);
2949 gr_printf(Debrief_title_coords[gr_screen.res][0], Debrief_title_coords[gr_screen.res][1] - 10, NOX("[name: %s, mod: %s]"), Mission_filename, The_mission.modified);
2952 // draw the screen-specific text
2953 switch (Current_mode) {
2955 if ( Num_debrief_stages <= 0 ) {
2956 gr_set_color_fast(&Color_white);
2957 Assert( Game_current_mission_filename != NULL );
2958 gr_printf(Debrief_text_wnd_coords[gr_screen.res][0], Debrief_text_wnd_coords[gr_screen.res][1], XSTR( "No Debriefing for mission: %s", 458), Game_current_mission_filename);
2967 debrief_stats_render();
2971 if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
2974 gr_set_color_fast(&Color_red);
2975 gr_get_string_size(&w, NULL, XSTR( "More", 459));
2976 gr_printf(Debrief_text_wnd_coords[gr_screen.res][0] + Debrief_text_wnd_coords[gr_screen.res][2] / 2 - w / 2, Debrief_text_wnd_coords[gr_screen.res][1] + Debrief_text_wnd_coords[gr_screen.res][3], XSTR( "More", 459));
2979 debrief_render_stagenum();
2980 debrief_multi_list_draw();
2982 // render some extra stuff in multiplayer
2983 if (Game_mode & GM_MULTIPLAYER) {
2984 // render the chatbox last
2988 Debrief_ui_window.draw_tooltip();
2990 // render the status indicator for the voice system
2991 multi_common_voice_display_status();
2994 // AL 3-6-98: Needed to move key reading here, since popups are launched from this code, and we don't
2995 // want to include the mouse pointer which is drawn in the flip
2997 if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
2998 debrief_check_buttons();
2999 debrief_do_keys(new_k);
3002 // blit help overlay if active
3003 help_overlay_maybe_blit(DEBRIEFING_OVERLAY);
3007 // dont let dude skip 3-09. hack.
3008 if(Game_mode & GM_CAMPAIGN_MODE){
3009 if((Campaign.current_mission >= 0) && (Campaign.current_mission < MAX_CAMPAIGN_MISSIONS)){
3010 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !stricmp(Campaign.missions[Campaign.current_mission].name, "sm3-09.fs2")) {
3011 Debrief_skip_popup_already_shown = 1;
3016 // maybe show skip mission popup
3017 if ((!Debrief_skip_popup_already_shown) && (Player->show_skip_popup) && (Game_mode & GM_NORMAL) && (Game_mode & GM_CAMPAIGN_MODE) && (Player->failures_this_session >= PLAYER_MISSION_FAILURE_LIMIT) && !(Game_mode & GM_MULTIPLAYER)) {
3018 int popup_choice = popup(0, 3, XSTR("Do Not Skip This Mission", 1473),
3019 XSTR("Advance To The Next Mission", 1474),
3020 XSTR("Don't Show Me This Again", 1475),
3021 XSTR("You have failed this mission five times. If you like, you may advance to the next mission.", 1472) );
3022 switch (popup_choice) {
3024 // stay on this mission, so proceed to normal debrief
3025 // in other words, do nothing.
3028 // skip this mission
3029 mission_campaign_skip_to_next();
3030 gameseq_post_event(GS_EVENT_START_GAME);
3033 // dont show this again
3034 Player->show_skip_popup = 0;
3038 Debrief_skip_popup_already_shown = 1;
3041 // check to see if we should be showing a pilot info popup in multiplayer (if a guy was double clicked)
3042 if ((Game_mode & GM_MULTIPLAYER) && Debrief_should_show_popup) {
3043 Assert((Multi_list_select >= 0) && (Multi_list_select < Multi_list_size));
3044 multi_pinfo_popup(&Net_players[Multi_list[Multi_list_select].net_player_index]);
3046 Debrief_should_show_popup = 0;
3050 void debrief_rebuild_player_list()
3054 debrief_multi_list_info *list;
3056 Multi_list_size = 0; // number of net players to choose from
3058 for ( i=0; i<MAX_PLAYERS; i++ ) {
3059 np = &Net_players[i];
3060 // remember not to include the standalone.
3061 if ( MULTI_CONNECTED((*np)) && !MULTI_STANDALONE((*np))){
3062 list = &Multi_list[Multi_list_size++];
3063 list->net_player_index = i;
3064 strcpy(list->callsign, np->player->callsign);
3066 // make sure to leave some room to blit the team indicator
3067 gr_force_fit_string(list->callsign, CALLSIGN_LEN - 1, Debrief_list_coords[gr_screen.res][2] - MULTI_LIST_TEAM_OFFSET);
3072 void debrief_handle_player_drop()
3074 debrief_rebuild_player_list();
3077 void debrief_disable_accept()