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 #include "techmenu.h"
401 #define MAX_TOTAL_DEBRIEF_LINES 200
403 #define TEXT_TYPE_NORMAL 1
404 #define TEXT_TYPE_RECOMMENDATION 2
406 #define DEBRIEF_NUM_STATS_PAGES 4
407 #define DEBRIEF_MISSION_STATS 0
408 #define DEBRIEF_MISSION_KILLS 1
409 #define DEBRIEF_ALLTIME_STATS 2
410 #define DEBRIEF_ALLTIME_KILLS 3
412 // 3rd coord is max width in pixels
413 int Debrief_title_coords[GR_NUM_RESOLUTIONS][3] = {
426 int Debrief_text_wnd_coords[GR_NUM_RESOLUTIONS][4] = {
439 int Debrief_text_x2[GR_NUM_RESOLUTIONS] = {
444 int Debrief_stage_info_coords[GR_NUM_RESOLUTIONS][2] = {
457 int Debrief_more_coords[GR_NUM_RESOLUTIONS][2] = {
470 #define MULTI_LIST_TEAM_OFFSET 16
472 int Debrief_multi_list_team_max_display[GR_NUM_RESOLUTIONS] = {
477 int Debrief_list_coords[GR_NUM_RESOLUTIONS][4] = {
486 int Debrief_award_wnd_coords[GR_NUM_RESOLUTIONS][2] = {
499 int Debrief_award_coords[GR_NUM_RESOLUTIONS][2] = {
513 int Debrief_rank_coords[2] = {
517 int Debrief_badge_coords[2] = {
523 // 0=x, 1=y, 2=width of the field
524 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][3] = {
533 // 0=x, 1=y, 2=height of the field
534 int Debrief_award_text_coords[GR_NUM_RESOLUTIONS][3] = {
543 // the medal text in FS1 is a bitmap
544 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][2] = {
553 int Debrief_rank_text_coords[GR_NUM_RESOLUTIONS][2] = {
562 int Debrief_badge_text_coords[GR_NUM_RESOLUTIONS][2] = {
573 // 1 = without medal (text will use medal space)
574 #define DB_WITH_MEDAL 0
575 #define DB_WITHOUT_MEDAL 1
576 int Debrief_award_text_width[GR_NUM_RESOLUTIONS][2] = {
585 const char *Debrief_single_name[GR_NUM_RESOLUTIONS] = {
586 "DebriefSingle", // GR_640
587 "2_DebriefSingle" // GR_1024
589 const char *Debrief_multi_name[GR_NUM_RESOLUTIONS] = {
590 "DebriefMulti", // GR_640
591 "2_DebriefMulti" // GR_1024
593 const char *Debrief_mask_name[GR_NUM_RESOLUTIONS] = {
594 "Debrief-m", // GR_640
595 "2_Debrief-m" // GR_1024
598 #define NUM_BUTTONS 18
601 #define DEBRIEF_TAB 0
603 #define TEXT_SCROLL_UP 2
604 #define TEXT_SCROLL_DOWN 3
605 #define REPLAY_MISSION 4
606 #define RECOMMENDATIONS 5
607 #define FIRST_STAGE 6
611 #define MULTI_PINFO_POPUP 10
612 #define MULTI_KICK 11
613 #define MEDALS_BUTTON 12
614 #define PLAYER_SCROLL_UP 13
615 #define PLAYER_SCROLL_DOWN 14
616 #define HELP_BUTTON 15
617 #define OPTIONS_BUTTON 16
618 #define ACCEPT_BUTTON 17
623 const char* Debrief_loading_bitmap_fname[GR_NUM_RESOLUTIONS] = {
624 "PleaseWait", // GR_640
625 "2_PleaseWait" // GR_1024
631 char text[NAME_LENGTH+1]; // name of ship type with a colon
632 int num; // how many ships of this type player has killed
633 } debrief_stats_kill_info;
636 int net_player_index; // index into Net_players[] array
637 int rank_bitmap; // bitmap id for rank
638 char callsign[CALLSIGN_LEN];
639 } debrief_multi_list_info;
641 static ui_button_info Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
644 ui_button_info("DB_00", 0, 2, -1, -1, 0), // debriefing
645 ui_button_info("DB_01", 0, 20, -1, -1, 1), // statistics
646 ui_button_info("DB_02", 0, 195, -1, -1, 2), // scroll stats up
647 ui_button_info("DB_03", 0, 232, -1, -1, 3), // scroll stats down
648 ui_button_info("DB_04", 24, 424, -1, -1, 4), // replay mission
649 ui_button_info("DB_05", 30, 451, -1, -1, 5), // recommendations
650 ui_button_info("DB_06", 211, 445, -1, -1, 6), // first page
651 ui_button_info("DB_07", 234, 445, -1, -1, 7), // prev page
652 ui_button_info("DB_08", 259, 445, -1, -1, 8), // next page
653 ui_button_info("DB_09", 283, 445, -1, -1, 9), // last page
654 ui_button_info("DB_21", 441, 384, -1, -1, 21), // pilot info
655 ui_button_info("DB_25", 511, 384, -1, -1, 25), // kick
656 ui_button_info("DB_15", 604, 224, -1, -1, 15), // medals
657 ui_button_info("DB_16", 615, 329, -1, -1, 16), // scroll pilots up
658 ui_button_info("DB_17", 615, 371, -1, -1, 17), // scroll pilots down
659 ui_button_info("DB_10", 469, 428, -1, -1, 10), // help
660 ui_button_info("DB_11", 447, 452, -1, -1, 11), // options
661 ui_button_info("DB_12", 562, 410, -1, -1, 12), // accept
663 ui_button_info("DB_00", 6, 1, 37, 7, 0), // debriefing
664 ui_button_info("DB_01", 6, 21, 37, 23, 1), // statistics
665 ui_button_info("DB_02", 1, 195, -1, -1, 2), // scroll stats up
666 ui_button_info("DB_03", 1, 236, -1, -1, 3), // scroll stats down
667 ui_button_info("DB_04", 1, 428, 49, 447, 4), // replay mission
668 ui_button_info("DB_05", 17, 459, 49, 464, 5), // recommendations
669 ui_button_info("DB_06", 323, 454, -1, -1, 6), // first page
670 ui_button_info("DB_07", 348, 454, -1, -1, 7), // prev page
671 ui_button_info("DB_08", 372, 454, -1, -1, 8), // next page
672 ui_button_info("DB_09", 396, 454, -1, -1, 9), // last page
673 ui_button_info("DB_10", 441, 384, 433, 413, 10), // pilot info
674 ui_button_info("DB_11", 511, 384, 510, 413, 11), // kick
675 ui_button_info("DB_12", 613, 226, -1, -1, 12), // medals
676 ui_button_info("DB_13", 615, 329, -1, -1, 13), // scroll pilots up
677 ui_button_info("DB_14", 615, 371, -1, -1, 14), // scroll pilots down
678 ui_button_info("DB_15", 538, 431, 500, 440, 15), // help
679 ui_button_info("DB_16", 538, 455, 479, 464, 16), // options
680 ui_button_info("DB_17", 573, 432, 572, 413, 17), // accept
684 ui_button_info("2_DB_00", 10, 1, 59, 12, 0), // debriefing
685 ui_button_info("2_DB_01", 10, 33, 59, 37, 1), // statistics
686 ui_button_info("2_DB_02", 1, 312, -1, -1, 2), // scroll stats up
687 ui_button_info("2_DB_03", 1, 378, -1, -1, 3), // scroll stats down
688 ui_button_info("2_DB_04", 1, 685, 79, 715, 4), // replay mission
689 ui_button_info("2_DB_05", 28, 735, 79, 743, 5), // recommendations
690 ui_button_info("2_DB_06", 517, 726, -1, -1, 6), // first page
691 ui_button_info("2_DB_07", 556, 726, -1, -1, 7), // prev page
692 ui_button_info("2_DB_08", 595, 726, -1, -1, 8), // next page
693 ui_button_info("2_DB_09", 633, 726, -1, -1, 9), // last page
694 ui_button_info("2_DB_10", 706, 615, 700, 661, 10), // pilot info
695 ui_button_info("2_DB_11", 817, 615, 816, 661, 11), // kick
696 ui_button_info("2_DB_12", 981, 362, -1, -1, 12), // medals
697 ui_button_info("2_DB_13", 984, 526, -1, -1, 13), // scroll pilots up
698 ui_button_info("2_DB_14", 984, 594, -1, -1, 14), // scroll pilots down
699 ui_button_info("2_DB_15", 861, 689, 801, 705, 15), // help
700 ui_button_info("2_DB_16", 861, 728, 777, 744, 16), // options
701 ui_button_info("2_DB_17", 917, 692, 917, 692, 17), // accept
707 #define NUM_DEBRIEF_TEXT 10
708 #define MP_TEXT_INDEX_1 4
709 #define MP_TEXT_INDEX_2 5
710 #define MP_TEXT_INDEX_3 6
711 UI_XSTR Debrief_strings[GR_NUM_RESOLUTIONS][NUM_DEBRIEF_TEXT] = {
713 { "Debriefing", 804, 37, 7, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][DEBRIEF_TAB].button },
714 { "Statistics", 1333, 37, 26, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][STATS_TAB].button },
715 { "Replay Mission", 444, 49, 447, UI_XSTR_COLOR_PINK, -1, &Buttons[0][REPLAY_MISSION].button },
716 { "Recommendations", 1334, 49, 464, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][RECOMMENDATIONS].button },
717 { "Pilot", 1310, 433, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_PINFO_POPUP].button },
718 { "Info", 1311, 433, 423, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_PINFO_POPUP].button },
719 { "Kick", 1266, 510, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_KICK].button },
720 { "Help", 928, 500, 440, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][HELP_BUTTON].button },
721 { "Options", 1036, 479, 464, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][OPTIONS_BUTTON].button },
722 { "Accept", 1035, 572, 413, UI_XSTR_COLOR_PINK, -1, &Buttons[0][ACCEPT_BUTTON].button },
725 { "Debriefing", 804, 59, 12, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][DEBRIEF_TAB].button },
726 { "Statistics", 1333, 59, 47, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][STATS_TAB].button },
727 { "Replay Mission", 444, 79, 715, UI_XSTR_COLOR_PINK, -1, &Buttons[1][REPLAY_MISSION].button },
728 { "Recommendations", 1334, 79, 743, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][RECOMMENDATIONS].button },
729 { "Pilot", 1310, 700, 661, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_PINFO_POPUP].button },
730 { "Info", 1311, 700, 679, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_PINFO_POPUP].button },
731 { "Kick", 1266, 816, 661, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_KICK].button },
732 { "Help", 928, 801, 705, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][HELP_BUTTON].button },
733 { "Options", 1036, 780, 744, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][OPTIONS_BUTTON].button },
734 { "Accept", 1035, 917, 672, UI_XSTR_COLOR_PINK, -1, &Buttons[1][ACCEPT_BUTTON].button },
740 char Debrief_current_callsign[CALLSIGN_LEN+10];
741 player *Debrief_player;
743 static UI_WINDOW Debrief_ui_window;
744 static UI_BUTTON List_region;
745 static int Background_bitmap; // bitmap for the background of the debriefing
746 static int Award_bg_bitmap;
747 static int Debrief_multi_loading_bitmap;
748 static int Rank_bitmap;
749 static int Medal_bitmap;
750 static int Badge_bitmap;
751 static int Wings_bitmap;
752 static int Crest_bitmap;
754 static int Rank_text_bitmap;
755 static int Medal_text_bitmap;
756 static int Badge_text_bitmap;
759 static int Debrief_accepted;
760 static int Turned_traitor;
761 static int Must_replay_mission;
763 static int Current_mode;
765 static int Recommend_active;
766 static int Award_active;
767 static int Text_offset;
768 static int Num_text_lines = 0;
769 static int Num_debrief_lines = 0;
770 static int Text_type[MAX_TOTAL_DEBRIEF_LINES];
771 static char *Text[MAX_TOTAL_DEBRIEF_LINES];
773 static int Debrief_inited = 0;
774 static int New_stage;
775 static int Current_stage;
776 static int Num_stages = 0;
777 static int Num_debrief_stages = 0;
778 static int Stage_voice = -1;
780 static int Multi_list_size;
781 static int Multi_list_offset;
783 int Debrief_multi_stages_loaded = 0;
784 int Debrief_multi_voice_loaded = 0;
786 // static int Debrief_voice_ask_for_cd;
788 // voice id's for debriefing text
789 static int Debrief_voices[MAX_DEBRIEF_STAGES];
791 #define DEBRIEF_VOICE_DELAY 400 // time to delay voice playback when a new stage starts
792 static int Debrief_cue_voice; // timestamp to cue the playback of the voice
793 static int Debrief_first_voice_flag = 1; // used to delay the first voice playback extra long
795 // pointer used for getting to debriefing information
796 debriefing Traitor_debriefing; // used when player is a traitor
798 // pointers to the active stages for this debriefing
799 static debrief_stage *Debrief_stages[MAX_DEBRIEF_STAGES];
800 static debrief_stage Promotion_stage, Badge_stage;
801 static debrief_stats_kill_info Debrief_stats_kills[MAX_SHIP_TYPES];
802 static debrief_multi_list_info Multi_list[MAX_PLAYERS];
803 int Multi_list_select;
805 // flag indicating if we should display info for the given player (in multiplayer)
806 int Debrief_should_show_popup = 1;
808 // already shown skip mission popup?
809 static int Debrief_skip_popup_already_shown = 0;
811 void debrief_text_init();
812 void debrief_accept(int ok_to_post_start_game_event = 1);
813 void debrief_kick_selected_player();
816 // promotion voice selection stuff
817 #define NUM_VOLITION_CAMPAIGNS 1
819 char campaign_name[32];
823 v_campaign Volition_campaigns[NUM_VOLITION_CAMPAIGNS] = {
825 BUILTIN_CAMPAIGN, // the only campaign for now, but this leaves room for a mission pack
826 35 // make sure this is equal to the number of missions you gave in the corresponding Debrief_promotion_voice_mapping
830 // data for which voice goes w/ which mission
831 typedef struct voice_map {
832 char mission_file[32];
836 voice_map Debrief_promotion_voice_mapping[NUM_VOLITION_CAMPAIGNS][MAX_CAMPAIGN_MISSIONS] = {
837 { // FreeSpace2 campaign
869 { "SM3-10.fs2", 9 }, // no debriefing for 3-10
871 { "loop1-1.fs2", 4 },
872 { "loop1-2.fs2", 4 },
873 { "loop1-3.fs2", 5 },
874 { "loop2-1.fs2", 4 },
880 #define DB_AWARD_WINGS 0
881 #define DB_AWARD_MEDAL 1
883 #define DB_AWARD_RANK 2
884 #define DB_AWARD_BADGE 3
885 #define DB_AWARD_BG 4
886 static const char* Debrief_award_filename[GR_NUM_RESOLUTIONS][5] = {
903 #define DB_AWARD_SOC 2
904 #define DB_AWARD_RANK 3
905 #define DB_AWARD_BADGE 4
906 #define DB_AWARD_BG 5
907 static const char* Debrief_award_filename[GR_NUM_RESOLUTIONS][6] = {
927 #define AWARD_TEXT_MAX_LINES 5
928 #define AWARD_TEXT_MAX_LINE_LENGTH 128
929 char Debrief_award_text[AWARD_TEXT_MAX_LINES][AWARD_TEXT_MAX_LINE_LENGTH];
930 int Debrief_award_text_num_lines = 0;
934 // prototypes, you know you love 'em
935 void debrief_add_award_text(char *str);
936 void debrief_award_text_clear();
941 const char *debrief_tooltip_handler(const char *str)
943 if (!SDL_strcasecmp(str, NOX("@.Medal"))) {
945 return XSTR( "Medal", 435);
948 } else if (!SDL_strcasecmp(str, NOX("@.Rank"))) {
950 return XSTR( "Rank", 436);
953 } else if (!SDL_strcasecmp(str, NOX("@.Badge"))) {
955 return XSTR( "Badge", 437);
958 } else if (!SDL_strcasecmp(str, NOX("@Medal"))) {
959 if (Medal_bitmap >= 0){
960 return Medals[Player->stats.m_medal_earned].name;
963 } else if (!SDL_strcasecmp(str, NOX("@Rank"))) {
964 if (Rank_bitmap >= 0){
965 return Ranks[Promoted].name;
968 } else if (!SDL_strcasecmp(str, NOX("@Badge"))) {
969 if (Badge_bitmap >= 0){
970 return Medals[Badge_index[Player->stats.m_badge_earned]].name;
977 // initialize the array of handles to the different voice streams
978 void debrief_voice_init()
982 for (i=0; i<MAX_DEBRIEF_STAGES; i++) {
983 Debrief_voices[i] = -1;
987 void debrief_load_voice_file(int voice_num, char *name)
989 int load_attempts = 0;
992 if ( load_attempts++ > 5 ) {
996 Debrief_voices[voice_num] = audiostream_open( name, ASF_VOICE );
997 if ( Debrief_voices[voice_num] >= 0 ) {
1001 // Don't bother to ask for the CD in multiplayer
1002 if ( Game_mode & GM_MULTIPLAYER ) {
1006 // couldn't load voice, ask user to insert CD (if necessary)
1008 // if ( Debrief_voice_ask_for_cd ) {
1009 // if ( game_do_cd_check() == 0 ) {
1010 // Debrief_voice_ask_for_cd = 0;
1017 // open and pre-load the stream buffers for the different voice streams
1018 void debrief_voice_load_all()
1022 // Debrief_voice_ask_for_cd = 1;
1024 for ( i=0; i<Num_debrief_stages; i++ ) {
1025 if ( strlen(Debrief_stages[i]->voice) <= 0 ) {
1028 if ( SDL_strncasecmp(Debrief_stages[i]->voice, NOX("none"), 4) ) {
1029 debrief_load_voice_file(i, Debrief_stages[i]->voice);
1030 // Debrief_voices[i] = audiostream_open(Debrief_stages[i]->voice, ASF_VOICE);
1035 // close all the briefing voice streams
1036 void debrief_voice_unload_all()
1040 for ( i=0; i<MAX_DEBRIEF_STAGES; i++ ) {
1041 if ( Debrief_voices[i] != -1 ) {
1042 audiostream_close_file(Debrief_voices[i], 0);
1043 Debrief_voices[i] = -1;
1048 // start playback of the voice for a particular briefing stage
1049 void debrief_voice_play()
1051 if (!Briefing_voice_enabled || (Current_mode != DEBRIEF_TAB)){
1055 // no more stages? We are done then.
1056 if (Stage_voice >= Num_debrief_stages){
1060 // if in delayed start, see if delay has elapsed and start voice if so
1061 if (Debrief_cue_voice) {
1062 if (!timestamp_elapsed(Debrief_cue_voice)){
1066 Stage_voice++; // move up to next voice
1067 if ((Stage_voice < Num_debrief_stages) && (Debrief_voices[Stage_voice] >= 0)) {
1068 audiostream_play(Debrief_voices[Stage_voice], Master_voice_volume, 0);
1069 Debrief_cue_voice = 0; // indicate no longer in delayed start checking
1075 // see if voice is still playing. If so, do nothing yet.
1076 if ((Stage_voice >= 0) && audiostream_is_playing(Debrief_voices[Stage_voice])){
1080 // set voice to play in a little while from now.
1081 Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY);
1084 // stop playback of the voice for a particular briefing stage
1085 void debrief_voice_stop()
1087 if ((Stage_voice < 0) || (Stage_voice > Num_debrief_stages) || (Debrief_voices[Stage_voice] < 0))
1090 audiostream_stop(Debrief_voices[Stage_voice]); // stream is automatically rewound
1094 // function to deal with inserting possible promition and badge stages into the debriefing
1096 void debrief_multi_fixup_stages()
1100 // possibly insert the badge stage first, them the promotion stage since they are
1101 // inserted at the front of the debrief stages.
1102 if ( Badge_bitmap >= 0 ) {
1103 // move all stages forward one. Don't
1104 for ( i = Num_debrief_stages; i > 0; i-- ) {
1105 Debrief_stages[i] = Debrief_stages[i-1];
1107 Debrief_stages[0] = &Badge_stage;
1108 Num_debrief_stages++;
1111 if ( Promoted >= 0) {
1112 // move all stages forward one
1113 for ( i = Num_debrief_stages; i > 0; i-- ) {
1114 Debrief_stages[i] = Debrief_stages[i-1];
1116 Debrief_stages[0] = &Promotion_stage;
1117 Num_debrief_stages++;
1122 // function called from multiplayer clients to set up the debriefing information for them
1123 // (sent from the server).
1124 void debrief_set_multi_clients( int stage_count, int active_stages[] )
1128 // set up the right briefing for this guy
1129 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
1130 Debriefing = &Debriefings[Net_player->p_info.team];
1132 Debriefing = &Debriefings[0];
1135 // see if this client was promoted -- if so, then add the first stage.
1136 Num_debrief_stages = 0;
1138 // set the pointers to the debriefings for this client
1139 for (i = 0; i < stage_count; i++) {
1140 Debrief_stages[Num_debrief_stages++] = &Debriefing->stages[active_stages[i]];
1143 Debrief_multi_stages_loaded = 1;
1146 // evaluate all stages for all teams. Server of a multiplayer game will have to send that
1147 // information to all clients after leaving this screen.
1148 void debrief_multi_server_stuff()
1150 debriefing *debriefp;
1152 int stage_active[MAX_TEAMS][MAX_DEBRIEF_STAGES], *stages[MAX_TEAMS];
1153 int i, j, num_stages, stage_count[MAX_TEAMS];
1155 memset( stage_active, 0, sizeof(stage_active) );
1157 for (i=0; i<Num_teams; i++) {
1158 debriefp = &Debriefings[i];
1160 stages[i] = stage_active[i];
1161 for (j=0; j<debriefp->num_stages; j++) {
1162 if ( eval_sexp(debriefp->stages[j].formula) ) {
1163 stage_active[i][num_stages] = j;
1168 stage_count[i] = num_stages;
1171 // if we're in campaign mode, evaluate campaign stuff
1172 if (Netgame.campaign_mode == MP_CAMPAIGN) {
1173 multi_campaign_eval_debrief();
1176 // send the information to all clients.
1177 send_debrief_info( stage_count, stages );
1181 // --------------------------------------------------------------------------------------
1182 // debrief_set_stages_and_multi_stuff()
1184 // Set up the active stages for this debriefing
1186 // returns: number of active debriefing stages
1188 int debrief_set_stages_and_multi_stuff()
1191 debriefing *debriefp;
1193 if ( MULTIPLAYER_CLIENT ) {
1197 Num_debrief_stages = 0;
1199 if ( Game_mode & GM_MULTIPLAYER ) {
1200 debrief_multi_server_stuff();
1203 // check to see if player is a traitor (looking at his team). If so, use the special
1204 // traitor debriefing. Only done in single player
1205 debriefp = Debriefing;
1206 if ( !(Game_mode & GM_MULTIPLAYER) ) {
1207 if (Player_ship->team == TEAM_TRAITOR)
1208 debriefp = &Traitor_debriefing;
1211 Num_debrief_stages = 0;
1212 if (Promoted >= 0) {
1213 Debrief_stages[Num_debrief_stages++] = &Promotion_stage;
1216 if (Badge_bitmap >= 0) {
1217 Debrief_stages[Num_debrief_stages++] = &Badge_stage;
1220 for (i=0; i<debriefp->num_stages; i++) {
1221 if (eval_sexp(debriefp->stages[i].formula) == 1) {
1222 Debrief_stages[Num_debrief_stages++] = &debriefp->stages[i];
1226 return Num_debrief_stages;
1229 // init the buttons that are specific to the debriefing screen
1230 void debrief_buttons_init()
1235 for ( i=0; i<NUM_BUTTONS; i++ ) {
1236 b = &Buttons[gr_screen.res][i];
1237 b->button.create( &Debrief_ui_window, "", b->x, b->y, 60, 30, 0 /*b->flags & REPEAT*/, 1 );
1238 // set up callback for when a mouse first goes over a button
1239 b->button.set_highlight_action( common_play_highlight_sound );
1240 b->button.set_bmaps(b->filename);
1241 b->button.link_hotspot(b->hotspot);
1246 for(i=0; i<NUM_DEBRIEF_TEXT; i++){
1247 // multiplayer specific text
1248 if((i == MP_TEXT_INDEX_1) || (i == MP_TEXT_INDEX_2) || (i == MP_TEXT_INDEX_3)){
1249 // only add if in multiplayer mode
1250 if(Game_mode & GM_MULTIPLAYER){
1251 Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
1256 Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
1261 // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1262 Buttons[gr_screen.res][NEXT_STAGE].button.set_hotkey(SDLK_RIGHT);
1263 Buttons[gr_screen.res][PREV_STAGE].button.set_hotkey(SDLK_LEFT);
1264 Buttons[gr_screen.res][LAST_STAGE].button.set_hotkey(KEY_SHIFTED | SDLK_RIGHT);
1265 Buttons[gr_screen.res][FIRST_STAGE].button.set_hotkey(KEY_SHIFTED | SDLK_LEFT);
1266 Buttons[gr_screen.res][TEXT_SCROLL_UP].button.set_hotkey(SDLK_UP);
1267 Buttons[gr_screen.res][TEXT_SCROLL_DOWN].button.set_hotkey(SDLK_DOWN);
1268 Buttons[gr_screen.res][ACCEPT_BUTTON].button.set_hotkey(KEY_CTRLED+SDLK_RETURN);
1270 // if in multiplayer, disable the button for all players except the host
1271 // also disable for squad war matches
1272 if(Game_mode & GM_MULTIPLAYER){
1273 if((Netgame.type_flags & NG_TYPE_SW) || !(Net_player->flags & NETINFO_FLAG_GAME_HOST)){
1274 Buttons[gr_screen.res][REPLAY_MISSION].button.disable();
1279 // --------------------------------------------------------------------------------------
1280 // debrief_ui_init()
1282 void debrief_ui_init()
1284 // init ship selection masks and buttons
1285 common_set_interface_palette("DebriefPalette"); // set the interface palette
1286 Debrief_ui_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
1287 Debrief_ui_window.set_mask_bmap(Debrief_mask_name[gr_screen.res]);
1288 Debrief_ui_window.tooltip_handler = debrief_tooltip_handler;
1289 debrief_buttons_init();
1291 // load in help overlay bitmap
1292 help_overlay_load(DEBRIEFING_OVERLAY);
1293 help_overlay_set_state(DEBRIEFING_OVERLAY,0);
1295 if ( Game_mode & GM_MULTIPLAYER ) {
1296 // close down any old instances of the chatbox
1299 // create the new one
1301 Background_bitmap = bm_load(Debrief_multi_name[gr_screen.res]);
1302 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);
1305 Background_bitmap = bm_load(Debrief_single_name[gr_screen.res]);
1308 if ( Background_bitmap < 0 ) {
1309 Warning(LOCATION, "Could not load the background bitmap for debrief screen");
1312 Award_bg_bitmap = bm_load(Debrief_award_filename[gr_screen.res][DB_AWARD_BG]);
1313 Debrief_multi_loading_bitmap = bm_load(Debrief_loading_bitmap_fname[gr_screen.res]);
1316 // sets Promotion_stage.voice
1317 // defaults to number 9 (Petrarch) for non-volition missions
1318 // this is an ugly, nasty way of doing this, but it saves us changing the missions at this point
1319 void debrief_choose_promotion_voice()
1321 if(Campaign.current_mission < 0){
1323 SDL_snprintf(Promotion_stage.voice, SDL_arraysize(Promotion_stage.voice), NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
1325 SDL_snprintf(Promotion_stage.voice, SDL_arraysize(Promotion_stage.voice), NOX("1_%s"), Ranks[Promoted].promotion_voice_base);
1330 // search thru all official campaigns for our current campaign
1331 if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename[0])) {
1333 if (Player->on_bastion) {
1334 SDL_snprintf(Promotion_stage.voice, SDL_arraysize(Promotion_stage.voice), NOX("3_%s"), Ranks[Promoted].promotion_voice_base);
1336 SDL_snprintf(Promotion_stage.voice, SDL_arraysize(Promotion_stage.voice), NOX("1_%s"), Ranks[Promoted].promotion_voice_base);
1341 for (i=0; i<NUM_VOLITION_CAMPAIGNS; i++) {
1342 if ((Campaign.filename[0]) && !SDL_strcasecmp(Campaign.filename, Volition_campaigns[i].campaign_name)) {
1343 // now search thru the mission filenames,
1344 for (j=0; j<Volition_campaigns[i].num_missions; j++) {
1345 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !SDL_strcasecmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file)) {
1346 // found it! set the persona and bail
1347 SDL_snprintf(Promotion_stage.voice, SDL_arraysize(Promotion_stage.voice), NOX("%d_%s"), Debrief_promotion_voice_mapping[i][j].persona_index, Ranks[Promoted].promotion_voice_base);
1357 // default to petrarch
1358 SDL_snprintf(Promotion_stage.voice, SDL_arraysize(Promotion_stage.voice), NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
1360 // default to FS1 guy
1361 SDL_snprintf(Promotion_stage.voice, SDL_arraysize(Promotion_stage.voice), NOX("1_%s"), Ranks[Promoted].promotion_voice_base);
1365 // sets Promotion_stage.voice
1366 // defaults to number 9 (Petrarch) for non-volition missions
1367 // this is an ugly, nasty, hateful way of doing this, but it saves us changing the missions at this point
1368 void debrief_choose_badge_voice()
1370 if(Campaign.current_mission < 0){
1372 // default to petrarch
1373 SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1375 // default to FS1 guy
1376 SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1381 if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename[0])) {
1383 if ( Player->on_bastion ) {
1384 SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base2);
1387 SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1393 // search thru all official campaigns for our current campaign
1394 for (i=0; i<NUM_VOLITION_CAMPAIGNS; i++) {
1395 if ((Campaign.filename[0]) && !SDL_strcasecmp(Campaign.filename, Volition_campaigns[i].campaign_name)) {
1396 // now search thru the mission filenames,
1397 for (j=0; j<Campaign.num_missions; j++) {
1398 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !SDL_strcasecmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file)) {
1399 // found it! set the persona and bail
1400 SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("%d_%s"), Debrief_promotion_voice_mapping[i][j].persona_index, Badge_info[Player->stats.m_badge_earned].voice_base);
1410 // default to petrarch
1411 SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1413 // default to FS1 guy
1414 SDL_snprintf(Badge_stage.voice, SDL_arraysize(Badge_stage.voice), NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1419 void debrief_award_init()
1431 // be sure there are no old award texts floating around
1433 debrief_award_text_clear();
1436 // handle medal earned
1437 if (Player->stats.m_medal_earned != -1) {
1438 if (Player->stats.m_medal_earned == 13) { // special hack for the wings..
1440 if ( Player->stats.medals[13] > 1 ) {
1445 SDL_snprintf(buf, SDL_arraysize(buf), NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_WINGS], ver);
1446 Wings_bitmap = bm_load(buf);
1448 } else if (Player->stats.m_medal_earned == 17) { // special hack for the soc crest
1449 Crest_bitmap = bm_load(Debrief_award_filename[gr_screen.res][DB_AWARD_SOC]);
1452 SDL_snprintf(buf, SDL_arraysize(buf), NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_MEDAL], Player->stats.m_medal_earned);
1453 Medal_bitmap = bm_load(buf);
1457 debrief_add_award_text(Medals[Player->stats.m_medal_earned].name);
1461 // handle promotions
1462 if ( Player->stats.m_promotion_earned != -1 ) {
1463 Promoted = Player->stats.m_promotion_earned;
1464 SDL_snprintf(buf, SDL_arraysize(buf), NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_RANK], Promoted + 1);
1465 Rank_bitmap = bm_load(buf);
1467 Promotion_stage.new_text = Ranks[Promoted].promotion_text;
1468 Promotion_stage.new_recommendation_text = NULL;
1470 // choose appropriate promotion voice for this mission
1471 debrief_choose_promotion_voice();
1474 debrief_add_award_text(Ranks[Promoted].name);
1478 // handle badge earned
1479 // only grant badge if earned and allowed. (no_promotion really means no promotion and no badges)
1480 if ( Player->stats.m_badge_earned != -1 ) {
1481 i = Player->stats.m_badge_earned;
1482 SDL_snprintf(buf, SDL_arraysize(buf), NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_BADGE], i + 1);
1483 Badge_bitmap = bm_load(buf);
1485 Badge_stage.new_text = Badge_info[i].promotion_text;
1486 Badge_stage.new_recommendation_text = NULL;
1488 // choose appropriate voice
1489 debrief_choose_badge_voice();
1492 debrief_add_award_text(Medals[Badge_index[i]].name);
1496 if ((Rank_bitmap >= 0) || (Medal_bitmap >= 0) || (Badge_bitmap >= 0) || (Wings_bitmap >= 0) || (Crest_bitmap >= 0)) {
1503 // debrief_traitor_init() initializes local data which could be used if the player leaves the
1504 // mission a traitor. The same debriefing always gets played
1505 void debrief_traitor_init()
1507 static int inited = 0;
1510 debriefing *debrief;
1511 debrief_stage *stagep;
1514 // open localization
1518 read_file_text("traitor.tbl");
1521 // simplied form of the debriefing stuff.
1522 debrief = &Traitor_debriefing;
1523 required_string("#Debriefing_info");
1525 required_string("$Num stages:");
1526 stuff_int(&debrief->num_stages);
1527 SDL_assert(debrief->num_stages == 1);
1530 stagep = &debrief->stages[stage_num++];
1531 required_string("$Formula:");
1532 stagep->formula = get_sexp_main();
1533 required_string("$multi text");
1534 if ( Fred_running ) {
1535 stuff_string( stagep->new_text, F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1537 stagep->new_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1539 required_string("$Voice:");
1540 char traitor_voice_file[NAME_LENGTH];
1541 stuff_string(traitor_voice_file, F_FILESPEC, NULL);
1543 // DKA 9/13/99 Only 1 traitor msg for FS2
1545 if ( Player->on_bastion ) {
1546 SDL_strlcpy(stagep->voice, NOX("3_"), SDL_arraysize(stagep->voice));
1548 SDL_strlcpy(stagep->voice, NOX("1_"), SDL_arraysize(stagep->voice));
1552 SDL_strlcat(stagep->voice, traitor_voice_file, SDL_arraysize(stagep->voice));
1554 required_string("$Recommendation text:");
1555 if ( Fred_running ) {
1556 stuff_string( stagep->new_recommendation_text, F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1558 stagep->new_recommendation_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1562 } catch (parse_error_t rval) {
1563 Error(LOCATION, "Unable to parse traitor.tbl! Code = %i.\n", (int)rval);
1566 // close localization
1570 // disable the accept button if in single player and I am a traitor
1571 Debrief_accepted = 0;
1572 Turned_traitor = Must_replay_mission = 0;
1573 if (!(Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_CAMPAIGN_MODE)) {
1574 if (Player_ship->team == TEAM_TRAITOR){
1578 if (Campaign.next_mission == Campaign.current_mission){
1579 Must_replay_mission = 1;
1583 if (Turned_traitor || Must_replay_mission) {
1584 Buttons[gr_screen.res][ACCEPT_BUTTON].button.hide();
1586 // kill off any stats
1587 Player->flags &= ~PLAYER_FLAGS_PROMOTED;
1588 scoring_level_init( &Player->stats );
1592 // initialization for listing of players in game
1593 void debrief_multi_list_init()
1595 Multi_list_size = 0; // number of net players to choose from
1596 Multi_list_offset = 0;
1598 Multi_list_select = -1;
1600 if ( !(Game_mode & GM_MULTIPLAYER) )
1603 debrief_rebuild_player_list();
1605 // switch stats display to this newly selected player
1606 set_player_stats(Multi_list[0].net_player_index);
1607 SDL_strlcpy(Debrief_current_callsign, Multi_list[0].callsign, SDL_arraysize(Debrief_current_callsign));
1608 Debrief_player = Player;
1611 void debrief_multi_list_scroll_up()
1613 // if we're at the beginning of the list, don't do anything
1614 if(Multi_list_offset == 0){
1615 gamesnd_play_iface(SND_GENERAL_FAIL);
1619 // otherwise scroll up
1620 Multi_list_offset--;
1621 gamesnd_play_iface(SND_USER_SELECT);
1624 void debrief_multi_list_scroll_down()
1626 // if we can scroll down no further
1627 if(Multi_list_size < Debrief_multi_list_team_max_display[gr_screen.res]){
1628 gamesnd_play_iface(SND_GENERAL_FAIL);
1631 if((Multi_list_offset + Debrief_multi_list_team_max_display[gr_screen.res]) >= Multi_list_size){
1632 gamesnd_play_iface(SND_GENERAL_FAIL);
1636 // otherwise scroll down
1637 Multi_list_offset++;
1638 gamesnd_play_iface(SND_USER_SELECT);
1641 // draw the connected net players
1642 void debrief_multi_list_draw()
1644 int y, z, font_height,idx;
1645 char str[CALLSIGN_LEN+5];
1648 font_height = gr_get_font_height();
1650 // if we currently have no item picked, pick a reasonable one
1651 if((Multi_list_size >= 0) && (Multi_list_select == -1)){
1652 // select the entry which corresponds to the local player
1653 Multi_list_select = 0;
1654 for(idx=0;idx<Multi_list_size;idx++){
1655 if(Multi_list[idx].net_player_index == MY_NET_PLAYER_NUM){
1656 Multi_list_select = idx;
1658 // switch stats display to this newly selected player
1659 set_player_stats(Multi_list[idx].net_player_index);
1660 SDL_strlcpy(Debrief_current_callsign, Multi_list[idx].callsign, SDL_arraysize(Debrief_current_callsign));
1661 Debrief_player = Net_players[Multi_list[idx].net_player_index].player;
1667 // draw the list itself
1669 z = Multi_list_offset;
1670 while (y + font_height <= Debrief_list_coords[gr_screen.res][3]){
1671 np = &Net_players[Multi_list[z].net_player_index];
1673 if (z >= Multi_list_size){
1676 // set the proper text color for the highlight
1677 if(np->flags & NETINFO_FLAG_GAME_HOST){
1678 if(Multi_list_select == z){
1679 gr_set_color_fast(&Color_text_active_hi);
1681 gr_set_color_fast(&Color_bright);
1684 if(Multi_list_select == z){
1685 gr_set_color_fast(&Color_text_active);
1687 gr_set_color_fast(&Color_text_normal);
1691 // blit the proper indicator - skipping observers
1692 if(!((np->flags & NETINFO_FLAG_OBSERVER) && !(np->flags & NETINFO_FLAG_OBS_PLAYER))){
1693 if(Netgame.type_flags & NG_TYPE_TEAM){
1695 if(np->p_info.team == 0){
1696 // draw his "selected" icon
1697 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM0_SELECT] != -1)){
1698 gr_set_bitmap(Multi_common_icons[MICON_TEAM0_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1699 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1701 // draw his "normal" icon
1702 else if(Multi_common_icons[MICON_TEAM0] != -1){
1703 gr_set_bitmap(Multi_common_icons[MICON_TEAM0], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1704 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1706 } else if(np->p_info.team == 1){
1707 // draw his "selected" icon
1708 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM1_SELECT] != -1)){
1709 gr_set_bitmap(Multi_common_icons[MICON_TEAM1_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1710 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1712 // draw his "normal" icon
1713 else if(Multi_common_icons[MICON_TEAM1] != -1){
1714 gr_set_bitmap(Multi_common_icons[MICON_TEAM1], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1715 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1719 // draw the team 0 selected icon
1720 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM0_SELECT] != -1)){
1721 gr_set_bitmap(Multi_common_icons[MICON_TEAM0_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1722 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1727 SDL_strlcpy(str, Multi_list[z].callsign, SDL_arraysize(str));
1728 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)){
1729 SDL_strlcat(str, XSTR( "(O)", 438), SDL_arraysize(str));
1733 gr_string(Debrief_list_coords[gr_screen.res][0] + MULTI_LIST_TEAM_OFFSET, Debrief_list_coords[gr_screen.res][1] + y, str);
1740 void debrief_kick_selected_player()
1742 if(Multi_list_select >= 0){
1743 SDL_assert(Net_player->flags & NETINFO_FLAG_GAME_HOST);
1744 multi_kick_player(Multi_list[Multi_list_select].net_player_index);
1748 // get optional mission popup text
1749 void debrief_assemble_optional_mission_popup_text(char *buffer, const int buf_len, char *mission_loop_desc)
1751 SDL_assert(buffer != NULL);
1754 if (mission_loop_desc == NULL) {
1755 SDL_strlcpy(buffer, XSTR("<No Mission Loop Description Available>", 1490), buf_len);
1756 mprintf(("No mission loop description avail"));
1758 SDL_strlcpy(buffer, mission_loop_desc, buf_len);
1761 SDL_strlcat(buffer, XSTR("\n\n\nDo you want to play the optional mission?", 1491), buf_len);
1764 // what to do when the accept button is hit
1765 void debrief_accept(int ok_to_post_start_game_event)
1769 if ( (/*Cheats_enabled ||*/ Turned_traitor || Must_replay_mission) && (Game_mode & GM_CAMPAIGN_MODE) ) {
1773 if (Game_mode & GM_MULTIPLAYER) {
1777 if (Player_ship->team == TEAM_TRAITOR){
1778 str = XSTR( "Your career is over, Traitor! You can't accept new missions!", 439);
1779 }/* else if (Cheats_enabled) {
1780 str = XSTR( "You are a cheater. You cannot accept this mission!", 440);
1782 str = XSTR( "You have failed this mission and cannot accept. What do you you wish to do instead?", 441);
1785 z = popup(0, 3, XSTR( "Return to &Debriefing", 442), XSTR( "Go to &Flight Deck", 443), XSTR( "&Replay Mission", 444), str);
1787 gameseq_post_event(GS_EVENT_START_BRIEFING); // cycle back to briefing
1788 } else if ( z == 1 ) {
1789 gameseq_post_event(GS_EVENT_END_GAME); // return to main hall, tossing stats
1795 Debrief_accepted = 1;
1796 // save mission stats
1797 if (Game_mode & GM_MULTIPLAYER) {
1798 // note that multi_debrief_accept_hit() will handle all mission_campaign_* calls on its own
1799 // as well as doing stats transfers, etc.
1800 multi_debrief_accept_hit();
1804 int play_commit_sound = 1;
1805 // only write the player's stats if he's accepted
1807 // if we are just playing a single mission, then don't do many of the things
1808 // that need to be done. Nothing much should happen when just playing a single
1809 // mission that isn't in a campaign.
1810 if ( Game_mode & GM_CAMPAIGN_MODE ) {
1812 // check for possible mission loop
1813 // check for (1) mission loop available, (2) dont have to repeat last mission
1814 if(!(Game_mode & GM_MULTIPLAYER)){
1815 int cur = Campaign.current_mission;
1816 bool require_repeat_mission = (Campaign.current_mission == Campaign.next_mission);
1817 if (Campaign.missions[cur].has_mission_loop) {
1818 SDL_assert(Campaign.loop_mission != CAMPAIGN_LOOP_MISSION_UNINITIALIZED);
1821 if ( (Campaign.missions[cur].has_mission_loop && (Campaign.loop_mission != -1)) && !require_repeat_mission ) {
1824 debrief_assemble_optional_mission_popup_text(buffer, Campaign.missions[cur].mission_loop_desc);
1826 int choice = popup(0 , 2, POPUP_NO, POPUP_YES, buffer);
1828 Campaign.loop_enabled = 1;
1829 Campaign.next_mission = Campaign.loop_mission;
1838 if(ok_to_post_start_game_event){
1839 gameseq_post_event(GS_EVENT_LOOP_BRIEF);
1841 play_commit_sound = 0;
1844 // continue as normal
1847 // if single player campagin, maybe mark shivans as visible in
1848 // tech room at completion of mission 5
1849 if ( !(Game_mode & GM_MULTIPLAYER) && (Intel_info[2].in_tech_db == 0) ) {
1850 char *m_name = Campaign.missions[Campaign.current_mission].name;
1852 if ( m_name && !SDL_strcasecmp(m_name, "sm1-05a.fsm") ) {
1853 Intel_info[2].in_tech_db = 1;
1859 mission_campaign_mission_over();
1861 // check to see if we are out of the loop now
1862 if ( Campaign.next_mission == Campaign.loop_reentry ) {
1863 Campaign.loop_enabled = 0;
1866 // check if campaign is over
1867 if ( Campaign.next_mission == -1 ) {
1868 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
1869 gameseq_post_event(GS_EVENT_END_DEMO);
1871 gameseq_post_event(GS_EVENT_MAIN_MENU);
1874 if ( ok_to_post_start_game_event ) {
1875 gameseq_post_event(GS_EVENT_START_GAME);
1877 play_commit_sound = 0;
1882 gameseq_post_event(GS_EVENT_MAIN_MENU);
1885 if ( play_commit_sound ) {
1886 gamesnd_play_iface(SND_COMMIT_PRESSED);
1893 void debrief_next_tab()
1895 New_mode = Current_mode + 1;
1896 if (New_mode >= NUM_TABS)
1900 void debrief_prev_tab()
1902 New_mode = Current_mode - 1;
1904 New_mode = NUM_TABS - 1;
1907 // --------------------------------------------------------------------------------------
1908 // debrief_next_stage()
1910 void debrief_next_stage()
1912 if (Current_stage < Num_stages - 1) {
1913 New_stage = Current_stage + 1;
1914 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1917 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1920 // --------------------------------------------------------------------------------------
1921 // debrief_prev_stage()
1923 void debrief_prev_stage()
1925 if (Current_stage) {
1926 New_stage = Current_stage - 1;
1927 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1930 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1933 // --------------------------------------------------------------------------------------
1934 // debrief_first_stage()
1935 void debrief_first_stage()
1937 if (Current_stage) {
1939 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1942 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1945 // --------------------------------------------------------------------------------------
1946 // debrief_last_stage()
1947 void debrief_last_stage()
1949 if (Current_stage != Num_stages - 1) {
1950 New_stage = Num_stages - 1;
1951 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1954 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1957 // draw what stage number the debriefing is on
1958 void debrief_render_stagenum()
1966 SDL_snprintf(buf, SDL_arraysize(buf), XSTR( "%d of %d", 445), Current_stage + 1, Num_stages);
1967 gr_get_string_size(&w, NULL, buf);
1968 gr_set_color_fast(&Color_bright_blue);
1969 gr_string(Debrief_stage_info_coords[gr_screen.res][0] - w, Debrief_stage_info_coords[gr_screen.res][1], buf);
1970 gr_set_color_fast(&Color_white);
1973 // render the mission time at the specified y location
1974 void debrief_render_mission_time(int y_loc)
1978 game_format_time(Missiontime, time_str, SDL_arraysize(time_str));
1979 gr_string(0, y_loc, XSTR( "Mission Time", 446));
1980 gr_string(Debrief_text_x2[gr_screen.res], y_loc, time_str);
1983 // render out the debriefing text to the scroll window
1984 void debrief_render()
1986 int y, z, font_height;
1988 if ( Num_stages <= 0 )
1991 font_height = gr_get_font_height();
1993 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]);
1996 while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
1997 if (z >= Num_text_lines)
2000 if (Text_type[z] == TEXT_TYPE_NORMAL)
2001 gr_set_color_fast(&Color_white);
2003 gr_set_color_fast(&Color_bright_red);
2006 gr_string(0, y, Text[z]);
2015 // render out the stats info to the scroll window
2017 void debrief_stats_render()
2019 int i, y, font_height;
2021 gr_set_color_fast(&Color_blue);
2022 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]);
2023 gr_string(0, 0, Debrief_current_callsign);
2024 font_height = gr_get_font_height();
2027 switch ( Current_stage ) {
2028 case DEBRIEF_MISSION_STATS:
2029 i = Current_stage - 1;
2033 gr_set_color_fast(&Color_white);
2035 // display mission completion time
2036 debrief_render_mission_time(y);
2039 show_stats_label(i, 0, y, font_height);
2040 show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2042 case DEBRIEF_ALLTIME_STATS:
2043 i = Current_stage - 1;
2047 gr_set_color_fast(&Color_white);
2048 show_stats_label(i, 0, y, font_height);
2049 show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2052 case DEBRIEF_ALLTIME_KILLS:
2053 case DEBRIEF_MISSION_KILLS:
2054 gr_set_color_fast(&Color_white);
2056 while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
2057 if (i >= Num_text_lines)
2061 if ( Current_stage == DEBRIEF_MISSION_KILLS )
2062 gr_printf(0, y, XSTR( "Mission Kills by Ship Type", 447));
2064 gr_printf(0, y, XSTR( "All-time Kills by Ship Type", 448));
2067 gr_printf(0, y, "%s", Debrief_stats_kills[i - 2].text);
2068 gr_printf(Debrief_text_x2[gr_screen.res], y, "%d", Debrief_stats_kills[i - 2].num);
2075 if (Num_text_lines == 2) {
2076 if ( Current_stage == DEBRIEF_MISSION_KILLS )
2077 gr_printf(0, y, XSTR( "(No ship kills this mission)", 449));
2079 gr_printf(0, y, XSTR( "(No ship kills)", 450));
2092 // do action for when the replay button is pressed
2093 void debrief_replay_pressed()
2095 if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2097 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));
2104 gameseq_post_event(GS_EVENT_START_BRIEFING); // take us to the briefing
2105 gamesnd_play_iface(SND_COMMIT_PRESSED);
2108 // -------------------------------------------------------------------
2109 // debrief_redraw_pressed_buttons()
2111 // Redraw any debriefing buttons that are pressed down. This function is needed
2112 // since we sometimes need to draw pressed buttons last to ensure the entire
2113 // button gets drawn (and not overlapped by other buttons)
2115 void debrief_redraw_pressed_buttons()
2120 for ( i=0; i<NUM_BUTTONS; i++ ) {
2121 b = &Buttons[gr_screen.res][i].button;
2122 // don't draw the recommendations button if we're in stats mode
2123 if ( b->button_down() ) {
2129 // debrief specific button with hotspot 'i' has been pressed, so perform the associated action
2131 void debrief_button_pressed(int num)
2135 Buttons[gr_screen.res][RECOMMENDATIONS].button.enable();
2136 // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
2137 if (num != Current_mode){
2138 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
2143 // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 1; // allows failure sound to be played
2144 Buttons[gr_screen.res][RECOMMENDATIONS].button.disable();
2145 if (num != Current_mode){
2146 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
2151 case TEXT_SCROLL_UP:
2154 gamesnd_play_iface(SND_SCROLL);
2156 gamesnd_play_iface(SND_GENERAL_FAIL);
2160 case TEXT_SCROLL_DOWN:
2161 if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
2163 gamesnd_play_iface(SND_SCROLL);
2165 gamesnd_play_iface(SND_GENERAL_FAIL);
2169 case REPLAY_MISSION:
2170 if(Game_mode & GM_MULTIPLAYER){
2171 multi_debrief_replay_hit();
2173 debrief_replay_pressed();
2177 case RECOMMENDATIONS:
2178 gamesnd_play_iface(SND_USER_SELECT);
2179 Recommend_active = !Recommend_active;
2180 debrief_text_init();
2184 debrief_first_stage();
2188 debrief_prev_stage();
2192 debrief_next_stage();
2196 debrief_last_stage();
2200 gamesnd_play_iface(SND_HELP_PRESSED);
2201 launch_context_help();
2204 case OPTIONS_BUTTON:
2205 gamesnd_play_iface(SND_SWITCH_SCREENS);
2206 gameseq_post_event( GS_EVENT_OPTIONS_MENU );
2214 gamesnd_play_iface(SND_SWITCH_SCREENS);
2215 gameseq_post_event(GS_EVENT_VIEW_MEDALS);
2218 case PLAYER_SCROLL_UP:
2219 debrief_multi_list_scroll_up();
2222 case PLAYER_SCROLL_DOWN:
2223 debrief_multi_list_scroll_down();
2226 case MULTI_PINFO_POPUP:
2227 Debrief_should_show_popup = 1;
2231 debrief_kick_selected_player();
2236 void debrief_setup_ship_kill_stats(int stage_num)
2244 debrief_stats_kill_info *kill_info;
2246 SDL_assert(Current_stage < DEBRIEF_NUM_STATS_PAGES);
2247 if ( Current_stage == DEBRIEF_MISSION_STATS || Current_stage == DEBRIEF_ALLTIME_STATS )
2250 SDL_assert(Debrief_player != NULL);
2252 // kill_ar points to an array of MAX_SHIP_TYPE ints
2253 if ( Current_stage == DEBRIEF_MISSION_KILLS ) {
2254 kill_arr = Debrief_player->stats.m_okKills;
2256 kill_arr = Debrief_player->stats.kills;
2260 for ( i=0; i<MAX_SHIP_TYPES; i++ ) {
2262 // code used to add in mission kills, but the new system assumes that the player will accept, so
2263 // all time stats already have mission stats added in.
2264 if ( kill_arr[i] <= 0 ){
2269 kill_info = &Debrief_stats_kills[Num_text_lines++];
2271 kill_info->num = kill_arr[i];
2273 SDL_strlcpy(kill_info->text, Ship_info[i].name, SDL_arraysize(kill_info->text));
2274 SDL_strlcat(kill_info->text, NOX(":"), SDL_arraysize(kill_info->text));
2277 Num_text_lines += 2;
2280 // Iterate through the debriefing buttons, checking if they are pressed
2281 void debrief_check_buttons()
2285 for ( i=0; i<NUM_BUTTONS; i++ ) {
2286 if ( Buttons[gr_screen.res][i].button.pressed() ) {
2287 debrief_button_pressed(i);
2291 if ( !(Game_mode & GM_MULTIPLAYER) )
2294 if (List_region.pressed()) {
2295 List_region.get_mouse_pos(NULL, &y);
2296 z = Multi_list_offset + y / gr_get_font_height();
2297 if ((z >= 0) && (z < Multi_list_size)) {
2298 // switch stats display to this newly selected player
2299 set_player_stats(Multi_list[z].net_player_index);
2300 SDL_strlcpy(Debrief_current_callsign, Multi_list[z].callsign, SDL_arraysize(Debrief_current_callsign));
2301 Debrief_player = Net_players[Multi_list[z].net_player_index].player;
2302 Multi_list_select = z;
2303 debrief_setup_ship_kill_stats(Current_stage);
2304 gamesnd_play_iface(SND_USER_SELECT);
2308 // if the player was double clicked on - we should popup a player info popup
2310 if (List_region.double_clicked()) {
2311 Debrief_should_show_popup = 1;
2316 void debrief_text_stage_init(const char *src, int type)
2318 int i, n_lines, n_chars[MAX_DEBRIEF_LINES];
2319 char line[MAX_DEBRIEF_LINE_LEN];
2320 char *p_str[MAX_DEBRIEF_LINES];
2323 n_lines = split_str(src, Debrief_text_wnd_coords[gr_screen.res][2], n_chars, p_str, MAX_DEBRIEF_LINES);
2324 SDL_assert(n_lines >= 0);
2326 // if you hit this, you proba
2327 if(n_lines >= MAX_DEBRIEF_LINES){
2328 Warning(LOCATION, "You have come close to the limit of debriefing lines, try adding more stages");
2331 for ( i=0; i<n_lines; i++ ) {
2332 SDL_assert(n_chars[i] < MAX_DEBRIEF_LINE_LEN);
2333 SDL_assert(Num_text_lines < MAX_TOTAL_DEBRIEF_LINES);
2334 len = SDL_min(n_chars[i] + 1, MAX_DEBRIEF_LINE_LEN);
2335 SDL_strlcpy(line, p_str[i], len);
2336 line[n_chars[i]] = 0;
2337 drop_white_space(line);
2338 Text_type[Num_text_lines] = type;
2339 Text[Num_text_lines++] = strdup(line);
2345 void debrief_free_text()
2349 for (i=0; i<Num_debrief_lines; i++)
2353 Num_debrief_lines = 0;
2356 // setup the debriefing text lines for rendering
2357 void debrief_text_init()
2362 // release old text lines first
2363 debrief_free_text();
2364 Num_text_lines = Text_offset = 0;
2366 if (Current_mode == DEBRIEF_TAB) {
2367 for (i=0; i<Num_debrief_stages; i++) {
2369 Text[Num_text_lines++] = NULL; // add a blank line between stages
2371 src = Debrief_stages[i]->new_text;
2373 debrief_text_stage_init(src, TEXT_TYPE_NORMAL);
2375 if (Recommend_active) {
2376 src = Debrief_stages[i]->new_recommendation_text;
2377 if (!src && (i == Num_debrief_stages - 1) && !r_count)
2378 src = XSTR( "We have no recommendations for you.", 1054);
2381 Text[Num_text_lines++] = NULL;
2382 debrief_text_stage_init(src, TEXT_TYPE_RECOMMENDATION);
2388 Num_debrief_lines = Num_text_lines;
2392 // not in debriefing mode, must be in stats mode
2394 debrief_setup_ship_kill_stats(Current_stage);
2398 // --------------------------------------------------------------------------------------
2402 SDL_assert(!Debrief_inited);
2403 // Campaign.loop_enabled = 0;
2404 Campaign.loop_mission = CAMPAIGN_LOOP_MISSION_UNINITIALIZED;
2406 // set up the right briefing for this guy
2407 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
2408 Debriefing = &Debriefings[Net_player->p_info.team];
2410 Debriefing = &Debriefings[0];
2413 // no longer is mission
2414 Game_mode &= ~(GM_IN_MISSION);
2418 New_mode = DEBRIEF_TAB;
2419 Recommend_active = Award_active = 0;
2424 Debrief_cue_voice = 0;
2425 Num_text_lines = Num_debrief_lines = 0;
2426 Debrief_first_voice_flag = 1;
2428 Debrief_multi_voice_loaded = 0;
2431 Medal_text_bitmap = bm_load(NOX("DebriefText01"));
2432 Rank_text_bitmap = bm_load(NOX("DebriefText02"));
2433 Badge_text_bitmap = bm_load(NOX("DebriefText03"));
2436 if ( (Game_mode & GM_CAMPAIGN_MODE) && ( !MULTIPLAYER_CLIENT ) ) {
2437 // MUST store goals and events first - may be used to evaluate next mission
2438 // store goals and events
2439 mission_campaign_store_goals_and_events();
2441 // evaluate next mission
2442 mission_campaign_eval_next_mission();
2445 // call traitor init before calling scoring_level_close. traitor init will essentially nullify
2447 if ( !(Game_mode & GM_MULTIPLAYER) ) { // only do for single player
2448 debrief_traitor_init(); // initialize data needed if player becomes traitor.
2451 // call scoring level close for my stats. Needed for award_init. The stats will
2452 // be backed out if used chooses to replace them.
2453 scoring_level_close();
2455 debrief_ui_init(); // init UI items
2456 debrief_award_init();
2458 debrief_voice_init();
2459 debrief_multi_list_init();
2460 // rank_bitmaps_clear();
2461 // rank_bitmaps_load();
2463 SDL_strlcpy(Debrief_current_callsign, Player->callsign, SDL_arraysize(Debrief_current_callsign));
2464 Debrief_player = Player;
2465 // Debrief_current_net_player_index = debrief_multi_list[0].net_player_index;
2467 // set up the Debrief_stages[] and Recommendations[] arrays. Only do the following stuff
2468 // for non-clients (i.e. single and game server). Multiplayer clients will get their debriefing
2469 // info directly from the server.
2470 if ( !MULTIPLAYER_CLIENT ) {
2471 debrief_set_stages_and_multi_stuff();
2473 if ( Num_debrief_stages <= 0 ) {
2474 Num_debrief_stages = 0;
2476 debrief_voice_load_all();
2479 // multiplayer client may have already received their debriefing info. If they have not,
2480 // then set the num debrief stages to 0
2481 if ( !Debrief_multi_stages_loaded ) {
2482 Num_debrief_stages = 0;
2487 if (mission_evaluate_primary_goals() == PRIMARY_GOALS_COMPLETE) {
2488 common_music_init(SCORE_DEBRIEF_SUCCESS);
2490 common_music_init(SCORE_DEBRIEF_FAIL);
2494 // start up the appropriate music
2495 if (Campaign.next_mission == Campaign.current_mission) {
2496 // you failed the mission because you suck, so you get the suck music
2497 common_music_init(SCORE_DEBRIEF_FAIL);
2498 } else if (mission_goals_met()) {
2499 // you completed all primaries and secondaries, thus you are a stud boy and you get stud boy music
2500 common_music_init(SCORE_DEBRIEF_SUCCESS);
2502 // you somehow passed the mission, so you get a little something for your efforts.
2503 common_music_init(SCORE_DEBRIEF_AVERAGE);
2506 if (Campaign.next_mission == Campaign.current_mission) {
2507 // better luck next time, increase his retries
2508 Player->failures_this_session++;
2510 // clear his retries info regardless of whether or not he accepts
2511 Player->failures_this_session = 0;
2514 if (Game_mode & GM_MULTIPLAYER) {
2515 multi_debrief_init();
2517 // if i'm not the host of the game, disable the multi kick button
2518 if (!(Net_player->flags & NETINFO_FLAG_GAME_HOST)) {
2519 Buttons[gr_screen.res][MULTI_KICK].button.disable();
2522 Buttons[gr_screen.res][PLAYER_SCROLL_UP].button.disable();
2523 Buttons[gr_screen.res][PLAYER_SCROLL_DOWN].button.disable();
2524 Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.disable();
2525 Buttons[gr_screen.res][MULTI_KICK].button.disable();
2526 Buttons[gr_screen.res][PLAYER_SCROLL_UP].button.hide();
2527 Buttons[gr_screen.res][PLAYER_SCROLL_DOWN].button.hide();
2528 Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.hide();
2529 Buttons[gr_screen.res][MULTI_KICK].button.hide();
2532 if (!Award_active) {
2533 Buttons[gr_screen.res][MEDALS_BUTTON].button.disable();
2534 Buttons[gr_screen.res][MEDALS_BUTTON].button.hide();
2537 Debrief_skip_popup_already_shown = 0;
2542 // --------------------------------------------------------------------------------------
2544 void debrief_close()
2548 SDL_assert(Debrief_inited);
2550 // if the mission wasn't accepted, clear out my stats
2551 // we need to evaluate a little differently for multiplayer since the conditions for "accepting"
2552 // are a little bit different
2553 if (Game_mode & GM_MULTIPLAYER) {
2554 // if stats weren't accepted, backout my own stats
2555 if (multi_debrief_stats_accept_code() != 1) {
2556 if(MULTIPLAYER_MASTER){
2557 for(idx=0; idx<MAX_PLAYERS; idx++){
2558 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) && (Net_players[idx].player != NULL)){
2559 scoring_backout_accept(&Net_players[idx].player->stats);
2563 scoring_backout_accept( &Player->stats );
2568 if( !Debrief_accepted || !(Game_mode & GM_CAMPAIGN_MODE) ){
2569 scoring_backout_accept( &Player->stats );
2573 // if dude passed the misson and accepted, reset his show skip popup flag
2574 if (Debrief_accepted) {
2575 Player->show_skip_popup = 1;
2578 if (Num_debrief_lines) {
2579 for (i=0; i<Num_debrief_lines; i++){
2586 // clear out debrief info parsed from mission file
2587 mission_debrief_common_reset();
2589 // unload the overlay bitmap
2591 help_overlay_unload(DEBRIEFING_OVERLAY);
2594 // clear out award text
2595 Debrief_award_text_num_lines = 0;
2597 debrief_voice_unload_all();
2598 common_music_close();
2601 // rank_bitmaps_release();
2604 if (Background_bitmap >= 0){
2605 bm_unload(Background_bitmap);
2608 if (Award_bg_bitmap >= 0){
2609 bm_unload(Award_bg_bitmap);
2612 if (Rank_bitmap >= 0){
2613 bm_unload(Rank_bitmap);
2616 if (Medal_bitmap >= 0){
2617 bm_unload(Medal_bitmap);
2620 if (Badge_bitmap >= 0){
2621 bm_unload(Badge_bitmap);
2624 if (Wings_bitmap >= 0) {
2625 bm_unload(Wings_bitmap);
2628 if (Crest_bitmap >= 0) {
2629 bm_unload(Crest_bitmap);
2633 if (Medal_text_bitmap >= 0) {
2634 bm_unload(Medal_text_bitmap);
2637 if (Badge_text_bitmap >= 0) {
2638 bm_unload(Badge_text_bitmap);
2641 if (Rank_text_bitmap >= 0) {
2642 bm_unload(Rank_text_bitmap);
2646 Debrief_ui_window.destroy();
2647 common_free_interface_palette(); // restore game palette
2650 if (Game_mode & GM_MULTIPLAYER){
2651 multi_debrief_close();
2661 // handle keypresses in debriefing
2662 void debrief_do_keys(int new_k)
2669 case KEY_SHIFTED | SDLK_TAB:
2677 // multiplayer accept popup is a little bit different
2678 if (Game_mode & GM_MULTIPLAYER) {
2679 multi_debrief_esc_hit();
2681 // display the normal debrief popup
2683 if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2684 pf_flags = PF_BODY_BIG; // | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON;
2685 choice = popup(pf_flags, 3, POPUP_CANCEL, XSTR( "&Yes", 454), XSTR( "&No, retry later", 455), XSTR( "Accept this mission outcome?", 456));
2686 if (choice == 1) { // accept and continue on
2688 gameseq_post_event(GS_EVENT_MAIN_MENU);
2694 } else if (Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2695 // need to popup saying that mission was a failure and must be replayed
2696 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));
2701 // Return to Main Hall
2702 gameseq_post_event(GS_EVENT_END_GAME);
2713 void debrief_draw_award_text()
2715 int start_y, curr_y, i, x, sw;
2716 int fh = gr_get_font_height();
2717 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 // vertically centered within field
2720 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);
2724 for (i=0; i<Debrief_award_text_num_lines; i++) {
2725 gr_get_string_size(&sw, NULL, Debrief_award_text[i]);
2726 x = (Medal_bitmap < 0) ? (Debrief_award_text_coords[gr_screen.res][0] + (field_width - sw) / 2) : Debrief_award_text_coords[gr_screen.res][0];
2727 if (i==AWARD_TEXT_MAX_LINES-1) x += 7; // hack because of the shape of the box
2728 gr_set_color_fast(&Color_white);
2729 gr_string(x, curr_y, Debrief_award_text[i]);
2731 // adjust y pos, including a little extra between the "pairs"
2733 if ((i == 1) || (i == 3)) {
2734 curr_y += ((gr_screen.res == GR_640) ? 2 : 6);
2739 // clears out text array so we dont have old award text showing up on new awards.
2740 void debrief_award_text_clear() {
2743 Debrief_award_text_num_lines = 0;
2744 for (i=0; i<AWARD_TEXT_MAX_LINES; i++) {
2745 //Debrief_award_text[i][0] = 0;
2746 memset(Debrief_award_text[i], 0, sizeof(char)*AWARD_TEXT_MAX_LINE_LENGTH);
2750 // this is the nastiest code I have ever written. if you are modifying this, i feel bad for you.
2751 void debrief_add_award_text(char *str)
2753 SDL_assert(Debrief_award_text_num_lines <= AWARD_TEXT_MAX_LINES);
2754 if (Debrief_award_text_num_lines > AWARD_TEXT_MAX_LINES) {
2759 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];
2762 SDL_strlcpy(Debrief_award_text[Debrief_award_text_num_lines], str, AWARD_TEXT_MAX_LINE_LENGTH);
2764 // maybe translate for displaying
2766 medals_translate_name(Debrief_award_text[Debrief_award_text_num_lines], AWARD_TEXT_MAX_LINE_LENGTH);
2767 } else if (Lcl_pl) {
2768 medals_translate_name_pl(Debrief_award_text[Debrief_award_text_num_lines], AWARD_TEXT_MAX_LINE_LENGTH);
2771 Debrief_award_text_num_lines++;
2773 // if its too long, split once ONLY
2774 // assumes text isnt > 2 lines, but this is a safe assumption due to the char limits of the ranks/badges/etc
2775 if (Debrief_award_text_num_lines < AWARD_TEXT_MAX_LINES) {
2776 line2 = split_str_once(Debrief_award_text[Debrief_award_text_num_lines-1], field_width);
2777 if (line2 != NULL) {
2778 SDL_snprintf(Debrief_award_text[Debrief_award_text_num_lines], AWARD_TEXT_MAX_LINE_LENGTH, " %s", line2); // indent a space
2780 Debrief_award_text_num_lines++; // leave blank line even if it all fits into 1
2783 #endif // !MAKE_FS1: No text for FS1, it's all bitmaps
2785 // called once per frame to drive all the input reading and rendering
2786 void debrief_do_frame(float frametime)
2789 const char *please_wait_str = XSTR("Please Wait", 1242);
2793 SDL_assert(Debrief_inited);
2795 // first thing is to load the files
2796 if ( MULTIPLAYER_CLIENT && !Debrief_multi_stages_loaded ) {
2797 // draw the background, etc
2798 GR_MAYBE_CLEAR_RES(Background_bitmap);
2799 if (Background_bitmap >= 0) {
2800 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2804 Debrief_ui_window.draw();
2806 if ( Debrief_multi_loading_bitmap > -1 ){
2807 gr_set_bitmap(Debrief_multi_loading_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2808 gr_bitmap( Please_wait_coords[gr_screen.res][0], Please_wait_coords[gr_screen.res][1] );
2811 // draw "Please Wait"
2812 gr_set_color_fast(&Color_normal);
2814 gr_get_string_size(&str_w, &str_h, please_wait_str);
2815 gr_string((gr_screen.max_w - str_w) / 2, (gr_screen.max_h - str_h) / 2, please_wait_str);
2820 // make sure we run the debrief do frame
2821 if (Game_mode & GM_MULTIPLAYER) {
2822 multi_debrief_do_frame();
2827 int keypress = game_check_key();
2828 if(keypress == SDLK_ESCAPE){
2830 multi_quit_game(PROMPT_CLIENT);
2836 // if multiplayer client, and not loaded voice, then load it
2837 if ( MULTIPLAYER_CLIENT && !Debrief_multi_voice_loaded ) {
2838 debrief_multi_fixup_stages();
2839 debrief_voice_load_all();
2840 Debrief_multi_voice_loaded = 1;
2843 if ( help_overlay_active(DEBRIEFING_OVERLAY) ) {
2844 Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
2845 Debrief_ui_window.set_ignore_gadgets(1);
2848 k = chatbox_process();
2849 if ( Game_mode & GM_NORMAL ) {
2850 new_k = Debrief_ui_window.process(k);
2852 new_k = Debrief_ui_window.process(k, 0);
2855 if ( (k > 0) || (new_k > 0) || B1_JUST_RELEASED ) {
2856 if ( help_overlay_active(DEBRIEFING_OVERLAY) ) {
2857 help_overlay_set_state(DEBRIEFING_OVERLAY, 0);
2858 Debrief_ui_window.set_ignore_gadgets(0);
2864 if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
2865 Debrief_ui_window.set_ignore_gadgets(0);
2868 // don't show pilot info popup by default
2869 Debrief_should_show_popup = 0;
2871 // see if the mode has changed and handle it if so.
2872 if ( Current_mode != New_mode ) {
2873 debrief_voice_stop();
2874 Current_mode = New_mode;
2877 if (New_mode == DEBRIEF_TAB) {
2879 Debrief_cue_voice = 0;
2881 if (Debrief_first_voice_flag) {
2882 Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY * 3);
2883 Debrief_first_voice_flag = 0;
2886 Num_stages = DEBRIEF_NUM_STATS_PAGES;
2890 if ((Num_stages > 0) && (New_stage != Current_stage)) {
2891 Current_stage = New_stage;
2892 debrief_text_init();
2895 debrief_voice_play();
2898 if (Game_mode & GM_MULTIPLAYER) {
2899 multi_debrief_do_frame();
2902 // Now do all the rendering for the frame
2903 GR_MAYBE_CLEAR_RES(Background_bitmap);
2904 if (Background_bitmap >= 0) {
2905 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2909 // draw the damn awarded stuff, G
2910 if ( Award_active && (Award_bg_bitmap >= 0) ) {
2911 gr_set_bitmap(Award_bg_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2912 gr_bitmap(Debrief_award_wnd_coords[gr_screen.res][0], Debrief_award_wnd_coords[gr_screen.res][1]);
2913 if (Rank_bitmap >= 0) {
2914 gr_set_bitmap(Rank_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2916 gr_bitmap(Debrief_rank_coords[0], Debrief_rank_coords[1]);
2918 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2922 if (Medal_bitmap >= 0) {
2923 gr_set_bitmap(Medal_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2924 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2927 if (Badge_bitmap >= 0) {
2928 gr_set_bitmap(Badge_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2930 gr_bitmap(Debrief_badge_coords[0], Debrief_badge_coords[1]);
2932 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2936 if (Wings_bitmap >= 0) {
2937 gr_set_bitmap(Wings_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2939 gr_bitmap(Debrief_badge_coords[0], Debrief_badge_coords[1]);
2941 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2945 // this isn't used in FS1 but doesn't hurt to leave it
2946 if (Crest_bitmap >= 0) {
2947 gr_set_bitmap(Crest_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2948 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2951 // draw medal/badge/rank labels
2953 debrief_draw_award_text();
2955 if (Rank_text_bitmap >= 0) {
2956 gr_set_bitmap(Rank_text_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2957 gr_bitmap(Debrief_rank_text_coords[gr_screen.res][0], Debrief_rank_text_coords[gr_screen.res][1]);
2960 if (Medal_text_bitmap >= 0) {
2961 gr_set_bitmap(Medal_text_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2962 gr_bitmap(Debrief_medal_text_coords[gr_screen.res][0], Debrief_medal_text_coords[gr_screen.res][1]);
2965 if (Badge_text_bitmap >= 0) {
2966 gr_set_bitmap(Badge_text_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2967 gr_bitmap(Debrief_badge_text_coords[gr_screen.res][0], Debrief_badge_text_coords[gr_screen.res][1]);
2972 Debrief_ui_window.draw();
2973 debrief_redraw_pressed_buttons();
2974 Buttons[gr_screen.res][Current_mode].button.draw_forced(2);
2975 if (Recommend_active && (Current_mode != STATS_TAB)) {
2976 Buttons[gr_screen.res][RECOMMENDATIONS].button.draw_forced(2);
2979 // draw the title of the mission
2980 gr_set_color_fast(&Color_bright_white);
2981 SDL_strlcpy(buf, The_mission.name, SDL_arraysize(buf));
2982 gr_force_fit_string(buf, 255, Debrief_title_coords[gr_screen.res][2]);
2983 gr_string(Debrief_title_coords[gr_screen.res][0], Debrief_title_coords[gr_screen.res][1], buf);
2985 #if !defined(NDEBUG) || defined(INTERPLAYQA)
2986 gr_set_color_fast(&Color_normal);
2987 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);
2990 // draw the screen-specific text
2991 switch (Current_mode) {
2993 if ( Num_debrief_stages <= 0 ) {
2994 gr_set_color_fast(&Color_white);
2995 SDL_assert( Game_current_mission_filename != NULL );
2996 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);
3005 debrief_stats_render();
3009 if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
3012 gr_set_color_fast(&Color_red);
3013 gr_get_string_size(&w, NULL, XSTR( "More", 459));
3014 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));
3017 debrief_render_stagenum();
3018 debrief_multi_list_draw();
3020 // render some extra stuff in multiplayer
3021 if (Game_mode & GM_MULTIPLAYER) {
3022 // render the chatbox last
3026 Debrief_ui_window.draw_tooltip();
3028 // render the status indicator for the voice system
3029 multi_common_voice_display_status();
3032 // AL 3-6-98: Needed to move key reading here, since popups are launched from this code, and we don't
3033 // want to include the mouse pointer which is drawn in the flip
3035 if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
3036 debrief_check_buttons();
3037 debrief_do_keys(new_k);
3040 // blit help overlay if active
3041 help_overlay_maybe_blit(DEBRIEFING_OVERLAY);
3045 // dont let dude skip 3-09. hack.
3046 if(Game_mode & GM_CAMPAIGN_MODE){
3047 if((Campaign.current_mission >= 0) && (Campaign.current_mission < MAX_CAMPAIGN_MISSIONS)){
3048 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !SDL_strcasecmp(Campaign.missions[Campaign.current_mission].name, "sm3-09.fs2")) {
3049 Debrief_skip_popup_already_shown = 1;
3054 // maybe show skip mission popup
3055 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)) {
3056 int popup_choice = popup(0, 3, XSTR("Do Not Skip This Mission", 1473),
3057 XSTR("Advance To The Next Mission", 1474),
3058 XSTR("Don't Show Me This Again", 1475),
3059 XSTR("You have failed this mission five times. If you like, you may advance to the next mission.", 1472) );
3060 switch (popup_choice) {
3062 // stay on this mission, so proceed to normal debrief
3063 // in other words, do nothing.
3066 // skip this mission
3067 mission_campaign_skip_to_next();
3068 gameseq_post_event(GS_EVENT_START_GAME);
3071 // dont show this again
3072 Player->show_skip_popup = 0;
3076 Debrief_skip_popup_already_shown = 1;
3079 // check to see if we should be showing a pilot info popup in multiplayer (if a guy was double clicked)
3080 if ((Game_mode & GM_MULTIPLAYER) && Debrief_should_show_popup) {
3081 SDL_assert((Multi_list_select >= 0) && (Multi_list_select < Multi_list_size));
3082 multi_pinfo_popup(&Net_players[Multi_list[Multi_list_select].net_player_index]);
3084 Debrief_should_show_popup = 0;
3088 void debrief_rebuild_player_list()
3092 debrief_multi_list_info *list;
3094 Multi_list_size = 0; // number of net players to choose from
3096 for ( i=0; i<MAX_PLAYERS; i++ ) {
3097 np = &Net_players[i];
3098 // remember not to include the standalone.
3099 if ( MULTI_CONNECTED((*np)) && !MULTI_STANDALONE((*np))){
3100 list = &Multi_list[Multi_list_size++];
3101 list->net_player_index = i;
3102 SDL_strlcpy(list->callsign, np->player->callsign, SDL_arraysize(list->callsign));
3104 // make sure to leave some room to blit the team indicator
3105 gr_force_fit_string(list->callsign, CALLSIGN_LEN - 1, Debrief_list_coords[gr_screen.res][2] - MULTI_LIST_TEAM_OFFSET);
3110 void debrief_handle_player_drop()
3112 debrief_rebuild_player_list();
3115 void debrief_disable_accept()