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.14 2006/04/26 19:43:25 taylor
19 * this should squash the first second double-play of debriefing voice
21 * Revision 1.13 2005/08/12 08:52:32 taylor
22 * various GCC4 warning fixes
24 * Revision 1.12 2005/03/29 02:18:47 taylor
25 * Various 64-bit platform fixes
26 * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
27 * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
28 * Streaming audio support (big thanks to Pierre Willenbrock!!)
29 * Removed dependance on strings.tbl for FS1 since we don't actually need it now
31 * Revision 1.11 2004/09/20 01:31:44 theoddone33
34 * Revision 1.10 2004/07/04 11:39:06 taylor
35 * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
37 * Revision 1.9 2003/08/03 16:10:29 taylor
38 * cleanup; compile warning fixes
40 * Revision 1.8 2003/06/03 04:00:40 taylor
41 * Polish language support (Janusz Dziemidowicz)
43 * Revision 1.7 2003/05/25 02:30:43 taylor
46 * Revision 1.6 2002/07/13 06:46:48 theoddone33
49 * Revision 1.5 2002/06/09 04:41:23 relnev
50 * added copyright header
52 * Revision 1.4 2002/06/02 04:26:34 relnev
55 * Revision 1.3 2002/05/26 22:06:17 relnev
56 * makefile: disable stand_gui for now.
58 * rest: staticize some globals
60 * Revision 1.2 2002/05/07 03:16:46 theoddone33
61 * The Great Newline Fix
63 * Revision 1.1.1.1 2002/05/03 03:28:10 root
67 * 57 10/29/99 10:40p Jefff
68 * hack to make german medal names display without actually changing them
70 * 56 10/13/99 3:26p Jefff
71 * fixed unnumbered XSTRs
73 * 55 10/06/99 10:28a Jefff
76 * 54 9/30/99 5:57p Jefff
77 * show upsell at end of campaign in OEM builds
79 * 53 9/15/99 3:42a Jefff
82 * 52 9/14/99 4:35a Dave
83 * Argh. Added all kinds of code to handle potential crashes in debriefing
86 * 51 9/14/99 3:26a Dave
87 * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
88 * respawn-too-early problem. Made a few crash points safe.
90 * 50 9/14/99 12:51a Jefff
92 * 49 9/13/99 6:01p Jefff
93 * fixed wrong promotion voice mapping for sm1-08
95 * 48 9/13/99 11:15a Jefff
96 * clear out award text bug fixed
98 * 47 9/13/99 12:17p Andsager
99 * Fix traitor debrief not playinf for FS2. Don't append _3 or _1 as in
102 * 46 9/07/99 9:35p Jefff
103 * fixed bug where award text was not getting cleared properly between
106 * 45 9/07/99 6:56p Jefff
107 * a few adjustments to loop detection
109 * 44 9/07/99 1:54p Jefff
110 * skip mission cleanup
112 * 43 9/06/99 9:45p Jefff
113 * skip mission support
115 * 42 9/06/99 6:38p Dave
116 * Improved CD detection code.
118 * 41 9/03/99 1:32a Dave
119 * CD checking by act. Added support to play 2 cutscenes in a row
120 * seamlessly. Fixed super low level cfile bug related to files in the
121 * root directory of a CD. Added cheat code to set campaign mission # in
124 * 40 9/02/99 3:45p Jefff
125 * forgot to remove some debug code. doh.
127 * 39 9/02/99 3:41p Jefff
128 * changed badge voice handling to be similar to promotion voice handling
130 * 38 9/01/99 4:41p Jefff
131 * fixed stoopid text color bug
133 * 37 8/31/99 11:54a Jefff
134 * minor debrief music tweak
136 * 36 8/27/99 9:57a Dave
137 * Enabled standard cheat codes. Allow player to continue in a campaing
138 * after using cheat codes.
140 * 35 8/27/99 12:04a Dave
141 * Campaign loop screen.
143 * 34 8/26/99 8:49p Jefff
144 * Updated medals screen and about everything that ever touches medals in
145 * one way or another. Sheesh.
147 * 33 8/20/99 4:20p Jefff
148 * hack for choosing the correct promotion voice
150 * 32 8/16/99 4:05p Dave
151 * Big honking checkin.
153 * 31 8/16/99 9:49a Jefff
154 * mission title length fix in multi
156 * 30 8/11/99 5:33p Jefff
157 * added 3rd debrief music track
159 * 29 8/10/99 7:28p Jefff
160 * shuffled some text around
162 * 28 8/04/99 5:36p Andsager
163 * Show upsell screens at end of demo campaign before returning to main
166 * 27 8/04/99 2:07p Jefff
167 * mission title no longer overwrites popup
169 * 26 8/02/99 5:37p Jefff
171 * 25 8/02/99 4:52p Jefff
172 * negative feedback sound when recommendations button pressed and
175 * 24 7/21/99 6:21p Jefff
176 * added hotkeys to the "you cannot accept" popup
178 * 23 6/15/99 12:04p Anoop
179 * Added a warning for running out of debrief text lines.
181 * 22 6/09/99 2:17p Dave
182 * Fixed up pleasewait bitmap rendering.
184 * 21 6/01/99 6:07p Dave
185 * New loading/pause/please wait bar.
187 * 20 5/22/99 6:05p Dave
188 * Fixed a few localization # problems.
190 * 19 5/22/99 5:35p Dave
191 * Debrief and chatbox screens. Fixed small hi-res HUD bug.
193 * 18 3/20/99 3:47p Andsager
194 * Fix crash with no mission loop description.
196 * 17 2/23/99 2:29p Dave
197 * First run of oldschool dogfight mode.
199 * 16 2/21/99 6:01p Dave
200 * Fixed standalone WSS packets.
202 * 15 2/11/99 3:08p Dave
203 * PXO refresh button. Very preliminary squad war support.
205 * 14 1/30/99 5:08p Dave
206 * More new hi-res stuff.Support for nice D3D textures.
208 * 13 1/29/99 2:08a Dave
209 * Fixed beam weapon collisions with players. Reduced size of scoring
210 * struct for multiplayer. Disabled PXO.
212 * 12 1/14/99 5:15p Neilk
213 * changed credits, command debrief interfaces to high resolution support
215 * 11 1/13/99 2:11p Andsager
216 * change default debriefing string text
218 * 10 12/17/98 4:50p Andsager
219 * Added debrief_assemble_optional_mission_popup_text() for single and
222 * 9 12/12/98 3:17p Andsager
223 * Clean up mission eval, goal, event and mission scoring.
225 * 8 12/10/98 10:19a Andsager
226 * Fix mission loop assert
228 * 7 12/10/98 9:59a Andsager
229 * Fix some bugs with mission loops
231 * 6 12/09/98 1:56p Andsager
232 * Initial checkin of mission loop
234 * 5 11/05/98 4:18p Dave
235 * First run nebula support. Beefed up localization a bit. Removed all
236 * conditional compiles for foreign versions. Modified mission file
239 * 4 10/23/98 3:51p Dave
240 * Full support for tstrings.tbl and foreign languages. All that remains
241 * is to make it active in Fred.
243 * 3 10/13/98 9:28a Dave
244 * Started neatening up freespace.h. Many variables renamed and
245 * reorganized. Added AlphaColors.[h,cpp]
247 * 2 10/07/98 10:53a Dave
250 * 1 10/07/98 10:49a Dave
252 * 178 9/17/98 3:08p Dave
253 * PXO to non-pxo game warning popup. Player icon stuff in create and join
254 * game screens. Upped server count refresh time in PXO to 35 secs (from
257 * 177 7/07/98 1:46p Dave
258 * Fixed nasty debriefing badge/promotion bug. Added extra physics info
261 * 175 6/09/98 10:31a Hoffoss
262 * Created index numbers for all xstr() references. Any new xstr() stuff
263 * added from here on out should be added to the end if the list. The
264 * current list count can be found in FreeSpace.cpp (search for
267 * 174 6/07/98 3:26p Lawrance
268 * Fix bug with cut-off popup text
270 * 173 6/05/98 9:54a Lawrance
273 * 172 6/01/98 11:43a John
274 * JAS & MK: Classified all strings for localization.
276 * 171 5/27/98 1:24p Allender
277 * make targeting dots work (as well as other targeting features) properly
278 * in multiplayer. Don't query for CD when entering debrief in
281 * 170 5/26/98 11:10a Lawrance
282 * Fix bug where window controls get disabled when F1 pressed twice
284 * 169 5/24/98 12:55a Mike
285 * Prevent SDL_assert() when no debriefing text for a stage.
287 * 168 5/23/98 10:38p Lawrance
288 * Avoid doing a cfile refresh when running debug
290 * 167 5/23/98 6:49p Lawrance
291 * Fix problems with refreshing the file list when a CD is inserted
293 * 166 5/21/98 6:57p Lawrance
294 * Don't prompt for the CD if voice not found
296 * 165 5/20/98 2:24a Dave
297 * Fixed server side voice muting. Tweaked multi debrief/endgame
298 * sequencing a bit. Much friendlier for stats tossing/accepting now.
300 * 164 5/19/98 8:35p Dave
301 * Revamp PXO channel listing system. Send campaign goals/events to
302 * clients for evaluation. Made lock button pressable on all screens.
304 * 163 5/19/98 11:13a Hoffoss
305 * Fixed bug where wrong wings award was being displayed in debriefing.
307 * 162 5/19/98 12:28a Mike
310 * 161 5/18/98 8:08p Hoffoss
311 * Moved placement of 'More' text.
313 * 160 5/18/98 3:50p Dan
314 * AL: Pick correct traitor debriefing voice file
316 * 159 5/17/98 6:32p Dave
317 * Make sure clients/servers aren't kicked out of the debriefing when team
318 * captains leave a game. Fixed chatbox off-by-one error. Fixed image
319 * xfer/pilot info popup stuff.
321 * 158 5/16/98 9:14p Allender
322 * fix scoring ckise fir training missions to actually count medals, but
323 * nothing else. Code used to SDL_assert when wings were granted then taken
324 * away because they were actually never granted in scoring structure
326 * 157 5/15/98 5:15p Dave
327 * Fix a standalone resetting bug.Tweaked PXO interface. Display captaincy
328 * status for team vs. team. Put in asserts to check for invalid team vs.
331 * 156 5/15/98 4:36p Allender
332 * fixed minor bug with wings
334 * 155 5/15/98 4:12p Allender
335 * removed redbook code. Put back in ingame join timer. Major fixups for
336 * stats in multiplayer. Pass correct score, medals, etc when leaving
337 * game. Be sure clients display medals, badges, etc.
339 * 154 5/15/98 2:25p Jasen
340 * temporarily disable granting of promotion and badges for clients
342 * 153 5/15/98 10:57a Allender
343 * fixed client side debriefings
345 * 152 5/15/98 10:36a Dave
346 * Removed 2 bogus bitmap drawing Int3()'s
348 * 151 5/14/98 2:44p Hoffoss
349 * Added wings awarding to debrief screen.
351 * 150 5/13/98 9:11p Lawrance
352 * Make 'replay mission' popup warn users about the loss of mission stats.
357 #include "missiondebrief.h"
358 #include "missionbriefcommon.h"
359 #include "missionscreencommon.h"
360 #include "missiongoals.h"
361 #include "missionpause.h"
362 #include "freespace.h"
363 #include "gamesequence.h"
371 #include "audiostr.h"
374 #include "contexthelp.h"
380 #include "multimsgs.h"
381 #include "multiutil.h"
382 #include "multiteamselect.h"
384 #include "eventmusic.h"
388 #include "multi_pinfo.h"
389 #include "contexthelp.h"
390 #include "multi_kick.h"
391 #include "multi_campaign.h"
392 #include "alphacolors.h"
393 #include "localize.h"
394 #include "multi_endgame.h"
397 #define MAX_TOTAL_DEBRIEF_LINES 200
399 #define TEXT_TYPE_NORMAL 1
400 #define TEXT_TYPE_RECOMMENDATION 2
402 #define DEBRIEF_NUM_STATS_PAGES 4
403 #define DEBRIEF_MISSION_STATS 0
404 #define DEBRIEF_MISSION_KILLS 1
405 #define DEBRIEF_ALLTIME_STATS 2
406 #define DEBRIEF_ALLTIME_KILLS 3
408 // 3rd coord is max width in pixels
409 int Debrief_title_coords[GR_NUM_RESOLUTIONS][3] = {
422 int Debrief_text_wnd_coords[GR_NUM_RESOLUTIONS][4] = {
435 int Debrief_text_x2[GR_NUM_RESOLUTIONS] = {
440 int Debrief_stage_info_coords[GR_NUM_RESOLUTIONS][2] = {
453 int Debrief_more_coords[GR_NUM_RESOLUTIONS][2] = {
466 #define MULTI_LIST_TEAM_OFFSET 16
468 int Debrief_multi_list_team_max_display[GR_NUM_RESOLUTIONS] = {
473 int Debrief_list_coords[GR_NUM_RESOLUTIONS][4] = {
482 int Debrief_award_wnd_coords[GR_NUM_RESOLUTIONS][2] = {
495 int Debrief_award_coords[GR_NUM_RESOLUTIONS][2] = {
509 int Debrief_rank_coords[2] = {
513 int Debrief_badge_coords[2] = {
519 // 0=x, 1=y, 2=width of the field
520 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][3] = {
529 // 0=x, 1=y, 2=height of the field
530 int Debrief_award_text_coords[GR_NUM_RESOLUTIONS][3] = {
539 // the medal text in FS1 is a bitmap
540 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][2] = {
549 int Debrief_rank_text_coords[GR_NUM_RESOLUTIONS][2] = {
558 int Debrief_badge_text_coords[GR_NUM_RESOLUTIONS][2] = {
569 // 1 = without medal (text will use medal space)
570 #define DB_WITH_MEDAL 0
571 #define DB_WITHOUT_MEDAL 1
572 int Debrief_award_text_width[GR_NUM_RESOLUTIONS][2] = {
581 const char *Debrief_single_name[GR_NUM_RESOLUTIONS] = {
582 "DebriefSingle", // GR_640
583 "2_DebriefSingle" // GR_1024
585 const char *Debrief_multi_name[GR_NUM_RESOLUTIONS] = {
586 "DebriefMulti", // GR_640
587 "2_DebriefMulti" // GR_1024
589 const char *Debrief_mask_name[GR_NUM_RESOLUTIONS] = {
590 "Debrief-m", // GR_640
591 "2_Debrief-m" // GR_1024
594 #define NUM_BUTTONS 18
597 #define DEBRIEF_TAB 0
599 #define TEXT_SCROLL_UP 2
600 #define TEXT_SCROLL_DOWN 3
601 #define REPLAY_MISSION 4
602 #define RECOMMENDATIONS 5
603 #define FIRST_STAGE 6
607 #define MULTI_PINFO_POPUP 10
608 #define MULTI_KICK 11
609 #define MEDALS_BUTTON 12
610 #define PLAYER_SCROLL_UP 13
611 #define PLAYER_SCROLL_DOWN 14
612 #define HELP_BUTTON 15
613 #define OPTIONS_BUTTON 16
614 #define ACCEPT_BUTTON 17
619 const char* Debrief_loading_bitmap_fname[GR_NUM_RESOLUTIONS] = {
620 "PleaseWait", // GR_640
621 "2_PleaseWait" // GR_1024
627 char text[NAME_LENGTH+1]; // name of ship type with a colon
628 int num; // how many ships of this type player has killed
629 } debrief_stats_kill_info;
632 int net_player_index; // index into Net_players[] array
633 int rank_bitmap; // bitmap id for rank
634 char callsign[CALLSIGN_LEN];
635 } debrief_multi_list_info;
637 static ui_button_info Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
640 ui_button_info("DB_00", 0, 2, -1, -1, 0), // debriefing
641 ui_button_info("DB_01", 0, 20, -1, -1, 1), // statistics
642 ui_button_info("DB_02", 0, 195, -1, -1, 2), // scroll stats up
643 ui_button_info("DB_03", 0, 232, -1, -1, 3), // scroll stats down
644 ui_button_info("DB_04", 24, 424, -1, -1, 4), // replay mission
645 ui_button_info("DB_05", 30, 451, -1, -1, 5), // recommendations
646 ui_button_info("DB_06", 211, 445, -1, -1, 6), // first page
647 ui_button_info("DB_07", 234, 445, -1, -1, 7), // prev page
648 ui_button_info("DB_08", 259, 445, -1, -1, 8), // next page
649 ui_button_info("DB_09", 283, 445, -1, -1, 9), // last page
650 ui_button_info("DB_21", 441, 384, -1, -1, 21), // pilot info
651 ui_button_info("DB_25", 511, 384, -1, -1, 25), // kick
652 ui_button_info("DB_15", 604, 224, -1, -1, 15), // medals
653 ui_button_info("DB_16", 615, 329, -1, -1, 16), // scroll pilots up
654 ui_button_info("DB_17", 615, 371, -1, -1, 17), // scroll pilots down
655 ui_button_info("DB_10", 469, 428, -1, -1, 10), // help
656 ui_button_info("DB_11", 447, 452, -1, -1, 11), // options
657 ui_button_info("DB_12", 562, 410, -1, -1, 12), // accept
659 ui_button_info("DB_00", 6, 1, 37, 7, 0), // debriefing
660 ui_button_info("DB_01", 6, 21, 37, 23, 1), // statistics
661 ui_button_info("DB_02", 1, 195, -1, -1, 2), // scroll stats up
662 ui_button_info("DB_03", 1, 236, -1, -1, 3), // scroll stats down
663 ui_button_info("DB_04", 1, 428, 49, 447, 4), // replay mission
664 ui_button_info("DB_05", 17, 459, 49, 464, 5), // recommendations
665 ui_button_info("DB_06", 323, 454, -1, -1, 6), // first page
666 ui_button_info("DB_07", 348, 454, -1, -1, 7), // prev page
667 ui_button_info("DB_08", 372, 454, -1, -1, 8), // next page
668 ui_button_info("DB_09", 396, 454, -1, -1, 9), // last page
669 ui_button_info("DB_10", 441, 384, 433, 413, 10), // pilot info
670 ui_button_info("DB_11", 511, 384, 510, 413, 11), // kick
671 ui_button_info("DB_12", 613, 226, -1, -1, 12), // medals
672 ui_button_info("DB_13", 615, 329, -1, -1, 13), // scroll pilots up
673 ui_button_info("DB_14", 615, 371, -1, -1, 14), // scroll pilots down
674 ui_button_info("DB_15", 538, 431, 500, 440, 15), // help
675 ui_button_info("DB_16", 538, 455, 479, 464, 16), // options
676 ui_button_info("DB_17", 573, 432, 572, 413, 17), // accept
680 ui_button_info("2_DB_00", 10, 1, 59, 12, 0), // debriefing
681 ui_button_info("2_DB_01", 10, 33, 59, 37, 1), // statistics
682 ui_button_info("2_DB_02", 1, 312, -1, -1, 2), // scroll stats up
683 ui_button_info("2_DB_03", 1, 378, -1, -1, 3), // scroll stats down
684 ui_button_info("2_DB_04", 1, 685, 79, 715, 4), // replay mission
685 ui_button_info("2_DB_05", 28, 735, 79, 743, 5), // recommendations
686 ui_button_info("2_DB_06", 517, 726, -1, -1, 6), // first page
687 ui_button_info("2_DB_07", 556, 726, -1, -1, 7), // prev page
688 ui_button_info("2_DB_08", 595, 726, -1, -1, 8), // next page
689 ui_button_info("2_DB_09", 633, 726, -1, -1, 9), // last page
690 ui_button_info("2_DB_10", 706, 615, 700, 661, 10), // pilot info
691 ui_button_info("2_DB_11", 817, 615, 816, 661, 11), // kick
692 ui_button_info("2_DB_12", 981, 362, -1, -1, 12), // medals
693 ui_button_info("2_DB_13", 984, 526, -1, -1, 13), // scroll pilots up
694 ui_button_info("2_DB_14", 984, 594, -1, -1, 14), // scroll pilots down
695 ui_button_info("2_DB_15", 861, 689, 801, 705, 15), // help
696 ui_button_info("2_DB_16", 861, 728, 777, 744, 16), // options
697 ui_button_info("2_DB_17", 917, 692, 917, 692, 17), // accept
703 #define NUM_DEBRIEF_TEXT 10
704 #define MP_TEXT_INDEX_1 4
705 #define MP_TEXT_INDEX_2 5
706 #define MP_TEXT_INDEX_3 6
707 UI_XSTR Debrief_strings[GR_NUM_RESOLUTIONS][NUM_DEBRIEF_TEXT] = {
709 { "Debriefing", 804, 37, 7, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][DEBRIEF_TAB].button },
710 { "Statistics", 1333, 37, 26, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][STATS_TAB].button },
711 { "Replay Mission", 444, 49, 447, UI_XSTR_COLOR_PINK, -1, &Buttons[0][REPLAY_MISSION].button },
712 { "Recommendations", 1334, 49, 464, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][RECOMMENDATIONS].button },
713 { "Pilot", 1310, 433, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_PINFO_POPUP].button },
714 { "Info", 1311, 433, 423, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_PINFO_POPUP].button },
715 { "Kick", 1266, 510, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_KICK].button },
716 { "Help", 928, 500, 440, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][HELP_BUTTON].button },
717 { "Options", 1036, 479, 464, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][OPTIONS_BUTTON].button },
718 { "Accept", 1035, 572, 413, UI_XSTR_COLOR_PINK, -1, &Buttons[0][ACCEPT_BUTTON].button },
721 { "Debriefing", 804, 59, 12, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][DEBRIEF_TAB].button },
722 { "Statistics", 1333, 59, 47, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][STATS_TAB].button },
723 { "Replay Mission", 444, 79, 715, UI_XSTR_COLOR_PINK, -1, &Buttons[1][REPLAY_MISSION].button },
724 { "Recommendations", 1334, 79, 743, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][RECOMMENDATIONS].button },
725 { "Pilot", 1310, 700, 661, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_PINFO_POPUP].button },
726 { "Info", 1311, 700, 679, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_PINFO_POPUP].button },
727 { "Kick", 1266, 816, 661, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_KICK].button },
728 { "Help", 928, 801, 705, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][HELP_BUTTON].button },
729 { "Options", 1036, 780, 744, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][OPTIONS_BUTTON].button },
730 { "Accept", 1035, 917, 672, UI_XSTR_COLOR_PINK, -1, &Buttons[1][ACCEPT_BUTTON].button },
736 char Debrief_current_callsign[CALLSIGN_LEN+10];
737 player *Debrief_player;
739 static UI_WINDOW Debrief_ui_window;
740 static UI_BUTTON List_region;
741 static int Background_bitmap; // bitmap for the background of the debriefing
742 static int Award_bg_bitmap;
743 static int Debrief_multi_loading_bitmap;
744 static int Rank_bitmap;
745 static int Medal_bitmap;
746 static int Badge_bitmap;
747 static int Wings_bitmap;
748 static int Crest_bitmap;
750 static int Rank_text_bitmap;
751 static int Medal_text_bitmap;
752 static int Badge_text_bitmap;
755 static int Debrief_accepted;
756 static int Turned_traitor;
757 static int Must_replay_mission;
759 static int Current_mode;
761 static int Recommend_active;
762 static int Award_active;
763 static int Text_offset;
764 static int Num_text_lines = 0;
765 static int Num_debrief_lines = 0;
766 static int Text_type[MAX_TOTAL_DEBRIEF_LINES];
767 static char *Text[MAX_TOTAL_DEBRIEF_LINES];
769 static int Debrief_inited = 0;
770 static int New_stage;
771 static int Current_stage;
772 static int Num_stages = 0;
773 static int Num_debrief_stages = 0;
774 static int Stage_voice = -1;
776 static int Multi_list_size;
777 static int Multi_list_offset;
779 int Debrief_multi_stages_loaded = 0;
780 int Debrief_multi_voice_loaded = 0;
782 // static int Debrief_voice_ask_for_cd;
784 // voice id's for debriefing text
785 static int Debrief_voices[MAX_DEBRIEF_STAGES];
787 #define DEBRIEF_VOICE_DELAY 400 // time to delay voice playback when a new stage starts
788 static int Debrief_cue_voice; // timestamp to cue the playback of the voice
789 static int Debrief_first_voice_flag = 1; // used to delay the first voice playback extra long
791 // pointer used for getting to debriefing information
792 debriefing Traitor_debriefing; // used when player is a traitor
794 // pointers to the active stages for this debriefing
795 static debrief_stage *Debrief_stages[MAX_DEBRIEF_STAGES];
796 static debrief_stage Promotion_stage, Badge_stage;
797 static debrief_stats_kill_info Debrief_stats_kills[MAX_SHIP_TYPES];
798 static debrief_multi_list_info Multi_list[MAX_PLAYERS];
799 int Multi_list_select;
801 // flag indicating if we should display info for the given player (in multiplayer)
802 int Debrief_should_show_popup = 1;
804 // already shown skip mission popup?
805 static int Debrief_skip_popup_already_shown = 0;
807 void debrief_text_init();
808 void debrief_accept(int ok_to_post_start_game_event = 1);
809 void debrief_kick_selected_player();
812 // promotion voice selection stuff
813 #define NUM_VOLITION_CAMPAIGNS 1
815 char campaign_name[32];
819 v_campaign Volition_campaigns[NUM_VOLITION_CAMPAIGNS] = {
821 BUILTIN_CAMPAIGN, // the only campaign for now, but this leaves room for a mission pack
822 35 // make sure this is equal to the number of missions you gave in the corresponding Debrief_promotion_voice_mapping
826 // data for which voice goes w/ which mission
827 typedef struct voice_map {
828 char mission_file[32];
832 voice_map Debrief_promotion_voice_mapping[NUM_VOLITION_CAMPAIGNS][MAX_CAMPAIGN_MISSIONS] = {
833 { // FreeSpace2 campaign
865 { "SM3-10.fs2", 9 }, // no debriefing for 3-10
867 { "loop1-1.fs2", 4 },
868 { "loop1-2.fs2", 4 },
869 { "loop1-3.fs2", 5 },
870 { "loop2-1.fs2", 4 },
875 #define DB_AWARD_WINGS 0
876 #define DB_AWARD_MEDAL 1
878 #define DB_AWARD_RANK 2
879 #define DB_AWARD_BADGE 3
880 #define DB_AWARD_BG 4
881 static const char* Debrief_award_filename[GR_NUM_RESOLUTIONS][5] = {
898 #define DB_AWARD_SOC 2
899 #define DB_AWARD_RANK 3
900 #define DB_AWARD_BADGE 4
901 #define DB_AWARD_BG 5
902 static const char* Debrief_award_filename[GR_NUM_RESOLUTIONS][6] = {
922 #define AWARD_TEXT_MAX_LINES 5
923 #define AWARD_TEXT_MAX_LINE_LENGTH 128
924 char Debrief_award_text[AWARD_TEXT_MAX_LINES][AWARD_TEXT_MAX_LINE_LENGTH];
925 int Debrief_award_text_num_lines = 0;
929 // prototypes, you know you love 'em
930 void debrief_add_award_text(char *str);
931 void debrief_award_text_clear();
936 const char *debrief_tooltip_handler(const char *str)
938 if (!SDL_strcasecmp(str, NOX("@.Medal"))) {
940 return XSTR( "Medal", 435);
943 } else if (!SDL_strcasecmp(str, NOX("@.Rank"))) {
945 return XSTR( "Rank", 436);
948 } else if (!SDL_strcasecmp(str, NOX("@.Badge"))) {
950 return XSTR( "Badge", 437);
953 } else if (!SDL_strcasecmp(str, NOX("@Medal"))) {
954 if (Medal_bitmap >= 0){
955 return Medals[Player->stats.m_medal_earned].name;
958 } else if (!SDL_strcasecmp(str, NOX("@Rank"))) {
959 if (Rank_bitmap >= 0){
960 return Ranks[Promoted].name;
963 } else if (!SDL_strcasecmp(str, NOX("@Badge"))) {
964 if (Badge_bitmap >= 0){
965 return Medals[Badge_index[Player->stats.m_badge_earned]].name;
972 // initialize the array of handles to the different voice streams
973 void debrief_voice_init()
977 for (i=0; i<MAX_DEBRIEF_STAGES; i++) {
978 Debrief_voices[i] = -1;
982 void debrief_load_voice_file(int voice_num, char *name)
984 int load_attempts = 0;
987 if ( load_attempts++ > 5 ) {
991 Debrief_voices[voice_num] = audiostream_open( name, ASF_VOICE );
992 if ( Debrief_voices[voice_num] >= 0 ) {
996 // Don't bother to ask for the CD in multiplayer
997 if ( Game_mode & GM_MULTIPLAYER ) {
1001 // couldn't load voice, ask user to insert CD (if necessary)
1003 // if ( Debrief_voice_ask_for_cd ) {
1004 // if ( game_do_cd_check() == 0 ) {
1005 // Debrief_voice_ask_for_cd = 0;
1012 // open and pre-load the stream buffers for the different voice streams
1013 void debrief_voice_load_all()
1017 // Debrief_voice_ask_for_cd = 1;
1019 for ( i=0; i<Num_debrief_stages; i++ ) {
1020 if ( strlen(Debrief_stages[i]->voice) <= 0 ) {
1023 if ( SDL_strncasecmp(Debrief_stages[i]->voice, NOX("none"), 4) ) {
1024 debrief_load_voice_file(i, Debrief_stages[i]->voice);
1025 // Debrief_voices[i] = audiostream_open(Debrief_stages[i]->voice, ASF_VOICE);
1030 // close all the briefing voice streams
1031 void debrief_voice_unload_all()
1035 for ( i=0; i<MAX_DEBRIEF_STAGES; i++ ) {
1036 if ( Debrief_voices[i] != -1 ) {
1037 audiostream_close_file(Debrief_voices[i], 0);
1038 Debrief_voices[i] = -1;
1043 // start playback of the voice for a particular briefing stage
1044 void debrief_voice_play()
1046 if (!Briefing_voice_enabled || (Current_mode != DEBRIEF_TAB)){
1050 // no more stages? We are done then.
1051 if (Stage_voice >= Num_debrief_stages){
1055 // if in delayed start, see if delay has elapsed and start voice if so
1056 if (Debrief_cue_voice) {
1057 if (!timestamp_elapsed(Debrief_cue_voice)){
1061 Stage_voice++; // move up to next voice
1062 if ((Stage_voice < Num_debrief_stages) && (Debrief_voices[Stage_voice] >= 0)) {
1063 audiostream_play(Debrief_voices[Stage_voice], Master_voice_volume, 0);
1064 Debrief_cue_voice = 0; // indicate no longer in delayed start checking
1070 // see if voice is still playing. If so, do nothing yet.
1071 if ((Stage_voice >= 0) && audiostream_is_playing(Debrief_voices[Stage_voice])){
1075 // set voice to play in a little while from now.
1076 Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY);
1079 // stop playback of the voice for a particular briefing stage
1080 void debrief_voice_stop()
1082 if ((Stage_voice < 0) || (Stage_voice > Num_debrief_stages) || (Debrief_voices[Stage_voice] < 0))
1085 audiostream_stop(Debrief_voices[Stage_voice]); // stream is automatically rewound
1089 // function to deal with inserting possible promition and badge stages into the debriefing
1091 void debrief_multi_fixup_stages()
1095 // possibly insert the badge stage first, them the promotion stage since they are
1096 // inserted at the front of the debrief stages.
1097 if ( Badge_bitmap >= 0 ) {
1098 // move all stages forward one. Don't
1099 for ( i = Num_debrief_stages; i > 0; i-- ) {
1100 Debrief_stages[i] = Debrief_stages[i-1];
1102 Debrief_stages[0] = &Badge_stage;
1103 Num_debrief_stages++;
1106 if ( Promoted >= 0) {
1107 // move all stages forward one
1108 for ( i = Num_debrief_stages; i > 0; i-- ) {
1109 Debrief_stages[i] = Debrief_stages[i-1];
1111 Debrief_stages[0] = &Promotion_stage;
1112 Num_debrief_stages++;
1117 // function called from multiplayer clients to set up the debriefing information for them
1118 // (sent from the server).
1119 void debrief_set_multi_clients( int stage_count, int active_stages[] )
1123 // set up the right briefing for this guy
1124 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
1125 Debriefing = &Debriefings[Net_player->p_info.team];
1127 Debriefing = &Debriefings[0];
1130 // see if this client was promoted -- if so, then add the first stage.
1131 Num_debrief_stages = 0;
1133 // set the pointers to the debriefings for this client
1134 for (i = 0; i < stage_count; i++) {
1135 Debrief_stages[Num_debrief_stages++] = &Debriefing->stages[active_stages[i]];
1138 Debrief_multi_stages_loaded = 1;
1141 // evaluate all stages for all teams. Server of a multiplayer game will have to send that
1142 // information to all clients after leaving this screen.
1143 void debrief_multi_server_stuff()
1145 debriefing *debriefp;
1147 int stage_active[MAX_TEAMS][MAX_DEBRIEF_STAGES], *stages[MAX_TEAMS];
1148 int i, j, num_stages, stage_count[MAX_TEAMS];
1150 memset( stage_active, 0, sizeof(stage_active) );
1152 for (i=0; i<Num_teams; i++) {
1153 debriefp = &Debriefings[i];
1155 stages[i] = stage_active[i];
1156 for (j=0; j<debriefp->num_stages; j++) {
1157 if ( eval_sexp(debriefp->stages[j].formula) ) {
1158 stage_active[i][num_stages] = j;
1163 stage_count[i] = num_stages;
1166 // if we're in campaign mode, evaluate campaign stuff
1167 if (Netgame.campaign_mode == MP_CAMPAIGN) {
1168 multi_campaign_eval_debrief();
1171 // send the information to all clients.
1172 send_debrief_info( stage_count, stages );
1176 // --------------------------------------------------------------------------------------
1177 // debrief_set_stages_and_multi_stuff()
1179 // Set up the active stages for this debriefing
1181 // returns: number of active debriefing stages
1183 int debrief_set_stages_and_multi_stuff()
1186 debriefing *debriefp;
1188 if ( MULTIPLAYER_CLIENT ) {
1192 Num_debrief_stages = 0;
1194 if ( Game_mode & GM_MULTIPLAYER ) {
1195 debrief_multi_server_stuff();
1198 // check to see if player is a traitor (looking at his team). If so, use the special
1199 // traitor debriefing. Only done in single player
1200 debriefp = Debriefing;
1201 if ( !(Game_mode & GM_MULTIPLAYER) ) {
1202 if (Player_ship->team == TEAM_TRAITOR)
1203 debriefp = &Traitor_debriefing;
1206 Num_debrief_stages = 0;
1207 if (Promoted >= 0) {
1208 Debrief_stages[Num_debrief_stages++] = &Promotion_stage;
1211 if (Badge_bitmap >= 0) {
1212 Debrief_stages[Num_debrief_stages++] = &Badge_stage;
1215 for (i=0; i<debriefp->num_stages; i++) {
1216 if (eval_sexp(debriefp->stages[i].formula) == 1) {
1217 Debrief_stages[Num_debrief_stages++] = &debriefp->stages[i];
1221 return Num_debrief_stages;
1224 // init the buttons that are specific to the debriefing screen
1225 void debrief_buttons_init()
1230 for ( i=0; i<NUM_BUTTONS; i++ ) {
1231 b = &Buttons[gr_screen.res][i];
1232 b->button.create( &Debrief_ui_window, "", b->x, b->y, 60, 30, 0 /*b->flags & REPEAT*/, 1 );
1233 // set up callback for when a mouse first goes over a button
1234 b->button.set_highlight_action( common_play_highlight_sound );
1235 b->button.set_bmaps(b->filename);
1236 b->button.link_hotspot(b->hotspot);
1241 for(i=0; i<NUM_DEBRIEF_TEXT; i++){
1242 // multiplayer specific text
1243 if((i == MP_TEXT_INDEX_1) || (i == MP_TEXT_INDEX_2) || (i == MP_TEXT_INDEX_3)){
1244 // only add if in multiplayer mode
1245 if(Game_mode & GM_MULTIPLAYER){
1246 Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
1251 Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
1256 // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1257 Buttons[gr_screen.res][NEXT_STAGE].button.set_hotkey(SDLK_RIGHT);
1258 Buttons[gr_screen.res][PREV_STAGE].button.set_hotkey(SDLK_LEFT);
1259 Buttons[gr_screen.res][LAST_STAGE].button.set_hotkey(KEY_SHIFTED | SDLK_RIGHT);
1260 Buttons[gr_screen.res][FIRST_STAGE].button.set_hotkey(KEY_SHIFTED | SDLK_LEFT);
1261 Buttons[gr_screen.res][TEXT_SCROLL_UP].button.set_hotkey(SDLK_UP);
1262 Buttons[gr_screen.res][TEXT_SCROLL_DOWN].button.set_hotkey(SDLK_DOWN);
1263 Buttons[gr_screen.res][ACCEPT_BUTTON].button.set_hotkey(KEY_CTRLED+SDLK_RETURN);
1265 // if in multiplayer, disable the button for all players except the host
1266 // also disable for squad war matches
1267 if(Game_mode & GM_MULTIPLAYER){
1268 if((Netgame.type_flags & NG_TYPE_SW) || !(Net_player->flags & NETINFO_FLAG_GAME_HOST)){
1269 Buttons[gr_screen.res][REPLAY_MISSION].button.disable();
1274 // --------------------------------------------------------------------------------------
1275 // debrief_ui_init()
1277 void debrief_ui_init()
1279 // init ship selection masks and buttons
1280 common_set_interface_palette("DebriefPalette"); // set the interface palette
1281 Debrief_ui_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
1282 Debrief_ui_window.set_mask_bmap(Debrief_mask_name[gr_screen.res]);
1283 Debrief_ui_window.tooltip_handler = debrief_tooltip_handler;
1284 debrief_buttons_init();
1286 // load in help overlay bitmap
1287 help_overlay_load(DEBRIEFING_OVERLAY);
1288 help_overlay_set_state(DEBRIEFING_OVERLAY,0);
1290 if ( Game_mode & GM_MULTIPLAYER ) {
1291 // close down any old instances of the chatbox
1294 // create the new one
1296 Background_bitmap = bm_load(Debrief_multi_name[gr_screen.res]);
1297 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);
1300 Background_bitmap = bm_load(Debrief_single_name[gr_screen.res]);
1303 if ( Background_bitmap < 0 ) {
1304 Warning(LOCATION, "Could not load the background bitmap for debrief screen");
1307 Award_bg_bitmap = bm_load(Debrief_award_filename[gr_screen.res][DB_AWARD_BG]);
1308 Debrief_multi_loading_bitmap = bm_load(Debrief_loading_bitmap_fname[gr_screen.res]);
1311 // sets Promotion_stage.voice
1312 // defaults to number 9 (Petrarch) for non-volition missions
1313 // this is an ugly, nasty way of doing this, but it saves us changing the missions at this point
1314 void debrief_choose_promotion_voice()
1318 if(Campaign.current_mission < 0){
1319 sprintf(Promotion_stage.voice, NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
1323 // search thru all official campaigns for our current campaign
1324 if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename)) {
1325 for (i=0; i<NUM_VOLITION_CAMPAIGNS; i++) {
1326 if ((Campaign.filename != NULL) && !SDL_strcasecmp(Campaign.filename, Volition_campaigns[i].campaign_name)) {
1327 // now search thru the mission filenames,
1328 for (j=0; j<Volition_campaigns[i].num_missions; j++) {
1329 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !SDL_strcasecmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file)) {
1330 // found it! set the persona and bail
1331 sprintf(Promotion_stage.voice, NOX("%d_%s"), Debrief_promotion_voice_mapping[i][j].persona_index, Ranks[Promoted].promotion_voice_base);
1339 // default to petrarch
1340 sprintf(Promotion_stage.voice, NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
1343 // sets Promotion_stage.voice
1344 // defaults to number 9 (Petrarch) for non-volition missions
1345 // this is an ugly, nasty, hateful way of doing this, but it saves us changing the missions at this point
1346 void debrief_choose_badge_voice()
1352 if(Campaign.current_mission < 0){
1354 // default to petrarch
1355 sprintf(Badge_stage.voice, NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1357 // default to FS1 guy
1358 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1362 if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename)) {
1364 if ( Player->on_bastion ) {
1365 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base2);
1368 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1372 // search thru all official campaigns for our current campaign
1373 for (i=0; i<NUM_VOLITION_CAMPAIGNS; i++) {
1374 if ((Campaign.filename != NULL) && !SDL_strcasecmp(Campaign.filename, Volition_campaigns[i].campaign_name)) {
1375 // now search thru the mission filenames,
1376 for (j=0; j<Campaign.num_missions; j++) {
1377 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !SDL_strcasecmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file)) {
1378 // found it! set the persona and bail
1379 sprintf(Badge_stage.voice, NOX("%d_%s"), Debrief_promotion_voice_mapping[i][j].persona_index, Badge_info[Player->stats.m_badge_earned].voice_base);
1389 // default to petrarch
1390 sprintf(Badge_stage.voice, NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1392 // default to FS1 guy
1393 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1398 void debrief_award_init()
1410 // be sure there are no old award texts floating around
1412 debrief_award_text_clear();
1415 // handle medal earned
1416 if (Player->stats.m_medal_earned != -1) {
1417 if (Player->stats.m_medal_earned == 13) { // special hack for the wings..
1419 if ( Player->stats.medals[13] > 1 ) {
1424 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_WINGS], ver);
1425 Wings_bitmap = bm_load(buf);
1427 } else if (Player->stats.m_medal_earned == 17) { // special hack for the soc crest
1428 Crest_bitmap = bm_load(Debrief_award_filename[gr_screen.res][DB_AWARD_SOC]);
1431 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_MEDAL], Player->stats.m_medal_earned);
1432 Medal_bitmap = bm_load(buf);
1436 debrief_add_award_text(Medals[Player->stats.m_medal_earned].name);
1440 // handle promotions
1441 if ( Player->stats.m_promotion_earned != -1 ) {
1442 Promoted = Player->stats.m_promotion_earned;
1443 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_RANK], Promoted + 1);
1444 Rank_bitmap = bm_load(buf);
1446 Promotion_stage.new_text = Ranks[Promoted].promotion_text;
1447 Promotion_stage.new_recommendation_text = NULL;
1449 // choose appropriate promotion voice for this mission
1450 debrief_choose_promotion_voice();
1453 debrief_add_award_text(Ranks[Promoted].name);
1457 // handle badge earned
1458 // only grant badge if earned and allowed. (no_promotion really means no promotion and no badges)
1459 if ( Player->stats.m_badge_earned != -1 ) {
1460 i = Player->stats.m_badge_earned;
1461 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_BADGE], i + 1);
1462 Badge_bitmap = bm_load(buf);
1464 Badge_stage.new_text = Badge_info[i].promotion_text;
1465 Badge_stage.new_recommendation_text = NULL;
1467 // choose appropriate voice
1468 debrief_choose_badge_voice();
1471 debrief_add_award_text(Medals[Badge_index[i]].name);
1475 if ((Rank_bitmap >= 0) || (Medal_bitmap >= 0) || (Badge_bitmap >= 0) || (Wings_bitmap >= 0) || (Crest_bitmap >= 0)) {
1482 // debrief_traitor_init() initializes local data which could be used if the player leaves the
1483 // mission a traitor. The same debriefing always gets played
1484 void debrief_traitor_init()
1486 static int inited = 0;
1489 debriefing *debrief;
1490 debrief_stage *stagep;
1494 if ((rval = setjmp(parse_abort)) != 0) {
1495 Error(LOCATION, "Unable to parse traitor.tbl! Code = %i.\n", rval);
1498 read_file_text("traitor.tbl");
1502 // open localization
1505 // simplied form of the debriefing stuff.
1506 debrief = &Traitor_debriefing;
1507 required_string("#Debriefing_info");
1509 required_string("$Num stages:");
1510 stuff_int(&debrief->num_stages);
1511 SDL_assert(debrief->num_stages == 1);
1514 stagep = &debrief->stages[stage_num++];
1515 required_string("$Formula:");
1516 stagep->formula = get_sexp_main();
1517 required_string("$multi text");
1518 if ( Fred_running ) {
1519 stuff_string( stagep->new_text, F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1521 stagep->new_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1523 required_string("$Voice:");
1524 char traitor_voice_file[NAME_LENGTH];
1525 stuff_string(traitor_voice_file, F_FILESPEC, NULL);
1527 // DKA 9/13/99 Only 1 traitor msg for FS2
1529 if ( Player->on_bastion ) {
1530 strcpy(stagep->voice, NOX("3_"));
1532 strcpy(stagep->voice, NOX("1_"));
1536 strcat(stagep->voice, traitor_voice_file);
1538 required_string("$Recommendation text:");
1539 if ( Fred_running ) {
1540 stuff_string( stagep->new_recommendation_text, F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1542 stagep->new_recommendation_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1546 // close localization
1550 // disable the accept button if in single player and I am a traitor
1551 Debrief_accepted = 0;
1552 Turned_traitor = Must_replay_mission = 0;
1553 if (!(Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_CAMPAIGN_MODE)) {
1554 if (Player_ship->team == TEAM_TRAITOR){
1558 if (Campaign.next_mission == Campaign.current_mission){
1559 Must_replay_mission = 1;
1563 if (Turned_traitor || Must_replay_mission) {
1564 Buttons[gr_screen.res][ACCEPT_BUTTON].button.hide();
1566 // kill off any stats
1567 Player->flags &= ~PLAYER_FLAGS_PROMOTED;
1568 scoring_level_init( &Player->stats );
1572 // initialization for listing of players in game
1573 void debrief_multi_list_init()
1575 Multi_list_size = 0; // number of net players to choose from
1576 Multi_list_offset = 0;
1578 Multi_list_select = -1;
1580 if ( !(Game_mode & GM_MULTIPLAYER) )
1583 debrief_rebuild_player_list();
1585 // switch stats display to this newly selected player
1586 set_player_stats(Multi_list[0].net_player_index);
1587 strcpy(Debrief_current_callsign, Multi_list[0].callsign);
1588 Debrief_player = Player;
1591 void debrief_multi_list_scroll_up()
1593 // if we're at the beginning of the list, don't do anything
1594 if(Multi_list_offset == 0){
1595 gamesnd_play_iface(SND_GENERAL_FAIL);
1599 // otherwise scroll up
1600 Multi_list_offset--;
1601 gamesnd_play_iface(SND_USER_SELECT);
1604 void debrief_multi_list_scroll_down()
1606 // if we can scroll down no further
1607 if(Multi_list_size < Debrief_multi_list_team_max_display[gr_screen.res]){
1608 gamesnd_play_iface(SND_GENERAL_FAIL);
1611 if((Multi_list_offset + Debrief_multi_list_team_max_display[gr_screen.res]) >= Multi_list_size){
1612 gamesnd_play_iface(SND_GENERAL_FAIL);
1616 // otherwise scroll down
1617 Multi_list_offset++;
1618 gamesnd_play_iface(SND_USER_SELECT);
1621 // draw the connected net players
1622 void debrief_multi_list_draw()
1624 int y, z, font_height,idx;
1625 char str[CALLSIGN_LEN+5];
1628 font_height = gr_get_font_height();
1630 // if we currently have no item picked, pick a reasonable one
1631 if((Multi_list_size >= 0) && (Multi_list_select == -1)){
1632 // select the entry which corresponds to the local player
1633 Multi_list_select = 0;
1634 for(idx=0;idx<Multi_list_size;idx++){
1635 if(Multi_list[idx].net_player_index == MY_NET_PLAYER_NUM){
1636 Multi_list_select = idx;
1638 // switch stats display to this newly selected player
1639 set_player_stats(Multi_list[idx].net_player_index);
1640 strcpy(Debrief_current_callsign, Multi_list[idx].callsign);
1641 Debrief_player = Net_players[Multi_list[idx].net_player_index].player;
1647 // draw the list itself
1649 z = Multi_list_offset;
1650 while (y + font_height <= Debrief_list_coords[gr_screen.res][3]){
1651 np = &Net_players[Multi_list[z].net_player_index];
1653 if (z >= Multi_list_size){
1656 // set the proper text color for the highlight
1657 if(np->flags & NETINFO_FLAG_GAME_HOST){
1658 if(Multi_list_select == z){
1659 gr_set_color_fast(&Color_text_active_hi);
1661 gr_set_color_fast(&Color_bright);
1664 if(Multi_list_select == z){
1665 gr_set_color_fast(&Color_text_active);
1667 gr_set_color_fast(&Color_text_normal);
1671 // blit the proper indicator - skipping observers
1672 if(!((np->flags & NETINFO_FLAG_OBSERVER) && !(np->flags & NETINFO_FLAG_OBS_PLAYER))){
1673 if(Netgame.type_flags & NG_TYPE_TEAM){
1675 if(np->p_info.team == 0){
1676 // draw his "selected" icon
1677 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM0_SELECT] != -1)){
1678 gr_set_bitmap(Multi_common_icons[MICON_TEAM0_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1679 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1681 // draw his "normal" icon
1682 else if(Multi_common_icons[MICON_TEAM0] != -1){
1683 gr_set_bitmap(Multi_common_icons[MICON_TEAM0], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1684 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1686 } else if(np->p_info.team == 1){
1687 // draw his "selected" icon
1688 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM1_SELECT] != -1)){
1689 gr_set_bitmap(Multi_common_icons[MICON_TEAM1_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1690 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1692 // draw his "normal" icon
1693 else if(Multi_common_icons[MICON_TEAM1] != -1){
1694 gr_set_bitmap(Multi_common_icons[MICON_TEAM1], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1695 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1699 // draw the team 0 selected icon
1700 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM0_SELECT] != -1)){
1701 gr_set_bitmap(Multi_common_icons[MICON_TEAM0_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1702 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1707 strcpy(str,Multi_list[z].callsign);
1708 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)){
1709 strcat(str,XSTR( "(O)", 438));
1713 gr_string(Debrief_list_coords[gr_screen.res][0] + MULTI_LIST_TEAM_OFFSET, Debrief_list_coords[gr_screen.res][1] + y, str);
1720 void debrief_kick_selected_player()
1722 if(Multi_list_select >= 0){
1723 SDL_assert(Net_player->flags & NETINFO_FLAG_GAME_HOST);
1724 multi_kick_player(Multi_list[Multi_list_select].net_player_index);
1728 // get optional mission popup text
1729 void debrief_assemble_optional_mission_popup_text(char *buffer, char *mission_loop_desc)
1731 SDL_assert(buffer != NULL);
1734 if (mission_loop_desc == NULL) {
1735 strcpy(buffer, XSTR("<No Mission Loop Description Available>", 1490));
1736 mprintf(("No mission loop description avail"));
1738 strcpy(buffer, mission_loop_desc);
1741 strcat(buffer, XSTR("\n\n\nDo you want to play the optional mission?", 1491));
1744 // what to do when the accept button is hit
1745 void debrief_accept(int ok_to_post_start_game_event)
1749 if ( (/*Cheats_enabled ||*/ Turned_traitor || Must_replay_mission) && (Game_mode & GM_CAMPAIGN_MODE) ) {
1753 if (Game_mode & GM_MULTIPLAYER) {
1757 if (Player_ship->team == TEAM_TRAITOR){
1758 str = XSTR( "Your career is over, Traitor! You can't accept new missions!", 439);
1759 }/* else if (Cheats_enabled) {
1760 str = XSTR( "You are a cheater. You cannot accept this mission!", 440);
1762 str = XSTR( "You have failed this mission and cannot accept. What do you you wish to do instead?", 441);
1765 z = popup(0, 3, XSTR( "Return to &Debriefing", 442), XSTR( "Go to &Flight Deck", 443), XSTR( "&Replay Mission", 444), str);
1767 gameseq_post_event(GS_EVENT_START_BRIEFING); // cycle back to briefing
1768 } else if ( z == 1 ) {
1769 gameseq_post_event(GS_EVENT_END_GAME); // return to main hall, tossing stats
1775 Debrief_accepted = 1;
1776 // save mission stats
1777 if (Game_mode & GM_MULTIPLAYER) {
1778 // note that multi_debrief_accept_hit() will handle all mission_campaign_* calls on its own
1779 // as well as doing stats transfers, etc.
1780 multi_debrief_accept_hit();
1784 int play_commit_sound = 1;
1785 // only write the player's stats if he's accepted
1787 // if we are just playing a single mission, then don't do many of the things
1788 // that need to be done. Nothing much should happen when just playing a single
1789 // mission that isn't in a campaign.
1790 if ( Game_mode & GM_CAMPAIGN_MODE ) {
1792 // check for possible mission loop
1793 // check for (1) mission loop available, (2) dont have to repeat last mission
1794 if(!(Game_mode & GM_MULTIPLAYER)){
1795 int cur = Campaign.current_mission;
1796 bool require_repeat_mission = (Campaign.current_mission == Campaign.next_mission);
1797 if (Campaign.missions[cur].has_mission_loop) {
1798 SDL_assert(Campaign.loop_mission != CAMPAIGN_LOOP_MISSION_UNINITIALIZED);
1801 if ( (Campaign.missions[cur].has_mission_loop && (Campaign.loop_mission != -1)) && !require_repeat_mission ) {
1804 debrief_assemble_optional_mission_popup_text(buffer, Campaign.missions[cur].mission_loop_desc);
1806 int choice = popup(0 , 2, POPUP_NO, POPUP_YES, buffer);
1808 Campaign.loop_enabled = 1;
1809 Campaign.next_mission = Campaign.loop_mission;
1818 if(ok_to_post_start_game_event){
1819 gameseq_post_event(GS_EVENT_LOOP_BRIEF);
1821 play_commit_sound = 0;
1824 // continue as normal
1827 mission_campaign_mission_over();
1829 // check to see if we are out of the loop now
1830 if ( Campaign.next_mission == Campaign.loop_reentry ) {
1831 Campaign.loop_enabled = 0;
1834 // check if campaign is over
1835 if ( Campaign.next_mission == -1 ) {
1836 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
1837 gameseq_post_event(GS_EVENT_END_DEMO);
1839 gameseq_post_event(GS_EVENT_MAIN_MENU);
1842 if ( ok_to_post_start_game_event ) {
1843 gameseq_post_event(GS_EVENT_START_GAME);
1845 play_commit_sound = 0;
1850 gameseq_post_event(GS_EVENT_MAIN_MENU);
1853 if ( play_commit_sound ) {
1854 gamesnd_play_iface(SND_COMMIT_PRESSED);
1861 void debrief_next_tab()
1863 New_mode = Current_mode + 1;
1864 if (New_mode >= NUM_TABS)
1868 void debrief_prev_tab()
1870 New_mode = Current_mode - 1;
1872 New_mode = NUM_TABS - 1;
1875 // --------------------------------------------------------------------------------------
1876 // debrief_next_stage()
1878 void debrief_next_stage()
1880 if (Current_stage < Num_stages - 1) {
1881 New_stage = Current_stage + 1;
1882 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1885 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1888 // --------------------------------------------------------------------------------------
1889 // debrief_prev_stage()
1891 void debrief_prev_stage()
1893 if (Current_stage) {
1894 New_stage = Current_stage - 1;
1895 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1898 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1901 // --------------------------------------------------------------------------------------
1902 // debrief_first_stage()
1903 void debrief_first_stage()
1905 if (Current_stage) {
1907 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1910 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1913 // --------------------------------------------------------------------------------------
1914 // debrief_last_stage()
1915 void debrief_last_stage()
1917 if (Current_stage != Num_stages - 1) {
1918 New_stage = Num_stages - 1;
1919 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1922 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1925 // draw what stage number the debriefing is on
1926 void debrief_render_stagenum()
1934 sprintf(buf, XSTR( "%d of %d", 445), Current_stage + 1, Num_stages);
1935 gr_get_string_size(&w, NULL, buf);
1936 gr_set_color_fast(&Color_bright_blue);
1937 gr_string(Debrief_stage_info_coords[gr_screen.res][0] - w, Debrief_stage_info_coords[gr_screen.res][1], buf);
1938 gr_set_color_fast(&Color_white);
1941 // render the mission time at the specified y location
1942 void debrief_render_mission_time(int y_loc)
1946 game_format_time(Missiontime, time_str);
1947 gr_string(0, y_loc, XSTR( "Mission Time", 446));
1948 gr_string(Debrief_text_x2[gr_screen.res], y_loc, time_str);
1951 // render out the debriefing text to the scroll window
1952 void debrief_render()
1954 int y, z, font_height;
1956 if ( Num_stages <= 0 )
1959 font_height = gr_get_font_height();
1961 gr_set_clip(Debrief_text_wnd_coords[gr_screen.res][0], Debrief_text_wnd_coords[gr_screen.res][1], Debrief_text_wnd_coords[gr_screen.res][2], Debrief_text_wnd_coords[gr_screen.res][3]);
1964 while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
1965 if (z >= Num_text_lines)
1968 if (Text_type[z] == TEXT_TYPE_NORMAL)
1969 gr_set_color_fast(&Color_white);
1971 gr_set_color_fast(&Color_bright_red);
1974 gr_string(0, y, Text[z]);
1983 // render out the stats info to the scroll window
1985 void debrief_stats_render()
1987 int i, y, font_height;
1989 gr_set_color_fast(&Color_blue);
1990 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]);
1991 gr_string(0, 0, Debrief_current_callsign);
1992 font_height = gr_get_font_height();
1995 switch ( Current_stage ) {
1996 case DEBRIEF_MISSION_STATS:
1997 i = Current_stage - 1;
2001 gr_set_color_fast(&Color_white);
2003 // display mission completion time
2004 debrief_render_mission_time(y);
2007 show_stats_label(i, 0, y, font_height);
2008 show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2010 case DEBRIEF_ALLTIME_STATS:
2011 i = Current_stage - 1;
2015 gr_set_color_fast(&Color_white);
2016 show_stats_label(i, 0, y, font_height);
2017 show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2020 case DEBRIEF_ALLTIME_KILLS:
2021 case DEBRIEF_MISSION_KILLS:
2022 gr_set_color_fast(&Color_white);
2024 while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
2025 if (i >= Num_text_lines)
2029 if ( Current_stage == DEBRIEF_MISSION_KILLS )
2030 gr_printf(0, y, XSTR( "Mission Kills by Ship Type", 447));
2032 gr_printf(0, y, XSTR( "All-time Kills by Ship Type", 448));
2035 gr_printf(0, y, "%s", Debrief_stats_kills[i - 2].text);
2036 gr_printf(Debrief_text_x2[gr_screen.res], y, "%d", Debrief_stats_kills[i - 2].num);
2043 if (Num_text_lines == 2) {
2044 if ( Current_stage == DEBRIEF_MISSION_KILLS )
2045 gr_printf(0, y, XSTR( "(No ship kills this mission)", 449));
2047 gr_printf(0, y, XSTR( "(No ship kills)", 450));
2060 // do action for when the replay button is pressed
2061 void debrief_replay_pressed()
2063 if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2065 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));
2072 gameseq_post_event(GS_EVENT_START_BRIEFING); // take us to the briefing
2073 gamesnd_play_iface(SND_COMMIT_PRESSED);
2076 // -------------------------------------------------------------------
2077 // debrief_redraw_pressed_buttons()
2079 // Redraw any debriefing buttons that are pressed down. This function is needed
2080 // since we sometimes need to draw pressed buttons last to ensure the entire
2081 // button gets drawn (and not overlapped by other buttons)
2083 void debrief_redraw_pressed_buttons()
2088 for ( i=0; i<NUM_BUTTONS; i++ ) {
2089 b = &Buttons[gr_screen.res][i].button;
2090 // don't draw the recommendations button if we're in stats mode
2091 if ( b->button_down() ) {
2097 // debrief specific button with hotspot 'i' has been pressed, so perform the associated action
2099 void debrief_button_pressed(int num)
2103 Buttons[gr_screen.res][RECOMMENDATIONS].button.enable();
2104 // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
2105 if (num != Current_mode){
2106 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
2111 // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 1; // allows failure sound to be played
2112 Buttons[gr_screen.res][RECOMMENDATIONS].button.disable();
2113 if (num != Current_mode){
2114 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
2119 case TEXT_SCROLL_UP:
2122 gamesnd_play_iface(SND_SCROLL);
2124 gamesnd_play_iface(SND_GENERAL_FAIL);
2128 case TEXT_SCROLL_DOWN:
2129 if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
2131 gamesnd_play_iface(SND_SCROLL);
2133 gamesnd_play_iface(SND_GENERAL_FAIL);
2137 case REPLAY_MISSION:
2138 if(Game_mode & GM_MULTIPLAYER){
2139 multi_debrief_replay_hit();
2141 debrief_replay_pressed();
2145 case RECOMMENDATIONS:
2146 gamesnd_play_iface(SND_USER_SELECT);
2147 Recommend_active = !Recommend_active;
2148 debrief_text_init();
2152 debrief_first_stage();
2156 debrief_prev_stage();
2160 debrief_next_stage();
2164 debrief_last_stage();
2168 gamesnd_play_iface(SND_HELP_PRESSED);
2169 launch_context_help();
2172 case OPTIONS_BUTTON:
2173 gamesnd_play_iface(SND_SWITCH_SCREENS);
2174 gameseq_post_event( GS_EVENT_OPTIONS_MENU );
2182 gamesnd_play_iface(SND_SWITCH_SCREENS);
2183 gameseq_post_event(GS_EVENT_VIEW_MEDALS);
2186 case PLAYER_SCROLL_UP:
2187 debrief_multi_list_scroll_up();
2190 case PLAYER_SCROLL_DOWN:
2191 debrief_multi_list_scroll_down();
2194 case MULTI_PINFO_POPUP:
2195 Debrief_should_show_popup = 1;
2199 debrief_kick_selected_player();
2204 void debrief_setup_ship_kill_stats(int stage_num)
2208 debrief_stats_kill_info *kill_info;
2210 SDL_assert(Current_stage < DEBRIEF_NUM_STATS_PAGES);
2211 if ( Current_stage == DEBRIEF_MISSION_STATS || Current_stage == DEBRIEF_ALLTIME_STATS )
2214 SDL_assert(Debrief_player != NULL);
2216 // kill_ar points to an array of MAX_SHIP_TYPE ints
2217 if ( Current_stage == DEBRIEF_MISSION_KILLS ) {
2218 kill_arr = Debrief_player->stats.m_okKills;
2220 kill_arr = Debrief_player->stats.kills;
2224 for ( i=0; i<MAX_SHIP_TYPES; i++ ) {
2226 // code used to add in mission kills, but the new system assumes that the player will accept, so
2227 // all time stats already have mission stats added in.
2228 if ( kill_arr[i] <= 0 ){
2233 kill_info = &Debrief_stats_kills[Num_text_lines++];
2235 kill_info->num = kill_arr[i];
2237 strcpy(kill_info->text, Ship_info[i].name);
2238 strcat(kill_info->text, NOX(":"));
2241 Num_text_lines += 2;
2244 // Iterate through the debriefing buttons, checking if they are pressed
2245 void debrief_check_buttons()
2249 for ( i=0; i<NUM_BUTTONS; i++ ) {
2250 if ( Buttons[gr_screen.res][i].button.pressed() ) {
2251 debrief_button_pressed(i);
2255 if ( !(Game_mode & GM_MULTIPLAYER) )
2258 if (List_region.pressed()) {
2259 List_region.get_mouse_pos(NULL, &y);
2260 z = Multi_list_offset + y / gr_get_font_height();
2261 if ((z >= 0) && (z < Multi_list_size)) {
2262 // switch stats display to this newly selected player
2263 set_player_stats(Multi_list[z].net_player_index);
2264 strcpy(Debrief_current_callsign, Multi_list[z].callsign);
2265 Debrief_player = Net_players[Multi_list[z].net_player_index].player;
2266 Multi_list_select = z;
2267 debrief_setup_ship_kill_stats(Current_stage);
2268 gamesnd_play_iface(SND_USER_SELECT);
2272 // if the player was double clicked on - we should popup a player info popup
2274 if (List_region.double_clicked()) {
2275 Debrief_should_show_popup = 1;
2280 void debrief_text_stage_init(const char *src, int type)
2282 int i, n_lines, n_chars[MAX_DEBRIEF_LINES];
2283 char line[MAX_DEBRIEF_LINE_LEN];
2284 char *p_str[MAX_DEBRIEF_LINES];
2286 n_lines = split_str(src, Debrief_text_wnd_coords[gr_screen.res][2], n_chars, p_str, MAX_DEBRIEF_LINES);
2287 SDL_assert(n_lines >= 0);
2289 // if you hit this, you proba
2290 if(n_lines >= MAX_DEBRIEF_LINES){
2291 Warning(LOCATION, "You have come close to the limit of debriefing lines, try adding more stages");
2294 for ( i=0; i<n_lines; i++ ) {
2295 SDL_assert(n_chars[i] < MAX_DEBRIEF_LINE_LEN);
2296 SDL_assert(Num_text_lines < MAX_TOTAL_DEBRIEF_LINES);
2297 strncpy(line, p_str[i], n_chars[i]);
2298 line[n_chars[i]] = 0;
2299 drop_white_space(line);
2300 Text_type[Num_text_lines] = type;
2301 Text[Num_text_lines++] = strdup(line);
2307 void debrief_free_text()
2311 for (i=0; i<Num_debrief_lines; i++)
2315 Num_debrief_lines = 0;
2318 // setup the debriefing text lines for rendering
2319 void debrief_text_init()
2324 // release old text lines first
2325 debrief_free_text();
2326 Num_text_lines = Text_offset = 0;
2328 if (Current_mode == DEBRIEF_TAB) {
2329 for (i=0; i<Num_debrief_stages; i++) {
2331 Text[Num_text_lines++] = NULL; // add a blank line between stages
2333 src = Debrief_stages[i]->new_text;
2335 debrief_text_stage_init(src, TEXT_TYPE_NORMAL);
2337 if (Recommend_active) {
2338 src = Debrief_stages[i]->new_recommendation_text;
2339 if (!src && (i == Num_debrief_stages - 1) && !r_count)
2340 src = XSTR( "We have no recommendations for you.", 1054);
2343 Text[Num_text_lines++] = NULL;
2344 debrief_text_stage_init(src, TEXT_TYPE_RECOMMENDATION);
2350 Num_debrief_lines = Num_text_lines;
2354 // not in debriefing mode, must be in stats mode
2356 debrief_setup_ship_kill_stats(Current_stage);
2360 // --------------------------------------------------------------------------------------
2364 SDL_assert(!Debrief_inited);
2365 // Campaign.loop_enabled = 0;
2366 Campaign.loop_mission = CAMPAIGN_LOOP_MISSION_UNINITIALIZED;
2368 // set up the right briefing for this guy
2369 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
2370 Debriefing = &Debriefings[Net_player->p_info.team];
2372 Debriefing = &Debriefings[0];
2375 // no longer is mission
2376 Game_mode &= ~(GM_IN_MISSION);
2380 New_mode = DEBRIEF_TAB;
2381 Recommend_active = Award_active = 0;
2386 Debrief_cue_voice = 0;
2387 Num_text_lines = Num_debrief_lines = 0;
2388 Debrief_first_voice_flag = 1;
2390 Debrief_multi_voice_loaded = 0;
2393 Medal_text_bitmap = bm_load(NOX("DebriefText01"));
2394 Rank_text_bitmap = bm_load(NOX("DebriefText02"));
2395 Badge_text_bitmap = bm_load(NOX("DebriefText03"));
2398 if ( (Game_mode & GM_CAMPAIGN_MODE) && ( !MULTIPLAYER_CLIENT ) ) {
2399 // MUST store goals and events first - may be used to evaluate next mission
2400 // store goals and events
2401 mission_campaign_store_goals_and_events();
2403 // evaluate next mission
2404 mission_campaign_eval_next_mission();
2407 // call traitor init before calling scoring_level_close. traitor init will essentially nullify
2409 if ( !(Game_mode & GM_MULTIPLAYER) ) { // only do for single player
2410 debrief_traitor_init(); // initialize data needed if player becomes traitor.
2413 // call scoring level close for my stats. Needed for award_init. The stats will
2414 // be backed out if used chooses to replace them.
2415 scoring_level_close();
2417 debrief_ui_init(); // init UI items
2418 debrief_award_init();
2420 debrief_voice_init();
2421 debrief_multi_list_init();
2422 // rank_bitmaps_clear();
2423 // rank_bitmaps_load();
2425 strcpy(Debrief_current_callsign, Player->callsign);
2426 Debrief_player = Player;
2427 // Debrief_current_net_player_index = debrief_multi_list[0].net_player_index;
2429 // set up the Debrief_stages[] and Recommendations[] arrays. Only do the following stuff
2430 // for non-clients (i.e. single and game server). Multiplayer clients will get their debriefing
2431 // info directly from the server.
2432 if ( !MULTIPLAYER_CLIENT ) {
2433 debrief_set_stages_and_multi_stuff();
2435 if ( Num_debrief_stages <= 0 ) {
2436 Num_debrief_stages = 0;
2438 debrief_voice_load_all();
2441 // multiplayer client may have already received their debriefing info. If they have not,
2442 // then set the num debrief stages to 0
2443 if ( !Debrief_multi_stages_loaded ) {
2444 Num_debrief_stages = 0;
2449 if (mission_evaluate_primary_goals() == PRIMARY_GOALS_COMPLETE) {
2450 common_music_init(SCORE_DEBRIEF_SUCCESS);
2452 common_music_init(SCORE_DEBRIEF_FAIL);
2456 // start up the appropriate music
2457 if (Campaign.next_mission == Campaign.current_mission) {
2458 // you failed the mission because you suck, so you get the suck music
2459 common_music_init(SCORE_DEBRIEF_FAIL);
2460 } else if (mission_goals_met()) {
2461 // you completed all primaries and secondaries, thus you are a stud boy and you get stud boy music
2462 common_music_init(SCORE_DEBRIEF_SUCCESS);
2464 // you somehow passed the mission, so you get a little something for your efforts.
2465 common_music_init(SCORE_DEBRIEF_AVERAGE);
2468 if (Campaign.next_mission == Campaign.current_mission) {
2469 // better luck next time, increase his retries
2470 Player->failures_this_session++;
2472 // clear his retries info regardless of whether or not he accepts
2473 Player->failures_this_session = 0;
2476 if (Game_mode & GM_MULTIPLAYER) {
2477 multi_debrief_init();
2479 // if i'm not the host of the game, disable the multi kick button
2480 if (!(Net_player->flags & NETINFO_FLAG_GAME_HOST)) {
2481 Buttons[gr_screen.res][MULTI_KICK].button.disable();
2484 Buttons[gr_screen.res][PLAYER_SCROLL_UP].button.disable();
2485 Buttons[gr_screen.res][PLAYER_SCROLL_DOWN].button.disable();
2486 Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.disable();
2487 Buttons[gr_screen.res][MULTI_KICK].button.disable();
2488 Buttons[gr_screen.res][PLAYER_SCROLL_UP].button.hide();
2489 Buttons[gr_screen.res][PLAYER_SCROLL_DOWN].button.hide();
2490 Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.hide();
2491 Buttons[gr_screen.res][MULTI_KICK].button.hide();
2494 if (!Award_active) {
2495 Buttons[gr_screen.res][MEDALS_BUTTON].button.disable();
2496 Buttons[gr_screen.res][MEDALS_BUTTON].button.hide();
2499 Debrief_skip_popup_already_shown = 0;
2504 // --------------------------------------------------------------------------------------
2506 void debrief_close()
2510 SDL_assert(Debrief_inited);
2512 // if the mission wasn't accepted, clear out my stats
2513 // we need to evaluate a little differently for multiplayer since the conditions for "accepting"
2514 // are a little bit different
2515 if (Game_mode & GM_MULTIPLAYER) {
2516 // if stats weren't accepted, backout my own stats
2517 if (multi_debrief_stats_accept_code() != 1) {
2518 if(MULTIPLAYER_MASTER){
2519 for(idx=0; idx<MAX_PLAYERS; idx++){
2520 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) && (Net_players[idx].player != NULL)){
2521 scoring_backout_accept(&Net_players[idx].player->stats);
2525 scoring_backout_accept( &Player->stats );
2530 if( !Debrief_accepted || !(Game_mode & GM_CAMPAIGN_MODE) ){
2531 scoring_backout_accept( &Player->stats );
2535 // if dude passed the misson and accepted, reset his show skip popup flag
2536 if (Debrief_accepted) {
2537 Player->show_skip_popup = 1;
2540 if (Num_debrief_lines) {
2541 for (i=0; i<Num_debrief_lines; i++){
2548 // clear out debrief info parsed from mission file
2549 mission_debrief_common_reset();
2551 // unload the overlay bitmap
2553 help_overlay_unload(DEBRIEFING_OVERLAY);
2556 // clear out award text
2557 Debrief_award_text_num_lines = 0;
2559 debrief_voice_unload_all();
2560 common_music_close();
2563 // rank_bitmaps_release();
2566 if (Background_bitmap >= 0){
2567 bm_unload(Background_bitmap);
2570 if (Award_bg_bitmap >= 0){
2571 bm_unload(Award_bg_bitmap);
2574 if (Rank_bitmap >= 0){
2575 bm_unload(Rank_bitmap);
2578 if (Medal_bitmap >= 0){
2579 bm_unload(Medal_bitmap);
2582 if (Badge_bitmap >= 0){
2583 bm_unload(Badge_bitmap);
2586 if (Wings_bitmap >= 0) {
2587 bm_unload(Wings_bitmap);
2590 if (Crest_bitmap >= 0) {
2591 bm_unload(Crest_bitmap);
2595 if (Medal_text_bitmap >= 0) {
2596 bm_unload(Medal_text_bitmap);
2599 if (Badge_text_bitmap >= 0) {
2600 bm_unload(Badge_text_bitmap);
2603 if (Rank_text_bitmap >= 0) {
2604 bm_unload(Rank_text_bitmap);
2608 Debrief_ui_window.destroy();
2609 common_free_interface_palette(); // restore game palette
2612 if (Game_mode & GM_MULTIPLAYER){
2613 multi_debrief_close();
2623 // handle keypresses in debriefing
2624 void debrief_do_keys(int new_k)
2631 case KEY_SHIFTED | SDLK_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 SDL_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 const char *please_wait_str = XSTR("Please Wait", 1242);
2755 SDL_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 == SDLK_ESCAPE){
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 SDL_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) && !SDL_strcasecmp(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 SDL_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()