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.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
25 * Revision 1.11 2004/09/20 01:31:44 theoddone33
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
31 * Revision 1.9 2003/08/03 16:10:29 taylor
32 * cleanup; compile warning fixes
34 * Revision 1.8 2003/06/03 04:00:40 taylor
35 * Polish language support (Janusz Dziemidowicz)
37 * Revision 1.7 2003/05/25 02:30:43 taylor
40 * Revision 1.6 2002/07/13 06:46:48 theoddone33
43 * Revision 1.5 2002/06/09 04:41:23 relnev
44 * added copyright header
46 * Revision 1.4 2002/06/02 04:26:34 relnev
49 * Revision 1.3 2002/05/26 22:06:17 relnev
50 * makefile: disable stand_gui for now.
52 * rest: staticize some globals
54 * Revision 1.2 2002/05/07 03:16:46 theoddone33
55 * The Great Newline Fix
57 * Revision 1.1.1.1 2002/05/03 03:28:10 root
61 * 57 10/29/99 10:40p Jefff
62 * hack to make german medal names display without actually changing them
64 * 56 10/13/99 3:26p Jefff
65 * fixed unnumbered XSTRs
67 * 55 10/06/99 10:28a Jefff
70 * 54 9/30/99 5:57p Jefff
71 * show upsell at end of campaign in OEM builds
73 * 53 9/15/99 3:42a Jefff
76 * 52 9/14/99 4:35a Dave
77 * Argh. Added all kinds of code to handle potential crashes in debriefing
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.
84 * 50 9/14/99 12:51a Jefff
86 * 49 9/13/99 6:01p Jefff
87 * fixed wrong promotion voice mapping for sm1-08
89 * 48 9/13/99 11:15a Jefff
90 * clear out award text bug fixed
92 * 47 9/13/99 12:17p Andsager
93 * Fix traitor debrief not playinf for FS2. Don't append _3 or _1 as in
96 * 46 9/07/99 9:35p Jefff
97 * fixed bug where award text was not getting cleared properly between
100 * 45 9/07/99 6:56p Jefff
101 * a few adjustments to loop detection
103 * 44 9/07/99 1:54p Jefff
104 * skip mission cleanup
106 * 43 9/06/99 9:45p Jefff
107 * skip mission support
109 * 42 9/06/99 6:38p Dave
110 * Improved CD detection code.
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
118 * 40 9/02/99 3:45p Jefff
119 * forgot to remove some debug code. doh.
121 * 39 9/02/99 3:41p Jefff
122 * changed badge voice handling to be similar to promotion voice handling
124 * 38 9/01/99 4:41p Jefff
125 * fixed stoopid text color bug
127 * 37 8/31/99 11:54a Jefff
128 * minor debrief music tweak
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.
134 * 35 8/27/99 12:04a Dave
135 * Campaign loop screen.
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.
141 * 33 8/20/99 4:20p Jefff
142 * hack for choosing the correct promotion voice
144 * 32 8/16/99 4:05p Dave
145 * Big honking checkin.
147 * 31 8/16/99 9:49a Jefff
148 * mission title length fix in multi
150 * 30 8/11/99 5:33p Jefff
151 * added 3rd debrief music track
153 * 29 8/10/99 7:28p Jefff
154 * shuffled some text around
156 * 28 8/04/99 5:36p Andsager
157 * Show upsell screens at end of demo campaign before returning to main
160 * 27 8/04/99 2:07p Jefff
161 * mission title no longer overwrites popup
163 * 26 8/02/99 5:37p Jefff
165 * 25 8/02/99 4:52p Jefff
166 * negative feedback sound when recommendations button pressed and
169 * 24 7/21/99 6:21p Jefff
170 * added hotkeys to the "you cannot accept" popup
172 * 23 6/15/99 12:04p Anoop
173 * Added a warning for running out of debrief text lines.
175 * 22 6/09/99 2:17p Dave
176 * Fixed up pleasewait bitmap rendering.
178 * 21 6/01/99 6:07p Dave
179 * New loading/pause/please wait bar.
181 * 20 5/22/99 6:05p Dave
182 * Fixed a few localization # problems.
184 * 19 5/22/99 5:35p Dave
185 * Debrief and chatbox screens. Fixed small hi-res HUD bug.
187 * 18 3/20/99 3:47p Andsager
188 * Fix crash with no mission loop description.
190 * 17 2/23/99 2:29p Dave
191 * First run of oldschool dogfight mode.
193 * 16 2/21/99 6:01p Dave
194 * Fixed standalone WSS packets.
196 * 15 2/11/99 3:08p Dave
197 * PXO refresh button. Very preliminary squad war support.
199 * 14 1/30/99 5:08p Dave
200 * More new hi-res stuff.Support for nice D3D textures.
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.
206 * 12 1/14/99 5:15p Neilk
207 * changed credits, command debrief interfaces to high resolution support
209 * 11 1/13/99 2:11p Andsager
210 * change default debriefing string text
212 * 10 12/17/98 4:50p Andsager
213 * Added debrief_assemble_optional_mission_popup_text() for single and
216 * 9 12/12/98 3:17p Andsager
217 * Clean up mission eval, goal, event and mission scoring.
219 * 8 12/10/98 10:19a Andsager
220 * Fix mission loop assert
222 * 7 12/10/98 9:59a Andsager
223 * Fix some bugs with mission loops
225 * 6 12/09/98 1:56p Andsager
226 * Initial checkin of mission loop
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
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.
237 * 3 10/13/98 9:28a Dave
238 * Started neatening up freespace.h. Many variables renamed and
239 * reorganized. Added AlphaColors.[h,cpp]
241 * 2 10/07/98 10:53a Dave
244 * 1 10/07/98 10:49a Dave
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
251 * 177 7/07/98 1:46p Dave
252 * Fixed nasty debriefing badge/promotion bug. Added extra physics info
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
261 * 174 6/07/98 3:26p Lawrance
262 * Fix bug with cut-off popup text
264 * 173 6/05/98 9:54a Lawrance
267 * 172 6/01/98 11:43a John
268 * JAS & MK: Classified all strings for localization.
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
275 * 170 5/26/98 11:10a Lawrance
276 * Fix bug where window controls get disabled when F1 pressed twice
278 * 169 5/24/98 12:55a Mike
279 * Prevent Assert() when no debriefing text for a stage.
281 * 168 5/23/98 10:38p Lawrance
282 * Avoid doing a cfile refresh when running debug
284 * 167 5/23/98 6:49p Lawrance
285 * Fix problems with refreshing the file list when a CD is inserted
287 * 166 5/21/98 6:57p Lawrance
288 * Don't prompt for the CD if voice not found
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.
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.
298 * 163 5/19/98 11:13a Hoffoss
299 * Fixed bug where wrong wings award was being displayed in debriefing.
301 * 162 5/19/98 12:28a Mike
304 * 161 5/18/98 8:08p Hoffoss
305 * Moved placement of 'More' text.
307 * 160 5/18/98 3:50p Dan
308 * AL: Pick correct traitor debriefing voice file
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.
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
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.
325 * 156 5/15/98 4:36p Allender
326 * fixed minor bug with wings
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.
333 * 154 5/15/98 2:25p Jasen
334 * temporarily disable granting of promotion and badges for clients
336 * 153 5/15/98 10:57a Allender
337 * fixed client side debriefings
339 * 152 5/15/98 10:36a Dave
340 * Removed 2 bogus bitmap drawing Int3()'s
342 * 151 5/14/98 2:44p Hoffoss
343 * Added wings awarding to debrief screen.
345 * 150 5/13/98 9:11p Lawrance
346 * Make 'replay mission' popup warn users about the loss of mission stats.
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"
365 #include "audiostr.h"
368 #include "contexthelp.h"
374 #include "multimsgs.h"
375 #include "multiutil.h"
376 #include "multiteamselect.h"
378 #include "eventmusic.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"
391 #define MAX_TOTAL_DEBRIEF_LINES 200
393 #define TEXT_TYPE_NORMAL 1
394 #define TEXT_TYPE_RECOMMENDATION 2
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
402 // 3rd coord is max width in pixels
403 int Debrief_title_coords[GR_NUM_RESOLUTIONS][3] = {
416 int Debrief_text_wnd_coords[GR_NUM_RESOLUTIONS][4] = {
429 int Debrief_text_x2[GR_NUM_RESOLUTIONS] = {
434 int Debrief_stage_info_coords[GR_NUM_RESOLUTIONS][2] = {
447 int Debrief_more_coords[GR_NUM_RESOLUTIONS][2] = {
460 #define MULTI_LIST_TEAM_OFFSET 16
462 int Debrief_multi_list_team_max_display[GR_NUM_RESOLUTIONS] = {
467 int Debrief_list_coords[GR_NUM_RESOLUTIONS][4] = {
476 int Debrief_award_wnd_coords[GR_NUM_RESOLUTIONS][2] = {
489 int Debrief_award_coords[GR_NUM_RESOLUTIONS][2] = {
503 int Debrief_rank_coords[2] = {
507 int Debrief_badge_coords[2] = {
513 // 0=x, 1=y, 2=width of the field
514 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][3] = {
523 // 0=x, 1=y, 2=height of the field
524 int Debrief_award_text_coords[GR_NUM_RESOLUTIONS][3] = {
533 // the medal text in FS1 is a bitmap
534 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][2] = {
543 int Debrief_rank_text_coords[GR_NUM_RESOLUTIONS][2] = {
552 int Debrief_badge_text_coords[GR_NUM_RESOLUTIONS][2] = {
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] = {
575 char *Debrief_single_name[GR_NUM_RESOLUTIONS] = {
576 "DebriefSingle", // GR_640
577 "2_DebriefSingle" // GR_1024
579 char *Debrief_multi_name[GR_NUM_RESOLUTIONS] = {
580 "DebriefMulti", // GR_640
581 "2_DebriefMulti" // GR_1024
583 char *Debrief_mask_name[GR_NUM_RESOLUTIONS] = {
584 "Debrief-m", // GR_640
585 "2_Debrief-m" // GR_1024
588 #define NUM_BUTTONS 18
591 #define DEBRIEF_TAB 0
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
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
613 char* Debrief_loading_bitmap_fname[GR_NUM_RESOLUTIONS] = {
614 "PleaseWait", // GR_640
615 "2_PleaseWait" // GR_1024
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;
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;
631 static ui_button_info Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
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
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
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
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] = {
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 },
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 },
730 char Debrief_current_callsign[CALLSIGN_LEN+10];
731 player *Debrief_player;
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;
744 static int Rank_text_bitmap;
745 static int Medal_text_bitmap;
746 static int Badge_text_bitmap;
749 static int Debrief_accepted;
750 static int Turned_traitor;
751 static int Must_replay_mission;
753 static int Current_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];
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;
770 static int Multi_list_size;
771 static int Multi_list_offset;
773 int Debrief_multi_stages_loaded = 0;
774 int Debrief_multi_voice_loaded = 0;
776 // static int Debrief_voice_ask_for_cd;
778 // voice id's for debriefing text
779 static int Debrief_voices[MAX_DEBRIEF_STAGES];
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
785 // pointer used for getting to debriefing information
786 debriefing Traitor_debriefing; // used when player is a traitor
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;
795 // flag indicating if we should display info for the given player (in multiplayer)
796 int Debrief_should_show_popup = 1;
798 // already shown skip mission popup?
799 static int Debrief_skip_popup_already_shown = 0;
801 void debrief_text_init();
802 void debrief_accept(int ok_to_post_start_game_event = 1);
803 void debrief_kick_selected_player();
806 // promotion voice selection stuff
807 #define NUM_VOLITION_CAMPAIGNS 1
809 char campaign_name[32];
811 } Volition_campaigns[NUM_VOLITION_CAMPAIGNS] = {
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
818 // data for which voice goes w/ which mission
819 typedef struct voice_map {
820 char mission_file[32];
824 voice_map Debrief_promotion_voice_mapping[NUM_VOLITION_CAMPAIGNS][MAX_CAMPAIGN_MISSIONS] = {
825 { // FreeSpace2 campaign
857 { "SM3-10.fs2", 9 }, // no debriefing for 3-10
859 { "loop1-1.fs2", 4 },
860 { "loop1-2.fs2", 4 },
861 { "loop1-3.fs2", 5 },
862 { "loop2-1.fs2", 4 },
867 #define DB_AWARD_WINGS 0
868 #define DB_AWARD_MEDAL 1
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] = {
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] = {
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;
921 // prototypes, you know you love 'em
922 void debrief_add_award_text(char *str);
923 void debrief_award_text_clear();
928 char *debrief_tooltip_handler(char *str)
930 if (!stricmp(str, NOX("@.Medal"))) {
932 return XSTR( "Medal", 435);
935 } else if (!stricmp(str, NOX("@.Rank"))) {
937 return XSTR( "Rank", 436);
940 } else if (!stricmp(str, NOX("@.Badge"))) {
942 return XSTR( "Badge", 437);
945 } else if (!stricmp(str, NOX("@Medal"))) {
946 if (Medal_bitmap >= 0){
947 return Medals[Player->stats.m_medal_earned].name;
950 } else if (!stricmp(str, NOX("@Rank"))) {
951 if (Rank_bitmap >= 0){
952 return Ranks[Promoted].name;
955 } else if (!stricmp(str, NOX("@Badge"))) {
956 if (Badge_bitmap >= 0){
957 return Medals[Badge_index[Player->stats.m_badge_earned]].name;
964 // initialize the array of handles to the different voice streams
965 void debrief_voice_init()
969 for (i=0; i<MAX_DEBRIEF_STAGES; i++) {
970 Debrief_voices[i] = -1;
974 void debrief_load_voice_file(int voice_num, char *name)
976 int load_attempts = 0;
979 if ( load_attempts++ > 5 ) {
983 Debrief_voices[voice_num] = audiostream_open( name, ASF_VOICE );
984 if ( Debrief_voices[voice_num] >= 0 ) {
988 // Don't bother to ask for the CD in multiplayer
989 if ( Game_mode & GM_MULTIPLAYER ) {
993 // couldn't load voice, ask user to insert CD (if necessary)
995 // if ( Debrief_voice_ask_for_cd ) {
996 // if ( game_do_cd_check() == 0 ) {
997 // Debrief_voice_ask_for_cd = 0;
1004 // open and pre-load the stream buffers for the different voice streams
1005 void debrief_voice_load_all()
1009 // Debrief_voice_ask_for_cd = 1;
1011 for ( i=0; i<Num_debrief_stages; i++ ) {
1012 if ( strlen(Debrief_stages[i]->voice) <= 0 ) {
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);
1022 // close all the briefing voice streams
1023 void debrief_voice_unload_all()
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;
1035 // start playback of the voice for a particular briefing stage
1036 void debrief_voice_play()
1038 if (!Briefing_voice_enabled || (Current_mode != DEBRIEF_TAB)){
1042 // no more stages? We are done then.
1043 if (Stage_voice >= Num_debrief_stages){
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)){
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
1062 // see if voice is still playing. If so, do nothing yet.
1063 if ((Stage_voice >= 0) && audiostream_is_playing(Debrief_voices[Stage_voice])){
1067 // set voice to play in a little while from now.
1068 Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY);
1071 // stop playback of the voice for a particular briefing stage
1072 void debrief_voice_stop()
1074 if ((Stage_voice < 0) || (Stage_voice > Num_debrief_stages) || (Debrief_voices[Stage_voice] < 0))
1077 audiostream_stop(Debrief_voices[Stage_voice]); // stream is automatically rewound
1081 // function to deal with inserting possible promition and badge stages into the debriefing
1083 void debrief_multi_fixup_stages()
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];
1094 Debrief_stages[0] = &Badge_stage;
1095 Num_debrief_stages++;
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];
1103 Debrief_stages[0] = &Promotion_stage;
1104 Num_debrief_stages++;
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[] )
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];
1119 Debriefing = &Debriefings[0];
1122 // see if this client was promoted -- if so, then add the first stage.
1123 Num_debrief_stages = 0;
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]];
1130 Debrief_multi_stages_loaded = 1;
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()
1137 debriefing *debriefp;
1139 int stage_active[MAX_TEAMS][MAX_DEBRIEF_STAGES], *stages[MAX_TEAMS];
1140 int i, j, num_stages, stage_count[MAX_TEAMS];
1142 memset( stage_active, 0, sizeof(stage_active) );
1144 for (i=0; i<Num_teams; i++) {
1145 debriefp = &Debriefings[i];
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;
1155 stage_count[i] = num_stages;
1158 // if we're in campaign mode, evaluate campaign stuff
1159 if (Netgame.campaign_mode == MP_CAMPAIGN) {
1160 multi_campaign_eval_debrief();
1163 // send the information to all clients.
1164 send_debrief_info( stage_count, stages );
1168 // --------------------------------------------------------------------------------------
1169 // debrief_set_stages_and_multi_stuff()
1171 // Set up the active stages for this debriefing
1173 // returns: number of active debriefing stages
1175 int debrief_set_stages_and_multi_stuff()
1178 debriefing *debriefp;
1180 if ( MULTIPLAYER_CLIENT ) {
1184 Num_debrief_stages = 0;
1186 if ( Game_mode & GM_MULTIPLAYER ) {
1187 debrief_multi_server_stuff();
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;
1198 Num_debrief_stages = 0;
1199 if (Promoted >= 0) {
1200 Debrief_stages[Num_debrief_stages++] = &Promotion_stage;
1203 if (Badge_bitmap >= 0) {
1204 Debrief_stages[Num_debrief_stages++] = &Badge_stage;
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];
1213 return Num_debrief_stages;
1216 // init the buttons that are specific to the debriefing screen
1217 void debrief_buttons_init()
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);
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]);
1243 Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
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);
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();
1266 // --------------------------------------------------------------------------------------
1267 // debrief_ui_init()
1269 void debrief_ui_init()
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();
1278 // load in help overlay bitmap
1279 help_overlay_load(DEBRIEFING_OVERLAY);
1280 help_overlay_set_state(DEBRIEFING_OVERLAY,0);
1282 if ( Game_mode & GM_MULTIPLAYER ) {
1283 // close down any old instances of the chatbox
1286 // create the new one
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);
1292 Background_bitmap = bm_load(Debrief_single_name[gr_screen.res]);
1295 if ( Background_bitmap < 0 ) {
1296 Warning(LOCATION, "Could not load the background bitmap for debrief screen");
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]);
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()
1310 if(Campaign.current_mission < 0){
1311 sprintf(Promotion_stage.voice, NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
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);
1331 // default to petrarch
1332 sprintf(Promotion_stage.voice, NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
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()
1344 if(Campaign.current_mission < 0){
1346 // default to petrarch
1347 sprintf(Badge_stage.voice, NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1349 // default to FS1 guy
1350 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1354 if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename)) {
1356 if ( Player->on_bastion ) {
1357 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base2);
1360 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
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);
1381 // default to petrarch
1382 sprintf(Badge_stage.voice, NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1384 // default to FS1 guy
1385 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1390 void debrief_award_init()
1402 // be sure there are no old award texts floating around
1404 debrief_award_text_clear();
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..
1411 if ( Player->stats.medals[13] > 1 ) {
1416 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_WINGS], ver);
1417 Wings_bitmap = bm_load(buf);
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]);
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);
1428 debrief_add_award_text(Medals[Player->stats.m_medal_earned].name);
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);
1438 Promotion_stage.new_text = Ranks[Promoted].promotion_text;
1439 Promotion_stage.new_recommendation_text = NULL;
1441 // choose appropriate promotion voice for this mission
1442 debrief_choose_promotion_voice();
1445 debrief_add_award_text(Ranks[Promoted].name);
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);
1456 Badge_stage.new_text = Badge_info[i].promotion_text;
1457 Badge_stage.new_recommendation_text = NULL;
1459 // choose appropriate voice
1460 debrief_choose_badge_voice();
1463 debrief_add_award_text(Medals[Badge_index[i]].name);
1467 if ((Rank_bitmap >= 0) || (Medal_bitmap >= 0) || (Badge_bitmap >= 0) || (Wings_bitmap >= 0) || (Crest_bitmap >= 0)) {
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()
1478 static int inited = 0;
1481 debriefing *debrief;
1482 debrief_stage *stagep;
1486 if ((rval = setjmp(parse_abort)) != 0) {
1487 Error(LOCATION, "Unable to parse traitor.tbl! Code = %i.\n", rval);
1490 read_file_text("traitor.tbl");
1494 // open localization
1497 // simplied form of the debriefing stuff.
1498 debrief = &Traitor_debriefing;
1499 required_string("#Debriefing_info");
1501 required_string("$Num stages:");
1502 stuff_int(&debrief->num_stages);
1503 Assert(debrief->num_stages == 1);
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);
1513 stagep->new_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1515 required_string("$Voice:");
1516 char traitor_voice_file[NAME_LENGTH];
1517 stuff_string(traitor_voice_file, F_FILESPEC, NULL);
1519 // DKA 9/13/99 Only 1 traitor msg for FS2
1521 if ( Player->on_bastion ) {
1522 strcpy(stagep->voice, NOX("3_"));
1524 strcpy(stagep->voice, NOX("1_"));
1528 strcat(stagep->voice, traitor_voice_file);
1530 required_string("$Recommendation text:");
1531 if ( Fred_running ) {
1532 stuff_string( stagep->new_recommendation_text, F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1534 stagep->new_recommendation_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1538 // close localization
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){
1550 if (Campaign.next_mission == Campaign.current_mission){
1551 Must_replay_mission = 1;
1555 if (Turned_traitor || Must_replay_mission) {
1556 Buttons[gr_screen.res][ACCEPT_BUTTON].button.hide();
1558 // kill off any stats
1559 Player->flags &= ~PLAYER_FLAGS_PROMOTED;
1560 scoring_level_init( &Player->stats );
1564 // initialization for listing of players in game
1565 void debrief_multi_list_init()
1567 Multi_list_size = 0; // number of net players to choose from
1568 Multi_list_offset = 0;
1570 Multi_list_select = -1;
1572 if ( !(Game_mode & GM_MULTIPLAYER) )
1575 debrief_rebuild_player_list();
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;
1583 void debrief_multi_list_scroll_up()
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);
1591 // otherwise scroll up
1592 Multi_list_offset--;
1593 gamesnd_play_iface(SND_USER_SELECT);
1596 void debrief_multi_list_scroll_down()
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);
1603 if((Multi_list_offset + Debrief_multi_list_team_max_display[gr_screen.res]) >= Multi_list_size){
1604 gamesnd_play_iface(SND_GENERAL_FAIL);
1608 // otherwise scroll down
1609 Multi_list_offset++;
1610 gamesnd_play_iface(SND_USER_SELECT);
1613 // draw the connected net players
1614 void debrief_multi_list_draw()
1616 int y, z, font_height,idx;
1617 char str[CALLSIGN_LEN+5];
1620 font_height = gr_get_font_height();
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;
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;
1639 // draw the list itself
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];
1645 if (z >= Multi_list_size){
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);
1653 gr_set_color_fast(&Color_bright);
1656 if(Multi_list_select == z){
1657 gr_set_color_fast(&Color_text_active);
1659 gr_set_color_fast(&Color_text_normal);
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){
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);
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);
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);
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);
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);
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));
1705 gr_string(Debrief_list_coords[gr_screen.res][0] + MULTI_LIST_TEAM_OFFSET, Debrief_list_coords[gr_screen.res][1] + y, str);
1712 void debrief_kick_selected_player()
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);
1720 // get optional mission popup text
1721 void debrief_assemble_optional_mission_popup_text(char *buffer, char *mission_loop_desc)
1723 Assert(buffer != NULL);
1726 if (mission_loop_desc == NULL) {
1727 strcpy(buffer, XSTR("<No Mission Loop Description Available>", 1490));
1728 mprintf(("No mission loop description avail"));
1730 strcpy(buffer, mission_loop_desc);
1733 strcat(buffer, XSTR("\n\n\nDo you want to play the optional mission?", 1491));
1736 // what to do when the accept button is hit
1737 void debrief_accept(int ok_to_post_start_game_event)
1741 if ( (/*Cheats_enabled ||*/ Turned_traitor || Must_replay_mission) && (Game_mode & GM_CAMPAIGN_MODE) ) {
1745 if (Game_mode & GM_MULTIPLAYER) {
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);
1754 str = XSTR( "You have failed this mission and cannot accept. What do you you wish to do instead?", 441);
1757 z = popup(0, 3, XSTR( "Return to &Debriefing", 442), XSTR( "Go to &Flight Deck", 443), XSTR( "&Replay Mission", 444), str);
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
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();
1776 int play_commit_sound = 1;
1777 // only write the player's stats if he's accepted
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 ) {
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);
1793 if ( (Campaign.missions[cur].has_mission_loop && (Campaign.loop_mission != -1)) && !require_repeat_mission ) {
1796 debrief_assemble_optional_mission_popup_text(buffer, Campaign.missions[cur].mission_loop_desc);
1798 int choice = popup(0 , 2, POPUP_NO, POPUP_YES, buffer);
1800 Campaign.loop_enabled = 1;
1801 Campaign.next_mission = Campaign.loop_mission;
1810 if(ok_to_post_start_game_event){
1811 gameseq_post_event(GS_EVENT_LOOP_BRIEF);
1813 play_commit_sound = 0;
1816 // continue as normal
1819 mission_campaign_mission_over();
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;
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);
1831 gameseq_post_event(GS_EVENT_MAIN_MENU);
1834 if ( ok_to_post_start_game_event ) {
1836 if(game_do_cd_mission_check(Game_current_mission_filename)){
1837 gameseq_post_event(GS_EVENT_START_GAME);
1839 gameseq_post_event(GS_EVENT_MAIN_MENU);
1842 play_commit_sound = 0;
1847 gameseq_post_event(GS_EVENT_MAIN_MENU);
1850 if ( play_commit_sound ) {
1851 gamesnd_play_iface(SND_COMMIT_PRESSED);
1858 void debrief_next_tab()
1860 New_mode = Current_mode + 1;
1861 if (New_mode >= NUM_TABS)
1865 void debrief_prev_tab()
1867 New_mode = Current_mode - 1;
1869 New_mode = NUM_TABS - 1;
1872 // --------------------------------------------------------------------------------------
1873 // debrief_next_stage()
1875 void debrief_next_stage()
1877 if (Current_stage < Num_stages - 1) {
1878 New_stage = Current_stage + 1;
1879 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1882 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1885 // --------------------------------------------------------------------------------------
1886 // debrief_prev_stage()
1888 void debrief_prev_stage()
1890 if (Current_stage) {
1891 New_stage = Current_stage - 1;
1892 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1895 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1898 // --------------------------------------------------------------------------------------
1899 // debrief_first_stage()
1900 void debrief_first_stage()
1902 if (Current_stage) {
1904 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1907 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1910 // --------------------------------------------------------------------------------------
1911 // debrief_last_stage()
1912 void debrief_last_stage()
1914 if (Current_stage != Num_stages - 1) {
1915 New_stage = Num_stages - 1;
1916 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1919 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1922 // draw what stage number the debriefing is on
1923 void debrief_render_stagenum()
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);
1938 // render the mission time at the specified y location
1939 void debrief_render_mission_time(int y_loc)
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);
1948 // render out the debriefing text to the scroll window
1949 void debrief_render()
1951 int y, z, font_height;
1953 if ( Num_stages <= 0 )
1956 font_height = gr_get_font_height();
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]);
1961 while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
1962 if (z >= Num_text_lines)
1965 if (Text_type[z] == TEXT_TYPE_NORMAL)
1966 gr_set_color_fast(&Color_white);
1968 gr_set_color_fast(&Color_bright_red);
1971 gr_string(0, y, Text[z]);
1980 // render out the stats info to the scroll window
1982 void debrief_stats_render()
1984 int i, y, font_height;
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();
1992 switch ( Current_stage ) {
1993 case DEBRIEF_MISSION_STATS:
1994 i = Current_stage - 1;
1998 gr_set_color_fast(&Color_white);
2000 // display mission completion time
2001 debrief_render_mission_time(y);
2004 show_stats_label(i, 0, y, font_height);
2005 show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2007 case DEBRIEF_ALLTIME_STATS:
2008 i = Current_stage - 1;
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);
2017 case DEBRIEF_ALLTIME_KILLS:
2018 case DEBRIEF_MISSION_KILLS:
2019 gr_set_color_fast(&Color_white);
2021 while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
2022 if (i >= Num_text_lines)
2026 if ( Current_stage == DEBRIEF_MISSION_KILLS )
2027 gr_printf(0, y, XSTR( "Mission Kills by Ship Type", 447));
2029 gr_printf(0, y, XSTR( "All-time Kills by Ship Type", 448));
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);
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));
2044 gr_printf(0, y, XSTR( "(No ship kills)", 450));
2057 // do action for when the replay button is pressed
2058 void debrief_replay_pressed()
2060 if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
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));
2069 gameseq_post_event(GS_EVENT_START_BRIEFING); // take us to the briefing
2070 gamesnd_play_iface(SND_COMMIT_PRESSED);
2073 // -------------------------------------------------------------------
2074 // debrief_redraw_pressed_buttons()
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)
2080 void debrief_redraw_pressed_buttons()
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() ) {
2094 // debrief specific button with hotspot 'i' has been pressed, so perform the associated action
2096 void debrief_button_pressed(int num)
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);
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);
2116 case TEXT_SCROLL_UP:
2119 gamesnd_play_iface(SND_SCROLL);
2121 gamesnd_play_iface(SND_GENERAL_FAIL);
2125 case TEXT_SCROLL_DOWN:
2126 if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
2128 gamesnd_play_iface(SND_SCROLL);
2130 gamesnd_play_iface(SND_GENERAL_FAIL);
2134 case REPLAY_MISSION:
2135 if(Game_mode & GM_MULTIPLAYER){
2136 multi_debrief_replay_hit();
2138 debrief_replay_pressed();
2142 case RECOMMENDATIONS:
2143 gamesnd_play_iface(SND_USER_SELECT);
2144 Recommend_active = !Recommend_active;
2145 debrief_text_init();
2149 debrief_first_stage();
2153 debrief_prev_stage();
2157 debrief_next_stage();
2161 debrief_last_stage();
2165 gamesnd_play_iface(SND_HELP_PRESSED);
2166 launch_context_help();
2169 case OPTIONS_BUTTON:
2170 gamesnd_play_iface(SND_SWITCH_SCREENS);
2171 gameseq_post_event( GS_EVENT_OPTIONS_MENU );
2179 gamesnd_play_iface(SND_SWITCH_SCREENS);
2180 gameseq_post_event(GS_EVENT_VIEW_MEDALS);
2183 case PLAYER_SCROLL_UP:
2184 debrief_multi_list_scroll_up();
2187 case PLAYER_SCROLL_DOWN:
2188 debrief_multi_list_scroll_down();
2191 case MULTI_PINFO_POPUP:
2192 Debrief_should_show_popup = 1;
2196 debrief_kick_selected_player();
2201 void debrief_setup_ship_kill_stats(int stage_num)
2205 debrief_stats_kill_info *kill_info;
2207 Assert(Current_stage < DEBRIEF_NUM_STATS_PAGES);
2208 if ( Current_stage == DEBRIEF_MISSION_STATS || Current_stage == DEBRIEF_ALLTIME_STATS )
2211 Assert(Debrief_player != NULL);
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;
2217 kill_arr = Debrief_player->stats.kills;
2221 for ( i=0; i<MAX_SHIP_TYPES; i++ ) {
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 ){
2230 kill_info = &Debrief_stats_kills[Num_text_lines++];
2232 kill_info->num = kill_arr[i];
2234 strcpy(kill_info->text, Ship_info[i].name);
2235 strcat(kill_info->text, NOX(":"));
2238 Num_text_lines += 2;
2241 // Iterate through the debriefing buttons, checking if they are pressed
2242 void debrief_check_buttons()
2246 for ( i=0; i<NUM_BUTTONS; i++ ) {
2247 if ( Buttons[gr_screen.res][i].button.pressed() ) {
2248 debrief_button_pressed(i);
2252 if ( !(Game_mode & GM_MULTIPLAYER) )
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);
2269 // if the player was double clicked on - we should popup a player info popup
2271 if (List_region.double_clicked()) {
2272 Debrief_should_show_popup = 1;
2277 void debrief_text_stage_init(char *src, int type)
2279 int i, n_lines, n_chars[MAX_DEBRIEF_LINES];
2280 char line[MAX_DEBRIEF_LINE_LEN];
2281 char *p_str[MAX_DEBRIEF_LINES];
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);
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");
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);
2304 void debrief_free_text()
2308 for (i=0; i<Num_debrief_lines; i++)
2312 Num_debrief_lines = 0;
2315 // setup the debriefing text lines for rendering
2316 void debrief_text_init()
2321 // release old text lines first
2322 debrief_free_text();
2323 Num_text_lines = Text_offset = 0;
2325 if (Current_mode == DEBRIEF_TAB) {
2326 for (i=0; i<Num_debrief_stages; i++) {
2328 Text[Num_text_lines++] = NULL; // add a blank line between stages
2330 src = Debrief_stages[i]->new_text;
2332 debrief_text_stage_init(src, TEXT_TYPE_NORMAL);
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);
2340 Text[Num_text_lines++] = NULL;
2341 debrief_text_stage_init(src, TEXT_TYPE_RECOMMENDATION);
2347 Num_debrief_lines = Num_text_lines;
2351 // not in debriefing mode, must be in stats mode
2353 debrief_setup_ship_kill_stats(Current_stage);
2357 // --------------------------------------------------------------------------------------
2361 Assert(!Debrief_inited);
2362 // Campaign.loop_enabled = 0;
2363 Campaign.loop_mission = CAMPAIGN_LOOP_MISSION_UNINITIALIZED;
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];
2369 Debriefing = &Debriefings[0];
2372 // no longer is mission
2373 Game_mode &= ~(GM_IN_MISSION);
2377 New_mode = DEBRIEF_TAB;
2378 Recommend_active = Award_active = 0;
2383 Debrief_cue_voice = 0;
2384 Num_text_lines = Num_debrief_lines = 0;
2385 Debrief_first_voice_flag = 1;
2387 Debrief_multi_voice_loaded = 0;
2390 Medal_text_bitmap = bm_load(NOX("DebriefText01"));
2391 Rank_text_bitmap = bm_load(NOX("DebriefText02"));
2392 Badge_text_bitmap = bm_load(NOX("DebriefText03"));
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();
2400 // evaluate next mission
2401 mission_campaign_eval_next_mission();
2404 // call traitor init before calling scoring_level_close. traitor init will essentially nullify
2406 if ( !(Game_mode & GM_MULTIPLAYER) ) { // only do for single player
2407 debrief_traitor_init(); // initialize data needed if player becomes traitor.
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();
2414 debrief_ui_init(); // init UI items
2415 debrief_award_init();
2417 debrief_voice_init();
2418 debrief_multi_list_init();
2419 // rank_bitmaps_clear();
2420 // rank_bitmaps_load();
2422 strcpy(Debrief_current_callsign, Player->callsign);
2423 Debrief_player = Player;
2424 // Debrief_current_net_player_index = debrief_multi_list[0].net_player_index;
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();
2432 if ( Num_debrief_stages <= 0 ) {
2433 Num_debrief_stages = 0;
2435 debrief_voice_load_all();
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;
2446 if (mission_evaluate_primary_goals() == PRIMARY_GOALS_COMPLETE) {
2447 common_music_init(SCORE_DEBRIEF_SUCCESS);
2449 common_music_init(SCORE_DEBRIEF_FAIL);
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);
2461 // you somehow passed the mission, so you get a little something for your efforts.
2462 common_music_init(SCORE_DEBRIEF_AVERAGE);
2465 if (Campaign.next_mission == Campaign.current_mission) {
2466 // better luck next time, increase his retries
2467 Player->failures_this_session++;
2469 // clear his retries info regardless of whether or not he accepts
2470 Player->failures_this_session = 0;
2473 if (Game_mode & GM_MULTIPLAYER) {
2474 multi_debrief_init();
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();
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();
2491 if (!Award_active) {
2492 Buttons[gr_screen.res][MEDALS_BUTTON].button.disable();
2493 Buttons[gr_screen.res][MEDALS_BUTTON].button.hide();
2496 Debrief_skip_popup_already_shown = 0;
2501 // --------------------------------------------------------------------------------------
2503 void debrief_close()
2507 Assert(Debrief_inited);
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);
2522 scoring_backout_accept( &Player->stats );
2527 if( !Debrief_accepted || !(Game_mode & GM_CAMPAIGN_MODE) ){
2528 scoring_backout_accept( &Player->stats );
2532 // if dude passed the misson and accepted, reset his show skip popup flag
2533 if (Debrief_accepted) {
2534 Player->show_skip_popup = 1;
2537 if (Num_debrief_lines) {
2538 for (i=0; i<Num_debrief_lines; i++){
2545 // clear out debrief info parsed from mission file
2546 mission_debrief_common_reset();
2548 // unload the overlay bitmap
2550 help_overlay_unload(DEBRIEFING_OVERLAY);
2553 // clear out award text
2554 Debrief_award_text_num_lines = 0;
2556 debrief_voice_unload_all();
2557 common_music_close();
2560 // rank_bitmaps_release();
2563 if (Background_bitmap >= 0){
2564 bm_unload(Background_bitmap);
2567 if (Award_bg_bitmap >= 0){
2568 bm_unload(Award_bg_bitmap);
2571 if (Rank_bitmap >= 0){
2572 bm_unload(Rank_bitmap);
2575 if (Medal_bitmap >= 0){
2576 bm_unload(Medal_bitmap);
2579 if (Badge_bitmap >= 0){
2580 bm_unload(Badge_bitmap);
2583 if (Wings_bitmap >= 0) {
2584 bm_unload(Wings_bitmap);
2587 if (Crest_bitmap >= 0) {
2588 bm_unload(Crest_bitmap);
2592 if (Medal_text_bitmap >= 0) {
2593 bm_unload(Medal_text_bitmap);
2596 if (Badge_text_bitmap >= 0) {
2597 bm_unload(Badge_text_bitmap);
2600 if (Rank_text_bitmap >= 0) {
2601 bm_unload(Rank_text_bitmap);
2605 Debrief_ui_window.destroy();
2606 common_free_interface_palette(); // restore game palette
2609 if (Game_mode & GM_MULTIPLAYER){
2610 multi_debrief_close();
2618 // handle keypresses in debriefing
2619 void debrief_do_keys(int new_k)
2626 case KEY_SHIFTED | KEY_TAB:
2634 // multiplayer accept popup is a little bit different
2635 if (Game_mode & GM_MULTIPLAYER) {
2636 multi_debrief_esc_hit();
2638 // display the normal debrief popup
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
2645 gameseq_post_event(GS_EVENT_MAIN_MENU);
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));
2658 // Return to Main Hall
2659 gameseq_post_event(GS_EVENT_END_GAME);
2670 void debrief_draw_award_text()
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];
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);
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]);
2688 // adjust y pos, including a little extra between the "pairs"
2690 if ((i == 1) || (i == 3)) {
2691 curr_y += ((gr_screen.res == GR_640) ? 2 : 6);
2696 // clears out text array so we dont have old award text showing up on new awards.
2697 void debrief_award_text_clear() {
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);
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)
2710 Assert(Debrief_award_text_num_lines <= AWARD_TEXT_MAX_LINES);
2711 if (Debrief_award_text_num_lines > AWARD_TEXT_MAX_LINES) {
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];
2719 strcpy(Debrief_award_text[Debrief_award_text_num_lines], str);
2721 // maybe translate for displaying
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);
2728 Debrief_award_text_num_lines++;
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
2737 Debrief_award_text_num_lines++; // leave blank line even if it all fits into 1
2740 #endif // !MAKE_FS1: No text for FS1, it's all bitmaps
2742 // called once per frame to drive all the input reading and rendering
2743 void debrief_do_frame(float frametime)
2746 char *please_wait_str = XSTR("Please Wait", 1242);
2750 Assert(Debrief_inited);
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);
2761 Debrief_ui_window.draw();
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] );
2768 // draw "Please Wait"
2769 gr_set_color_fast(&Color_normal);
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);
2777 // make sure we run the debrief do frame
2778 if (Game_mode & GM_MULTIPLAYER) {
2779 multi_debrief_do_frame();
2784 int keypress = game_check_key();
2785 if(keypress == KEY_ESC){
2787 multi_quit_game(PROMPT_CLIENT);
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;
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);
2805 k = chatbox_process();
2806 if ( Game_mode & GM_NORMAL ) {
2807 new_k = Debrief_ui_window.process(k);
2809 new_k = Debrief_ui_window.process(k, 0);
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);
2821 if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
2822 Debrief_ui_window.set_ignore_gadgets(0);
2825 // don't show pilot info popup by default
2826 Debrief_should_show_popup = 0;
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;
2834 if (New_mode == DEBRIEF_TAB) {
2836 Debrief_cue_voice = 0;
2838 if (Debrief_first_voice_flag) {
2839 Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY * 3);
2840 Debrief_first_voice_flag = 0;
2843 Num_stages = DEBRIEF_NUM_STATS_PAGES;
2847 if ((Num_stages > 0) && (New_stage != Current_stage)) {
2848 Current_stage = New_stage;
2849 debrief_text_init();
2852 debrief_voice_play();
2855 if (Game_mode & GM_MULTIPLAYER) {
2856 multi_debrief_do_frame();
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);
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);
2873 gr_bitmap(Debrief_rank_coords[0], Debrief_rank_coords[1]);
2875 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
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]);
2884 if (Badge_bitmap >= 0) {
2885 gr_set_bitmap(Badge_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2887 gr_bitmap(Debrief_badge_coords[0], Debrief_badge_coords[1]);
2889 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2893 if (Wings_bitmap >= 0) {
2894 gr_set_bitmap(Wings_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2896 gr_bitmap(Debrief_badge_coords[0], Debrief_badge_coords[1]);
2898 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
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]);
2908 // draw medal/badge/rank labels
2910 debrief_draw_award_text();
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]);
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]);
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]);
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);
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);
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);
2947 // draw the screen-specific text
2948 switch (Current_mode) {
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);
2962 debrief_stats_render();
2966 if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
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));
2974 debrief_render_stagenum();
2975 debrief_multi_list_draw();
2977 // render some extra stuff in multiplayer
2978 if (Game_mode & GM_MULTIPLAYER) {
2979 // render the chatbox last
2983 Debrief_ui_window.draw_tooltip();
2985 // render the status indicator for the voice system
2986 multi_common_voice_display_status();
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
2992 if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
2993 debrief_check_buttons();
2994 debrief_do_keys(new_k);
2997 // blit help overlay if active
2998 help_overlay_maybe_blit(DEBRIEFING_OVERLAY);
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;
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) {
3019 // stay on this mission, so proceed to normal debrief
3020 // in other words, do nothing.
3023 // skip this mission
3024 mission_campaign_skip_to_next();
3025 gameseq_post_event(GS_EVENT_START_GAME);
3028 // dont show this again
3029 Player->show_skip_popup = 0;
3033 Debrief_skip_popup_already_shown = 1;
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]);
3041 Debrief_should_show_popup = 0;
3045 void debrief_rebuild_player_list()
3049 debrief_multi_list_info *list;
3051 Multi_list_size = 0; // number of net players to choose from
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);
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);
3067 void debrief_handle_player_drop()
3069 debrief_rebuild_player_list();
3072 void debrief_disable_accept()