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.11 2004/09/20 01:31:44 theoddone33
21 * Revision 1.10 2004/07/04 11:39:06 taylor
22 * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
24 * Revision 1.9 2003/08/03 16:10:29 taylor
25 * cleanup; compile warning fixes
27 * Revision 1.8 2003/06/03 04:00:40 taylor
28 * Polish language support (Janusz Dziemidowicz)
30 * Revision 1.7 2003/05/25 02:30:43 taylor
33 * Revision 1.6 2002/07/13 06:46:48 theoddone33
36 * Revision 1.5 2002/06/09 04:41:23 relnev
37 * added copyright header
39 * Revision 1.4 2002/06/02 04:26:34 relnev
42 * Revision 1.3 2002/05/26 22:06:17 relnev
43 * makefile: disable stand_gui for now.
45 * rest: staticize some globals
47 * Revision 1.2 2002/05/07 03:16:46 theoddone33
48 * The Great Newline Fix
50 * Revision 1.1.1.1 2002/05/03 03:28:10 root
54 * 57 10/29/99 10:40p Jefff
55 * hack to make german medal names display without actually changing them
57 * 56 10/13/99 3:26p Jefff
58 * fixed unnumbered XSTRs
60 * 55 10/06/99 10:28a Jefff
63 * 54 9/30/99 5:57p Jefff
64 * show upsell at end of campaign in OEM builds
66 * 53 9/15/99 3:42a Jefff
69 * 52 9/14/99 4:35a Dave
70 * Argh. Added all kinds of code to handle potential crashes in debriefing
73 * 51 9/14/99 3:26a Dave
74 * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
75 * respawn-too-early problem. Made a few crash points safe.
77 * 50 9/14/99 12:51a Jefff
79 * 49 9/13/99 6:01p Jefff
80 * fixed wrong promotion voice mapping for sm1-08
82 * 48 9/13/99 11:15a Jefff
83 * clear out award text bug fixed
85 * 47 9/13/99 12:17p Andsager
86 * Fix traitor debrief not playinf for FS2. Don't append _3 or _1 as in
89 * 46 9/07/99 9:35p Jefff
90 * fixed bug where award text was not getting cleared properly between
93 * 45 9/07/99 6:56p Jefff
94 * a few adjustments to loop detection
96 * 44 9/07/99 1:54p Jefff
97 * skip mission cleanup
99 * 43 9/06/99 9:45p Jefff
100 * skip mission support
102 * 42 9/06/99 6:38p Dave
103 * Improved CD detection code.
105 * 41 9/03/99 1:32a Dave
106 * CD checking by act. Added support to play 2 cutscenes in a row
107 * seamlessly. Fixed super low level cfile bug related to files in the
108 * root directory of a CD. Added cheat code to set campaign mission # in
111 * 40 9/02/99 3:45p Jefff
112 * forgot to remove some debug code. doh.
114 * 39 9/02/99 3:41p Jefff
115 * changed badge voice handling to be similar to promotion voice handling
117 * 38 9/01/99 4:41p Jefff
118 * fixed stoopid text color bug
120 * 37 8/31/99 11:54a Jefff
121 * minor debrief music tweak
123 * 36 8/27/99 9:57a Dave
124 * Enabled standard cheat codes. Allow player to continue in a campaing
125 * after using cheat codes.
127 * 35 8/27/99 12:04a Dave
128 * Campaign loop screen.
130 * 34 8/26/99 8:49p Jefff
131 * Updated medals screen and about everything that ever touches medals in
132 * one way or another. Sheesh.
134 * 33 8/20/99 4:20p Jefff
135 * hack for choosing the correct promotion voice
137 * 32 8/16/99 4:05p Dave
138 * Big honking checkin.
140 * 31 8/16/99 9:49a Jefff
141 * mission title length fix in multi
143 * 30 8/11/99 5:33p Jefff
144 * added 3rd debrief music track
146 * 29 8/10/99 7:28p Jefff
147 * shuffled some text around
149 * 28 8/04/99 5:36p Andsager
150 * Show upsell screens at end of demo campaign before returning to main
153 * 27 8/04/99 2:07p Jefff
154 * mission title no longer overwrites popup
156 * 26 8/02/99 5:37p Jefff
158 * 25 8/02/99 4:52p Jefff
159 * negative feedback sound when recommendations button pressed and
162 * 24 7/21/99 6:21p Jefff
163 * added hotkeys to the "you cannot accept" popup
165 * 23 6/15/99 12:04p Anoop
166 * Added a warning for running out of debrief text lines.
168 * 22 6/09/99 2:17p Dave
169 * Fixed up pleasewait bitmap rendering.
171 * 21 6/01/99 6:07p Dave
172 * New loading/pause/please wait bar.
174 * 20 5/22/99 6:05p Dave
175 * Fixed a few localization # problems.
177 * 19 5/22/99 5:35p Dave
178 * Debrief and chatbox screens. Fixed small hi-res HUD bug.
180 * 18 3/20/99 3:47p Andsager
181 * Fix crash with no mission loop description.
183 * 17 2/23/99 2:29p Dave
184 * First run of oldschool dogfight mode.
186 * 16 2/21/99 6:01p Dave
187 * Fixed standalone WSS packets.
189 * 15 2/11/99 3:08p Dave
190 * PXO refresh button. Very preliminary squad war support.
192 * 14 1/30/99 5:08p Dave
193 * More new hi-res stuff.Support for nice D3D textures.
195 * 13 1/29/99 2:08a Dave
196 * Fixed beam weapon collisions with players. Reduced size of scoring
197 * struct for multiplayer. Disabled PXO.
199 * 12 1/14/99 5:15p Neilk
200 * changed credits, command debrief interfaces to high resolution support
202 * 11 1/13/99 2:11p Andsager
203 * change default debriefing string text
205 * 10 12/17/98 4:50p Andsager
206 * Added debrief_assemble_optional_mission_popup_text() for single and
209 * 9 12/12/98 3:17p Andsager
210 * Clean up mission eval, goal, event and mission scoring.
212 * 8 12/10/98 10:19a Andsager
213 * Fix mission loop assert
215 * 7 12/10/98 9:59a Andsager
216 * Fix some bugs with mission loops
218 * 6 12/09/98 1:56p Andsager
219 * Initial checkin of mission loop
221 * 5 11/05/98 4:18p Dave
222 * First run nebula support. Beefed up localization a bit. Removed all
223 * conditional compiles for foreign versions. Modified mission file
226 * 4 10/23/98 3:51p Dave
227 * Full support for tstrings.tbl and foreign languages. All that remains
228 * is to make it active in Fred.
230 * 3 10/13/98 9:28a Dave
231 * Started neatening up freespace.h. Many variables renamed and
232 * reorganized. Added AlphaColors.[h,cpp]
234 * 2 10/07/98 10:53a Dave
237 * 1 10/07/98 10:49a Dave
239 * 178 9/17/98 3:08p Dave
240 * PXO to non-pxo game warning popup. Player icon stuff in create and join
241 * game screens. Upped server count refresh time in PXO to 35 secs (from
244 * 177 7/07/98 1:46p Dave
245 * Fixed nasty debriefing badge/promotion bug. Added extra physics info
248 * 175 6/09/98 10:31a Hoffoss
249 * Created index numbers for all xstr() references. Any new xstr() stuff
250 * added from here on out should be added to the end if the list. The
251 * current list count can be found in FreeSpace.cpp (search for
254 * 174 6/07/98 3:26p Lawrance
255 * Fix bug with cut-off popup text
257 * 173 6/05/98 9:54a Lawrance
260 * 172 6/01/98 11:43a John
261 * JAS & MK: Classified all strings for localization.
263 * 171 5/27/98 1:24p Allender
264 * make targeting dots work (as well as other targeting features) properly
265 * in multiplayer. Don't query for CD when entering debrief in
268 * 170 5/26/98 11:10a Lawrance
269 * Fix bug where window controls get disabled when F1 pressed twice
271 * 169 5/24/98 12:55a Mike
272 * Prevent Assert() when no debriefing text for a stage.
274 * 168 5/23/98 10:38p Lawrance
275 * Avoid doing a cfile refresh when running debug
277 * 167 5/23/98 6:49p Lawrance
278 * Fix problems with refreshing the file list when a CD is inserted
280 * 166 5/21/98 6:57p Lawrance
281 * Don't prompt for the CD if voice not found
283 * 165 5/20/98 2:24a Dave
284 * Fixed server side voice muting. Tweaked multi debrief/endgame
285 * sequencing a bit. Much friendlier for stats tossing/accepting now.
287 * 164 5/19/98 8:35p Dave
288 * Revamp PXO channel listing system. Send campaign goals/events to
289 * clients for evaluation. Made lock button pressable on all screens.
291 * 163 5/19/98 11:13a Hoffoss
292 * Fixed bug where wrong wings award was being displayed in debriefing.
294 * 162 5/19/98 12:28a Mike
297 * 161 5/18/98 8:08p Hoffoss
298 * Moved placement of 'More' text.
300 * 160 5/18/98 3:50p Dan
301 * AL: Pick correct traitor debriefing voice file
303 * 159 5/17/98 6:32p Dave
304 * Make sure clients/servers aren't kicked out of the debriefing when team
305 * captains leave a game. Fixed chatbox off-by-one error. Fixed image
306 * xfer/pilot info popup stuff.
308 * 158 5/16/98 9:14p Allender
309 * fix scoring ckise fir training missions to actually count medals, but
310 * nothing else. Code used to Assert when wings were granted then taken
311 * away because they were actually never granted in scoring structure
313 * 157 5/15/98 5:15p Dave
314 * Fix a standalone resetting bug.Tweaked PXO interface. Display captaincy
315 * status for team vs. team. Put in asserts to check for invalid team vs.
318 * 156 5/15/98 4:36p Allender
319 * fixed minor bug with wings
321 * 155 5/15/98 4:12p Allender
322 * removed redbook code. Put back in ingame join timer. Major fixups for
323 * stats in multiplayer. Pass correct score, medals, etc when leaving
324 * game. Be sure clients display medals, badges, etc.
326 * 154 5/15/98 2:25p Jasen
327 * temporarily disable granting of promotion and badges for clients
329 * 153 5/15/98 10:57a Allender
330 * fixed client side debriefings
332 * 152 5/15/98 10:36a Dave
333 * Removed 2 bogus bitmap drawing Int3()'s
335 * 151 5/14/98 2:44p Hoffoss
336 * Added wings awarding to debrief screen.
338 * 150 5/13/98 9:11p Lawrance
339 * Make 'replay mission' popup warn users about the loss of mission stats.
344 #include "missiondebrief.h"
345 #include "missionbriefcommon.h"
346 #include "missionscreencommon.h"
347 #include "missiongoals.h"
348 #include "missionpause.h"
349 #include "freespace.h"
350 #include "gamesequence.h"
358 #include "audiostr.h"
361 #include "contexthelp.h"
367 #include "multimsgs.h"
368 #include "multiutil.h"
369 #include "multiteamselect.h"
371 #include "eventmusic.h"
375 #include "multi_pinfo.h"
376 #include "contexthelp.h"
377 #include "multi_kick.h"
378 #include "multi_campaign.h"
379 #include "alphacolors.h"
380 #include "localize.h"
381 #include "multi_endgame.h"
384 #define MAX_TOTAL_DEBRIEF_LINES 200
386 #define TEXT_TYPE_NORMAL 1
387 #define TEXT_TYPE_RECOMMENDATION 2
389 #define DEBRIEF_NUM_STATS_PAGES 4
390 #define DEBRIEF_MISSION_STATS 0
391 #define DEBRIEF_MISSION_KILLS 1
392 #define DEBRIEF_ALLTIME_STATS 2
393 #define DEBRIEF_ALLTIME_KILLS 3
395 // 3rd coord is max width in pixels
396 int Debrief_title_coords[GR_NUM_RESOLUTIONS][3] = {
409 int Debrief_text_wnd_coords[GR_NUM_RESOLUTIONS][4] = {
422 int Debrief_text_x2[GR_NUM_RESOLUTIONS] = {
427 int Debrief_stage_info_coords[GR_NUM_RESOLUTIONS][2] = {
440 int Debrief_more_coords[GR_NUM_RESOLUTIONS][2] = {
453 #define MULTI_LIST_TEAM_OFFSET 16
455 int Debrief_multi_list_team_max_display[GR_NUM_RESOLUTIONS] = {
460 int Debrief_list_coords[GR_NUM_RESOLUTIONS][4] = {
469 int Debrief_award_wnd_coords[GR_NUM_RESOLUTIONS][2] = {
482 int Debrief_award_coords[GR_NUM_RESOLUTIONS][2] = {
496 int Debrief_rank_coords[2] = {
500 int Debrief_badge_coords[2] = {
506 // 0=x, 1=y, 2=width of the field
507 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][3] = {
516 // 0=x, 1=y, 2=height of the field
517 int Debrief_award_text_coords[GR_NUM_RESOLUTIONS][3] = {
526 // the medal text in FS1 is a bitmap
527 int Debrief_medal_text_coords[GR_NUM_RESOLUTIONS][2] = {
536 int Debrief_rank_text_coords[GR_NUM_RESOLUTIONS][2] = {
545 int Debrief_badge_text_coords[GR_NUM_RESOLUTIONS][2] = {
556 // 1 = without medal (text will use medal space)
557 #define DB_WITH_MEDAL 0
558 #define DB_WITHOUT_MEDAL 1
559 int Debrief_award_text_width[GR_NUM_RESOLUTIONS][2] = {
568 char *Debrief_single_name[GR_NUM_RESOLUTIONS] = {
569 "DebriefSingle", // GR_640
570 "2_DebriefSingle" // GR_1024
572 char *Debrief_multi_name[GR_NUM_RESOLUTIONS] = {
573 "DebriefMulti", // GR_640
574 "2_DebriefMulti" // GR_1024
576 char *Debrief_mask_name[GR_NUM_RESOLUTIONS] = {
577 "Debrief-m", // GR_640
578 "2_Debrief-m" // GR_1024
581 #define NUM_BUTTONS 18
584 #define DEBRIEF_TAB 0
586 #define TEXT_SCROLL_UP 2
587 #define TEXT_SCROLL_DOWN 3
588 #define REPLAY_MISSION 4
589 #define RECOMMENDATIONS 5
590 #define FIRST_STAGE 6
594 #define MULTI_PINFO_POPUP 10
595 #define MULTI_KICK 11
596 #define MEDALS_BUTTON 12
597 #define PLAYER_SCROLL_UP 13
598 #define PLAYER_SCROLL_DOWN 14
599 #define HELP_BUTTON 15
600 #define OPTIONS_BUTTON 16
601 #define ACCEPT_BUTTON 17
606 char* Debrief_loading_bitmap_fname[GR_NUM_RESOLUTIONS] = {
607 "PleaseWait", // GR_640
608 "2_PleaseWait" // GR_1024
614 char text[NAME_LENGTH+1]; // name of ship type with a colon
615 int num; // how many ships of this type player has killed
616 } debrief_stats_kill_info;
619 int net_player_index; // index into Net_players[] array
620 int rank_bitmap; // bitmap id for rank
621 char callsign[CALLSIGN_LEN];
622 } debrief_multi_list_info;
624 static ui_button_info Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
627 ui_button_info("DB_00", 0, 2, -1, -1, 0), // debriefing
628 ui_button_info("DB_01", 0, 20, -1, -1, 1), // statistics
629 ui_button_info("DB_02", 0, 195, -1, -1, 2), // scroll stats up
630 ui_button_info("DB_03", 0, 232, -1, -1, 3), // scroll stats down
631 ui_button_info("DB_04", 24, 424, -1, -1, 4), // replay mission
632 ui_button_info("DB_05", 30, 451, -1, -1, 5), // recommendations
633 ui_button_info("DB_06", 211, 445, -1, -1, 6), // first page
634 ui_button_info("DB_07", 234, 445, -1, -1, 7), // prev page
635 ui_button_info("DB_08", 259, 445, -1, -1, 8), // next page
636 ui_button_info("DB_09", 283, 445, -1, -1, 9), // last page
637 ui_button_info("DB_21", 441, 384, -1, -1, 21), // pilot info
638 ui_button_info("DB_25", 511, 384, -1, -1, 25), // kick
639 ui_button_info("DB_15", 604, 224, -1, -1, 15), // medals
640 ui_button_info("DB_16", 615, 329, -1, -1, 16), // scroll pilots up
641 ui_button_info("DB_17", 615, 371, -1, -1, 17), // scroll pilots down
642 ui_button_info("DB_10", 469, 428, -1, -1, 10), // help
643 ui_button_info("DB_11", 447, 452, -1, -1, 11), // options
644 ui_button_info("DB_12", 562, 410, -1, -1, 12), // accept
646 ui_button_info("DB_00", 6, 1, 37, 7, 0), // debriefing
647 ui_button_info("DB_01", 6, 21, 37, 23, 1), // statistics
648 ui_button_info("DB_02", 1, 195, -1, -1, 2), // scroll stats up
649 ui_button_info("DB_03", 1, 236, -1, -1, 3), // scroll stats down
650 ui_button_info("DB_04", 1, 428, 49, 447, 4), // replay mission
651 ui_button_info("DB_05", 17, 459, 49, 464, 5), // recommendations
652 ui_button_info("DB_06", 323, 454, -1, -1, 6), // first page
653 ui_button_info("DB_07", 348, 454, -1, -1, 7), // prev page
654 ui_button_info("DB_08", 372, 454, -1, -1, 8), // next page
655 ui_button_info("DB_09", 396, 454, -1, -1, 9), // last page
656 ui_button_info("DB_10", 441, 384, 433, 413, 10), // pilot info
657 ui_button_info("DB_11", 511, 384, 510, 413, 11), // kick
658 ui_button_info("DB_12", 613, 226, -1, -1, 12), // medals
659 ui_button_info("DB_13", 615, 329, -1, -1, 13), // scroll pilots up
660 ui_button_info("DB_14", 615, 371, -1, -1, 14), // scroll pilots down
661 ui_button_info("DB_15", 538, 431, 500, 440, 15), // help
662 ui_button_info("DB_16", 538, 455, 479, 464, 16), // options
663 ui_button_info("DB_17", 573, 432, 572, 413, 17), // accept
667 ui_button_info("2_DB_00", 10, 1, 59, 12, 0), // debriefing
668 ui_button_info("2_DB_01", 10, 33, 59, 37, 1), // statistics
669 ui_button_info("2_DB_02", 1, 312, -1, -1, 2), // scroll stats up
670 ui_button_info("2_DB_03", 1, 378, -1, -1, 3), // scroll stats down
671 ui_button_info("2_DB_04", 1, 685, 79, 715, 4), // replay mission
672 ui_button_info("2_DB_05", 28, 735, 79, 743, 5), // recommendations
673 ui_button_info("2_DB_06", 517, 726, -1, -1, 6), // first page
674 ui_button_info("2_DB_07", 556, 726, -1, -1, 7), // prev page
675 ui_button_info("2_DB_08", 595, 726, -1, -1, 8), // next page
676 ui_button_info("2_DB_09", 633, 726, -1, -1, 9), // last page
677 ui_button_info("2_DB_10", 706, 615, 700, 661, 10), // pilot info
678 ui_button_info("2_DB_11", 817, 615, 816, 661, 11), // kick
679 ui_button_info("2_DB_12", 981, 362, -1, -1, 12), // medals
680 ui_button_info("2_DB_13", 984, 526, -1, -1, 13), // scroll pilots up
681 ui_button_info("2_DB_14", 984, 594, -1, -1, 14), // scroll pilots down
682 ui_button_info("2_DB_15", 861, 689, 801, 705, 15), // help
683 ui_button_info("2_DB_16", 861, 728, 777, 744, 16), // options
684 ui_button_info("2_DB_17", 917, 692, 917, 692, 17), // accept
690 #define NUM_DEBRIEF_TEXT 0
692 #define NUM_DEBRIEF_TEXT 10
694 #define MP_TEXT_INDEX_1 4
695 #define MP_TEXT_INDEX_2 5
696 #define MP_TEXT_INDEX_3 6
697 UI_XSTR Debrief_strings[GR_NUM_RESOLUTIONS][NUM_DEBRIEF_TEXT] = {
699 // not needed for FS1
701 { "Debriefing", 804, 37, 7, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][DEBRIEF_TAB].button },
702 { "Statistics", 1333, 37, 26, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][STATS_TAB].button },
703 { "Replay Mission", 444, 49, 447, UI_XSTR_COLOR_PINK, -1, &Buttons[0][REPLAY_MISSION].button },
704 { "Recommendations", 1334, 49, 464, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][RECOMMENDATIONS].button },
705 { "Pilot", 1310, 433, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_PINFO_POPUP].button },
706 { "Info", 1311, 433, 423, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_PINFO_POPUP].button },
707 { "Kick", 1266, 510, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MULTI_KICK].button },
708 { "Help", 928, 500, 440, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][HELP_BUTTON].button },
709 { "Options", 1036, 479, 464, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][OPTIONS_BUTTON].button },
710 { "Accept", 1035, 572, 413, UI_XSTR_COLOR_PINK, -1, &Buttons[0][ACCEPT_BUTTON].button },
714 // not needed for FS1
716 { "Debriefing", 804, 59, 12, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][DEBRIEF_TAB].button },
717 { "Statistics", 1333, 59, 47, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][STATS_TAB].button },
718 { "Replay Mission", 444, 79, 715, UI_XSTR_COLOR_PINK, -1, &Buttons[1][REPLAY_MISSION].button },
719 { "Recommendations", 1334, 79, 743, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][RECOMMENDATIONS].button },
720 { "Pilot", 1310, 700, 661, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_PINFO_POPUP].button },
721 { "Info", 1311, 700, 679, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_PINFO_POPUP].button },
722 { "Kick", 1266, 816, 661, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MULTI_KICK].button },
723 { "Help", 928, 801, 705, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][HELP_BUTTON].button },
724 { "Options", 1036, 780, 744, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][OPTIONS_BUTTON].button },
725 { "Accept", 1035, 917, 672, UI_XSTR_COLOR_PINK, -1, &Buttons[1][ACCEPT_BUTTON].button },
731 char Debrief_current_callsign[CALLSIGN_LEN+10];
732 player *Debrief_player;
734 static UI_WINDOW Debrief_ui_window;
735 static UI_BUTTON List_region;
736 static int Background_bitmap; // bitmap for the background of the debriefing
737 static int Award_bg_bitmap;
738 static int Debrief_multi_loading_bitmap;
739 static int Rank_bitmap;
740 static int Medal_bitmap;
741 static int Badge_bitmap;
742 static int Wings_bitmap;
743 static int Crest_bitmap;
745 static int Rank_text_bitmap;
746 static int Medal_text_bitmap;
747 static int Badge_text_bitmap;
750 static int Debrief_accepted;
751 static int Turned_traitor;
752 static int Must_replay_mission;
754 static int Current_mode;
756 static int Recommend_active;
757 static int Award_active;
758 static int Text_offset;
759 static int Num_text_lines = 0;
760 static int Num_debrief_lines = 0;
761 static int Text_type[MAX_TOTAL_DEBRIEF_LINES];
762 static char *Text[MAX_TOTAL_DEBRIEF_LINES];
764 static int Debrief_inited = 0;
765 static int New_stage;
766 static int Current_stage;
767 static int Num_stages;
768 static int Num_debrief_stages;
769 static int Stage_voice;
771 static int Multi_list_size;
772 static int Multi_list_offset;
774 int Debrief_multi_stages_loaded = 0;
775 int Debrief_multi_voice_loaded = 0;
777 // static int Debrief_voice_ask_for_cd;
779 // voice id's for debriefing text
780 static int Debrief_voices[MAX_DEBRIEF_STAGES];
782 #define DEBRIEF_VOICE_DELAY 400 // time to delay voice playback when a new stage starts
783 static int Debrief_cue_voice; // timestamp to cue the playback of the voice
784 static int Debrief_first_voice_flag = 1; // used to delay the first voice playback extra long
786 // pointer used for getting to debriefing information
787 debriefing Traitor_debriefing; // used when player is a traitor
789 // pointers to the active stages for this debriefing
790 static debrief_stage *Debrief_stages[MAX_DEBRIEF_STAGES];
791 static debrief_stage Promotion_stage, Badge_stage;
792 static debrief_stats_kill_info Debrief_stats_kills[MAX_SHIP_TYPES];
793 static debrief_multi_list_info Multi_list[MAX_PLAYERS];
794 int Multi_list_select;
796 // flag indicating if we should display info for the given player (in multiplayer)
797 int Debrief_should_show_popup = 1;
799 // already shown skip mission popup?
800 static int Debrief_skip_popup_already_shown = 0;
802 void debrief_text_init();
803 void debrief_accept(int ok_to_post_start_game_event = 1);
804 void debrief_kick_selected_player();
807 // promotion voice selection stuff
808 #define NUM_VOLITION_CAMPAIGNS 1
810 char campaign_name[32];
812 } Volition_campaigns[NUM_VOLITION_CAMPAIGNS] = {
814 BUILTIN_CAMPAIGN, // the only campaign for now, but this leaves room for a mission pack
815 35 // make sure this is equal to the number of missions you gave in the corresponding Debrief_promotion_voice_mapping
819 // data for which voice goes w/ which mission
820 typedef struct voice_map {
821 char mission_file[32];
825 voice_map Debrief_promotion_voice_mapping[NUM_VOLITION_CAMPAIGNS][MAX_CAMPAIGN_MISSIONS] = {
826 { // FreeSpace2 campaign
858 { "SM3-10.fs2", 9 }, // no debriefing for 3-10
860 { "loop1-1.fs2", 4 },
861 { "loop1-2.fs2", 4 },
862 { "loop1-3.fs2", 5 },
863 { "loop2-1.fs2", 4 },
868 #define DB_AWARD_WINGS 0
869 #define DB_AWARD_MEDAL 1
871 #define DB_AWARD_RANK 2
872 #define DB_AWARD_BADGE 3
873 #define DB_AWARD_BG 4
874 static char* Debrief_award_filename[GR_NUM_RESOLUTIONS][5] = {
891 #define DB_AWARD_SOC 2
892 #define DB_AWARD_RANK 3
893 #define DB_AWARD_BADGE 4
894 #define DB_AWARD_BG 5
895 static char* Debrief_award_filename[GR_NUM_RESOLUTIONS][6] = {
915 #define AWARD_TEXT_MAX_LINES 5
916 #define AWARD_TEXT_MAX_LINE_LENGTH 128
917 char Debrief_award_text[AWARD_TEXT_MAX_LINES][AWARD_TEXT_MAX_LINE_LENGTH];
918 int Debrief_award_text_num_lines = 0;
922 // prototypes, you know you love 'em
923 void debrief_add_award_text(char *str);
924 void debrief_award_text_clear();
929 char *debrief_tooltip_handler(char *str)
931 if (!stricmp(str, NOX("@.Medal"))) {
933 return XSTR( "Medal", 435);
936 } else if (!stricmp(str, NOX("@.Rank"))) {
938 return XSTR( "Rank", 436);
941 } else if (!stricmp(str, NOX("@.Badge"))) {
943 return XSTR( "Badge", 437);
946 } else if (!stricmp(str, NOX("@Medal"))) {
947 if (Medal_bitmap >= 0){
948 return Medals[Player->stats.m_medal_earned].name;
951 } else if (!stricmp(str, NOX("@Rank"))) {
952 if (Rank_bitmap >= 0){
953 return Ranks[Promoted].name;
956 } else if (!stricmp(str, NOX("@Badge"))) {
957 if (Badge_bitmap >= 0){
958 return Medals[Badge_index[Player->stats.m_badge_earned]].name;
965 // initialize the array of handles to the different voice streams
966 void debrief_voice_init()
970 for (i=0; i<MAX_DEBRIEF_STAGES; i++) {
971 Debrief_voices[i] = -1;
975 void debrief_load_voice_file(int voice_num, char *name)
977 int load_attempts = 0;
980 if ( load_attempts++ > 5 ) {
984 Debrief_voices[voice_num] = audiostream_open( name, ASF_VOICE );
985 if ( Debrief_voices[voice_num] >= 0 ) {
989 // Don't bother to ask for the CD in multiplayer
990 if ( Game_mode & GM_MULTIPLAYER ) {
994 // couldn't load voice, ask user to insert CD (if necessary)
996 // if ( Debrief_voice_ask_for_cd ) {
997 // if ( game_do_cd_check() == 0 ) {
998 // Debrief_voice_ask_for_cd = 0;
1005 // open and pre-load the stream buffers for the different voice streams
1006 void debrief_voice_load_all()
1010 // Debrief_voice_ask_for_cd = 1;
1012 for ( i=0; i<Num_debrief_stages; i++ ) {
1013 if ( strlen(Debrief_stages[i]->voice) <= 0 ) {
1016 if ( strnicmp(Debrief_stages[i]->voice, NOX("none"), 4) ) {
1017 debrief_load_voice_file(i, Debrief_stages[i]->voice);
1018 // Debrief_voices[i] = audiostream_open(Debrief_stages[i]->voice, ASF_VOICE);
1023 // close all the briefing voice streams
1024 void debrief_voice_unload_all()
1028 for ( i=0; i<MAX_DEBRIEF_STAGES; i++ ) {
1029 if ( Debrief_voices[i] != -1 ) {
1030 audiostream_close_file(Debrief_voices[i], 0);
1031 Debrief_voices[i] = -1;
1036 // start playback of the voice for a particular briefing stage
1037 void debrief_voice_play()
1039 if (!Briefing_voice_enabled || (Current_mode != DEBRIEF_TAB)){
1043 // no more stages? We are done then.
1044 if (Stage_voice >= Num_debrief_stages){
1048 // if in delayed start, see if delay has elapsed and start voice if so
1049 if (Debrief_cue_voice) {
1050 if (!timestamp_elapsed(Debrief_cue_voice)){
1054 Stage_voice++; // move up to next voice
1055 if ((Stage_voice < Num_debrief_stages) && (Debrief_voices[Stage_voice] >= 0)) {
1056 audiostream_play(Debrief_voices[Stage_voice], Master_voice_volume, 0);
1057 Debrief_cue_voice = 0; // indicate no longer in delayed start checking
1063 // see if voice is still playing. If so, do nothing yet.
1064 if ((Stage_voice >= 0) && audiostream_is_playing(Debrief_voices[Stage_voice])){
1068 // set voice to play in a little while from now.
1069 Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY);
1072 // stop playback of the voice for a particular briefing stage
1073 void debrief_voice_stop()
1075 if ((Stage_voice < 0) || (Stage_voice > Num_debrief_stages) || (Debrief_voices[Stage_voice] < 0))
1078 audiostream_stop(Debrief_voices[Stage_voice]); // stream is automatically rewound
1082 // function to deal with inserting possible promition and badge stages into the debriefing
1084 void debrief_multi_fixup_stages()
1088 // possibly insert the badge stage first, them the promotion stage since they are
1089 // inserted at the front of the debrief stages.
1090 if ( Badge_bitmap >= 0 ) {
1091 // move all stages forward one. Don't
1092 for ( i = Num_debrief_stages; i > 0; i-- ) {
1093 Debrief_stages[i] = Debrief_stages[i-1];
1095 Debrief_stages[0] = &Badge_stage;
1096 Num_debrief_stages++;
1099 if ( Promoted >= 0) {
1100 // move all stages forward one
1101 for ( i = Num_debrief_stages; i > 0; i-- ) {
1102 Debrief_stages[i] = Debrief_stages[i-1];
1104 Debrief_stages[0] = &Promotion_stage;
1105 Num_debrief_stages++;
1110 // function called from multiplayer clients to set up the debriefing information for them
1111 // (sent from the server).
1112 void debrief_set_multi_clients( int stage_count, int active_stages[] )
1116 // set up the right briefing for this guy
1117 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
1118 Debriefing = &Debriefings[Net_player->p_info.team];
1120 Debriefing = &Debriefings[0];
1123 // see if this client was promoted -- if so, then add the first stage.
1124 Num_debrief_stages = 0;
1126 // set the pointers to the debriefings for this client
1127 for (i = 0; i < stage_count; i++) {
1128 Debrief_stages[Num_debrief_stages++] = &Debriefing->stages[active_stages[i]];
1131 Debrief_multi_stages_loaded = 1;
1134 // evaluate all stages for all teams. Server of a multiplayer game will have to send that
1135 // information to all clients after leaving this screen.
1136 void debrief_multi_server_stuff()
1138 debriefing *debriefp;
1140 int stage_active[MAX_TEAMS][MAX_DEBRIEF_STAGES], *stages[MAX_TEAMS];
1141 int i, j, num_stages, stage_count[MAX_TEAMS];
1143 memset( stage_active, 0, sizeof(stage_active) );
1145 for (i=0; i<Num_teams; i++) {
1146 debriefp = &Debriefings[i];
1148 stages[i] = stage_active[i];
1149 for (j=0; j<debriefp->num_stages; j++) {
1150 if ( eval_sexp(debriefp->stages[j].formula) ) {
1151 stage_active[i][num_stages] = j;
1156 stage_count[i] = num_stages;
1159 // if we're in campaign mode, evaluate campaign stuff
1160 if (Netgame.campaign_mode == MP_CAMPAIGN) {
1161 multi_campaign_eval_debrief();
1164 // send the information to all clients.
1165 send_debrief_info( stage_count, stages );
1169 // --------------------------------------------------------------------------------------
1170 // debrief_set_stages_and_multi_stuff()
1172 // Set up the active stages for this debriefing
1174 // returns: number of active debriefing stages
1176 int debrief_set_stages_and_multi_stuff()
1179 debriefing *debriefp;
1181 if ( MULTIPLAYER_CLIENT ) {
1185 Num_debrief_stages = 0;
1187 if ( Game_mode & GM_MULTIPLAYER ) {
1188 debrief_multi_server_stuff();
1191 // check to see if player is a traitor (looking at his team). If so, use the special
1192 // traitor debriefing. Only done in single player
1193 debriefp = Debriefing;
1194 if ( !(Game_mode & GM_MULTIPLAYER) ) {
1195 if (Player_ship->team == TEAM_TRAITOR)
1196 debriefp = &Traitor_debriefing;
1199 Num_debrief_stages = 0;
1200 if (Promoted >= 0) {
1201 Debrief_stages[Num_debrief_stages++] = &Promotion_stage;
1204 if (Badge_bitmap >= 0) {
1205 Debrief_stages[Num_debrief_stages++] = &Badge_stage;
1208 for (i=0; i<debriefp->num_stages; i++) {
1209 if (eval_sexp(debriefp->stages[i].formula) == 1) {
1210 Debrief_stages[Num_debrief_stages++] = &debriefp->stages[i];
1214 return Num_debrief_stages;
1217 // init the buttons that are specific to the debriefing screen
1218 void debrief_buttons_init()
1223 for ( i=0; i<NUM_BUTTONS; i++ ) {
1224 b = &Buttons[gr_screen.res][i];
1225 b->button.create( &Debrief_ui_window, "", b->x, b->y, 60, 30, 0 /*b->flags & REPEAT*/, 1 );
1226 // set up callback for when a mouse first goes over a button
1227 b->button.set_highlight_action( common_play_highlight_sound );
1228 b->button.set_bmaps(b->filename);
1229 b->button.link_hotspot(b->hotspot);
1233 for(i=0; i<NUM_DEBRIEF_TEXT; i++){
1234 // multiplayer specific text
1235 if((i == MP_TEXT_INDEX_1) || (i == MP_TEXT_INDEX_2) || (i == MP_TEXT_INDEX_3)){
1236 // only add if in multiplayer mode
1237 if(Game_mode & GM_MULTIPLAYER){
1238 Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
1243 Debrief_ui_window.add_XSTR(&Debrief_strings[gr_screen.res][i]);
1247 // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1248 Buttons[gr_screen.res][NEXT_STAGE].button.set_hotkey(KEY_RIGHT);
1249 Buttons[gr_screen.res][PREV_STAGE].button.set_hotkey(KEY_LEFT);
1250 Buttons[gr_screen.res][LAST_STAGE].button.set_hotkey(KEY_SHIFTED | KEY_RIGHT);
1251 Buttons[gr_screen.res][FIRST_STAGE].button.set_hotkey(KEY_SHIFTED | KEY_LEFT);
1252 Buttons[gr_screen.res][TEXT_SCROLL_UP].button.set_hotkey(KEY_UP);
1253 Buttons[gr_screen.res][TEXT_SCROLL_DOWN].button.set_hotkey(KEY_DOWN);
1254 Buttons[gr_screen.res][ACCEPT_BUTTON].button.set_hotkey(KEY_CTRLED+KEY_ENTER);
1256 // if in multiplayer, disable the button for all players except the host
1257 // also disable for squad war matches
1258 if(Game_mode & GM_MULTIPLAYER){
1259 if((Netgame.type_flags & NG_TYPE_SW) || !(Net_player->flags & NETINFO_FLAG_GAME_HOST)){
1260 Buttons[gr_screen.res][REPLAY_MISSION].button.disable();
1265 // --------------------------------------------------------------------------------------
1266 // debrief_ui_init()
1268 void debrief_ui_init()
1270 // init ship selection masks and buttons
1271 common_set_interface_palette("DebriefPalette"); // set the interface palette
1272 Debrief_ui_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
1273 Debrief_ui_window.set_mask_bmap(Debrief_mask_name[gr_screen.res]);
1274 Debrief_ui_window.tooltip_handler = debrief_tooltip_handler;
1275 debrief_buttons_init();
1277 // load in help overlay bitmap
1278 help_overlay_load(DEBRIEFING_OVERLAY);
1279 help_overlay_set_state(DEBRIEFING_OVERLAY,0);
1281 if ( Game_mode & GM_MULTIPLAYER ) {
1282 // close down any old instances of the chatbox
1285 // create the new one
1287 Background_bitmap = bm_load(Debrief_multi_name[gr_screen.res]);
1288 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);
1291 Background_bitmap = bm_load(Debrief_single_name[gr_screen.res]);
1294 if ( Background_bitmap < 0 ) {
1295 Warning(LOCATION, "Could not load the background bitmap for debrief screen");
1298 Award_bg_bitmap = bm_load(Debrief_award_filename[gr_screen.res][DB_AWARD_BG]);
1299 Debrief_multi_loading_bitmap = bm_load(Debrief_loading_bitmap_fname[gr_screen.res]);
1302 // sets Promotion_stage.voice
1303 // defaults to number 9 (Petrarch) for non-volition missions
1304 // this is an ugly, nasty way of doing this, but it saves us changing the missions at this point
1305 void debrief_choose_promotion_voice()
1309 if(Campaign.current_mission < 0){
1310 sprintf(Promotion_stage.voice, NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
1314 // search thru all official campaigns for our current campaign
1315 if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename)) {
1316 for (i=0; i<NUM_VOLITION_CAMPAIGNS; i++) {
1317 if ((Campaign.filename != NULL) && !stricmp(Campaign.filename, Volition_campaigns[i].campaign_name)) {
1318 // now search thru the mission filenames,
1319 for (j=0; j<Volition_campaigns[i].num_missions; j++) {
1320 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !stricmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file)) {
1321 // found it! set the persona and bail
1322 sprintf(Promotion_stage.voice, NOX("%d_%s"), Debrief_promotion_voice_mapping[i][j].persona_index, Ranks[Promoted].promotion_voice_base);
1330 // default to petrarch
1331 sprintf(Promotion_stage.voice, NOX("9_%s"), Ranks[Promoted].promotion_voice_base);
1334 // sets Promotion_stage.voice
1335 // defaults to number 9 (Petrarch) for non-volition missions
1336 // this is an ugly, nasty, hateful way of doing this, but it saves us changing the missions at this point
1337 void debrief_choose_badge_voice()
1343 if(Campaign.current_mission < 0){
1345 // default to petrarch
1346 sprintf(Badge_stage.voice, NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1348 // default to FS1 guy
1349 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1353 if ((Campaign.missions[Campaign.current_mission].name) && (Campaign.filename)) {
1355 if ( Player->on_bastion ) {
1356 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base2);
1359 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1363 // search thru all official campaigns for our current campaign
1364 for (i=0; i<NUM_VOLITION_CAMPAIGNS; i++) {
1365 if ((Campaign.filename != NULL) && !stricmp(Campaign.filename, Volition_campaigns[i].campaign_name)) {
1366 // now search thru the mission filenames,
1367 for (j=0; j<Campaign.num_missions; j++) {
1368 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !stricmp(Campaign.missions[Campaign.current_mission].name, Debrief_promotion_voice_mapping[i][j].mission_file)) {
1369 // found it! set the persona and bail
1370 sprintf(Badge_stage.voice, NOX("%d_%s"), Debrief_promotion_voice_mapping[i][j].persona_index, Badge_info[Player->stats.m_badge_earned].voice_base);
1380 // default to petrarch
1381 sprintf(Badge_stage.voice, NOX("9_%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1383 // default to FS1 guy
1384 sprintf(Badge_stage.voice, NOX("%s"), Badge_info[Player->stats.m_badge_earned].voice_base);
1389 void debrief_award_init()
1401 // be sure there are no old award texts floating around
1403 debrief_award_text_clear();
1406 // handle medal earned
1407 if (Player->stats.m_medal_earned != -1) {
1408 if (Player->stats.m_medal_earned == 13) { // special hack for the wings..
1410 if ( Player->stats.medals[13] > 1 ) {
1415 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_WINGS], ver);
1416 Wings_bitmap = bm_load(buf);
1418 } else if (Player->stats.m_medal_earned == 17) { // special hack for the soc crest
1419 Crest_bitmap = bm_load(Debrief_award_filename[gr_screen.res][DB_AWARD_SOC]);
1422 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_MEDAL], Player->stats.m_medal_earned);
1423 Medal_bitmap = bm_load(buf);
1427 debrief_add_award_text(Medals[Player->stats.m_medal_earned].name);
1431 // handle promotions
1432 if ( Player->stats.m_promotion_earned != -1 ) {
1433 Promoted = Player->stats.m_promotion_earned;
1434 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_RANK], Promoted + 1);
1435 Rank_bitmap = bm_load(buf);
1437 Promotion_stage.new_text = Ranks[Promoted].promotion_text;
1438 Promotion_stage.new_recommendation_text = NULL;
1440 // choose appropriate promotion voice for this mission
1441 debrief_choose_promotion_voice();
1444 debrief_add_award_text(Ranks[Promoted].name);
1448 // handle badge earned
1449 // only grant badge if earned and allowed. (no_promotion really means no promotion and no badges)
1450 if ( Player->stats.m_badge_earned != -1 ) {
1451 i = Player->stats.m_badge_earned;
1452 sprintf(buf, NOX("%s%.2d"), Debrief_award_filename[gr_screen.res][DB_AWARD_BADGE], i + 1);
1453 Badge_bitmap = bm_load(buf);
1455 Badge_stage.new_text = Badge_info[i].promotion_text;
1456 Badge_stage.new_recommendation_text = NULL;
1458 // choose appropriate voice
1459 debrief_choose_badge_voice();
1462 debrief_add_award_text(Medals[Badge_index[i]].name);
1466 if ((Rank_bitmap >= 0) || (Medal_bitmap >= 0) || (Badge_bitmap >= 0) || (Wings_bitmap >= 0) || (Crest_bitmap >= 0)) {
1473 // debrief_traitor_init() initializes local data which could be used if the player leaves the
1474 // mission a traitor. The same debriefing always gets played
1475 void debrief_traitor_init()
1477 static int inited = 0;
1480 debriefing *debrief;
1481 debrief_stage *stagep;
1485 if ((rval = setjmp(parse_abort)) != 0) {
1486 Error(LOCATION, "Unable to parse traitor.tbl! Code = %i.\n", rval);
1489 read_file_text("traitor.tbl");
1493 // open localization
1496 // simplied form of the debriefing stuff.
1497 debrief = &Traitor_debriefing;
1498 required_string("#Debriefing_info");
1500 required_string("$Num stages:");
1501 stuff_int(&debrief->num_stages);
1502 Assert(debrief->num_stages == 1);
1505 stagep = &debrief->stages[stage_num++];
1506 required_string("$Formula:");
1507 stagep->formula = get_sexp_main();
1508 required_string("$multi text");
1509 if ( Fred_running ) {
1510 stuff_string( stagep->new_text, F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1512 stagep->new_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_DEBRIEF_LEN);
1514 required_string("$Voice:");
1515 char traitor_voice_file[NAME_LENGTH];
1516 stuff_string(traitor_voice_file, F_FILESPEC, NULL);
1518 // DKA 9/13/99 Only 1 traitor msg for FS2
1520 if ( Player->on_bastion ) {
1521 strcpy(stagep->voice, NOX("3_"));
1523 strcpy(stagep->voice, NOX("1_"));
1527 strcat(stagep->voice, traitor_voice_file);
1529 required_string("$Recommendation text:");
1530 if ( Fred_running ) {
1531 stuff_string( stagep->new_recommendation_text, F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1533 stagep->new_recommendation_text = stuff_and_malloc_string( F_MULTITEXT, NULL, MAX_RECOMMENDATION_LEN);
1537 // close localization
1541 // disable the accept button if in single player and I am a traitor
1542 Debrief_accepted = 0;
1543 Turned_traitor = Must_replay_mission = 0;
1544 if (!(Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_CAMPAIGN_MODE)) {
1545 if (Player_ship->team == TEAM_TRAITOR){
1549 if (Campaign.next_mission == Campaign.current_mission){
1550 Must_replay_mission = 1;
1554 if (Turned_traitor || Must_replay_mission) {
1555 Buttons[gr_screen.res][ACCEPT_BUTTON].button.hide();
1557 // kill off any stats
1558 Player->flags &= ~PLAYER_FLAGS_PROMOTED;
1559 scoring_level_init( &Player->stats );
1563 // initialization for listing of players in game
1564 void debrief_multi_list_init()
1566 Multi_list_size = 0; // number of net players to choose from
1567 Multi_list_offset = 0;
1569 Multi_list_select = -1;
1571 if ( !(Game_mode & GM_MULTIPLAYER) )
1574 debrief_rebuild_player_list();
1576 // switch stats display to this newly selected player
1577 set_player_stats(Multi_list[0].net_player_index);
1578 strcpy(Debrief_current_callsign, Multi_list[0].callsign);
1579 Debrief_player = Player;
1582 void debrief_multi_list_scroll_up()
1584 // if we're at the beginning of the list, don't do anything
1585 if(Multi_list_offset == 0){
1586 gamesnd_play_iface(SND_GENERAL_FAIL);
1590 // otherwise scroll up
1591 Multi_list_offset--;
1592 gamesnd_play_iface(SND_USER_SELECT);
1595 void debrief_multi_list_scroll_down()
1597 // if we can scroll down no further
1598 if(Multi_list_size < Debrief_multi_list_team_max_display[gr_screen.res]){
1599 gamesnd_play_iface(SND_GENERAL_FAIL);
1602 if((Multi_list_offset + Debrief_multi_list_team_max_display[gr_screen.res]) >= Multi_list_size){
1603 gamesnd_play_iface(SND_GENERAL_FAIL);
1607 // otherwise scroll down
1608 Multi_list_offset++;
1609 gamesnd_play_iface(SND_USER_SELECT);
1612 // draw the connected net players
1613 void debrief_multi_list_draw()
1615 int y, z, font_height,idx;
1616 char str[CALLSIGN_LEN+5];
1619 font_height = gr_get_font_height();
1621 // if we currently have no item picked, pick a reasonable one
1622 if((Multi_list_size >= 0) && (Multi_list_select == -1)){
1623 // select the entry which corresponds to the local player
1624 Multi_list_select = 0;
1625 for(idx=0;idx<Multi_list_size;idx++){
1626 if(Multi_list[idx].net_player_index == MY_NET_PLAYER_NUM){
1627 Multi_list_select = idx;
1629 // switch stats display to this newly selected player
1630 set_player_stats(Multi_list[idx].net_player_index);
1631 strcpy(Debrief_current_callsign, Multi_list[idx].callsign);
1632 Debrief_player = Net_players[Multi_list[idx].net_player_index].player;
1638 // draw the list itself
1640 z = Multi_list_offset;
1641 while (y + font_height <= Debrief_list_coords[gr_screen.res][3]){
1642 np = &Net_players[Multi_list[z].net_player_index];
1644 if (z >= Multi_list_size){
1647 // set the proper text color for the highlight
1648 if(np->flags & NETINFO_FLAG_GAME_HOST){
1649 if(Multi_list_select == z){
1650 gr_set_color_fast(&Color_text_active_hi);
1652 gr_set_color_fast(&Color_bright);
1655 if(Multi_list_select == z){
1656 gr_set_color_fast(&Color_text_active);
1658 gr_set_color_fast(&Color_text_normal);
1662 // blit the proper indicator - skipping observers
1663 if(!((np->flags & NETINFO_FLAG_OBSERVER) && !(np->flags & NETINFO_FLAG_OBS_PLAYER))){
1664 if(Netgame.type_flags & NG_TYPE_TEAM){
1666 if(np->p_info.team == 0){
1667 // draw his "selected" icon
1668 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM0_SELECT] != -1)){
1669 gr_set_bitmap(Multi_common_icons[MICON_TEAM0_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1670 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1672 // draw his "normal" icon
1673 else if(Multi_common_icons[MICON_TEAM0] != -1){
1674 gr_set_bitmap(Multi_common_icons[MICON_TEAM0], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1675 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1677 } else if(np->p_info.team == 1){
1678 // draw his "selected" icon
1679 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM1_SELECT] != -1)){
1680 gr_set_bitmap(Multi_common_icons[MICON_TEAM1_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1681 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1683 // draw his "normal" icon
1684 else if(Multi_common_icons[MICON_TEAM1] != -1){
1685 gr_set_bitmap(Multi_common_icons[MICON_TEAM1], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1686 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1690 // draw the team 0 selected icon
1691 if(((np->state == NETPLAYER_STATE_DEBRIEF_ACCEPT) || (np->state == NETPLAYER_STATE_DEBRIEF_REPLAY)) && (Multi_common_icons[MICON_TEAM0_SELECT] != -1)){
1692 gr_set_bitmap(Multi_common_icons[MICON_TEAM0_SELECT], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1693 gr_bitmap(Debrief_list_coords[gr_screen.res][0], Debrief_list_coords[gr_screen.res][1] + y - 2);
1698 strcpy(str,Multi_list[z].callsign);
1699 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)){
1700 strcat(str,XSTR( "(O)", 438));
1704 gr_string(Debrief_list_coords[gr_screen.res][0] + MULTI_LIST_TEAM_OFFSET, Debrief_list_coords[gr_screen.res][1] + y, str);
1711 void debrief_kick_selected_player()
1713 if(Multi_list_select >= 0){
1714 Assert(Net_player->flags & NETINFO_FLAG_GAME_HOST);
1715 multi_kick_player(Multi_list[Multi_list_select].net_player_index);
1719 // get optional mission popup text
1720 void debrief_assemble_optional_mission_popup_text(char *buffer, char *mission_loop_desc)
1722 Assert(buffer != NULL);
1725 if (mission_loop_desc == NULL) {
1726 strcpy(buffer, XSTR("<No Mission Loop Description Available>", 1490));
1727 mprintf(("No mission loop description avail"));
1729 strcpy(buffer, mission_loop_desc);
1732 strcat(buffer, XSTR("\n\n\nDo you want to play the optional mission?", 1491));
1735 // what to do when the accept button is hit
1736 void debrief_accept(int ok_to_post_start_game_event)
1740 if ( (/*Cheats_enabled ||*/ Turned_traitor || Must_replay_mission) && (Game_mode & GM_CAMPAIGN_MODE) ) {
1744 if (Game_mode & GM_MULTIPLAYER) {
1748 if (Player_ship->team == TEAM_TRAITOR){
1749 str = XSTR( "Your career is over, Traitor! You can't accept new missions!", 439);
1750 }/* else if (Cheats_enabled) {
1751 str = XSTR( "You are a cheater. You cannot accept this mission!", 440);
1753 str = XSTR( "You have failed this mission and cannot accept. What do you you wish to do instead?", 441);
1756 z = popup(0, 3, XSTR( "Return to &Debriefing", 442), XSTR( "Go to &Flight Deck", 443), XSTR( "&Replay Mission", 444), str);
1758 gameseq_post_event(GS_EVENT_START_BRIEFING); // cycle back to briefing
1759 } else if ( z == 1 ) {
1760 gameseq_post_event(GS_EVENT_END_GAME); // return to main hall, tossing stats
1766 Debrief_accepted = 1;
1767 // save mission stats
1768 if (Game_mode & GM_MULTIPLAYER) {
1769 // note that multi_debrief_accept_hit() will handle all mission_campaign_* calls on its own
1770 // as well as doing stats transfers, etc.
1771 multi_debrief_accept_hit();
1775 int play_commit_sound = 1;
1776 // only write the player's stats if he's accepted
1778 // if we are just playing a single mission, then don't do many of the things
1779 // that need to be done. Nothing much should happen when just playing a single
1780 // mission that isn't in a campaign.
1781 if ( Game_mode & GM_CAMPAIGN_MODE ) {
1783 // check for possible mission loop
1784 // check for (1) mission loop available, (2) dont have to repeat last mission
1785 if(!(Game_mode & GM_MULTIPLAYER)){
1786 int cur = Campaign.current_mission;
1787 bool require_repeat_mission = (Campaign.current_mission == Campaign.next_mission);
1788 if (Campaign.missions[cur].has_mission_loop) {
1789 Assert(Campaign.loop_mission != CAMPAIGN_LOOP_MISSION_UNINITIALIZED);
1792 if ( (Campaign.missions[cur].has_mission_loop && (Campaign.loop_mission != -1)) && !require_repeat_mission ) {
1795 debrief_assemble_optional_mission_popup_text(buffer, Campaign.missions[cur].mission_loop_desc);
1797 int choice = popup(0 , 2, POPUP_NO, POPUP_YES, buffer);
1799 Campaign.loop_enabled = 1;
1800 Campaign.next_mission = Campaign.loop_mission;
1809 if(ok_to_post_start_game_event){
1810 gameseq_post_event(GS_EVENT_LOOP_BRIEF);
1812 play_commit_sound = 0;
1815 // continue as normal
1818 mission_campaign_mission_over();
1820 // check to see if we are out of the loop now
1821 if ( Campaign.next_mission == Campaign.loop_reentry ) {
1822 Campaign.loop_enabled = 0;
1825 // check if campaign is over
1826 if ( Campaign.next_mission == -1 ) {
1827 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
1828 gameseq_post_event(GS_EVENT_END_DEMO);
1830 gameseq_post_event(GS_EVENT_MAIN_MENU);
1833 if ( ok_to_post_start_game_event ) {
1835 if(game_do_cd_mission_check(Game_current_mission_filename)){
1836 gameseq_post_event(GS_EVENT_START_GAME);
1838 gameseq_post_event(GS_EVENT_MAIN_MENU);
1841 play_commit_sound = 0;
1846 gameseq_post_event(GS_EVENT_MAIN_MENU);
1849 if ( play_commit_sound ) {
1850 gamesnd_play_iface(SND_COMMIT_PRESSED);
1857 void debrief_next_tab()
1859 New_mode = Current_mode + 1;
1860 if (New_mode >= NUM_TABS)
1864 void debrief_prev_tab()
1866 New_mode = Current_mode - 1;
1868 New_mode = NUM_TABS - 1;
1871 // --------------------------------------------------------------------------------------
1872 // debrief_next_stage()
1874 void debrief_next_stage()
1876 if (Current_stage < Num_stages - 1) {
1877 New_stage = Current_stage + 1;
1878 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1881 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1884 // --------------------------------------------------------------------------------------
1885 // debrief_prev_stage()
1887 void debrief_prev_stage()
1889 if (Current_stage) {
1890 New_stage = Current_stage - 1;
1891 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1894 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1897 // --------------------------------------------------------------------------------------
1898 // debrief_first_stage()
1899 void debrief_first_stage()
1901 if (Current_stage) {
1903 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1906 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1909 // --------------------------------------------------------------------------------------
1910 // debrief_last_stage()
1911 void debrief_last_stage()
1913 if (Current_stage != Num_stages - 1) {
1914 New_stage = Num_stages - 1;
1915 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
1918 gamesnd_play_iface(SND_BRIEF_STAGE_CHG_FAIL);
1921 // draw what stage number the debriefing is on
1922 void debrief_render_stagenum()
1930 sprintf(buf, XSTR( "%d of %d", 445), Current_stage + 1, Num_stages);
1931 gr_get_string_size(&w, NULL, buf);
1932 gr_set_color_fast(&Color_bright_blue);
1933 gr_string(Debrief_stage_info_coords[gr_screen.res][0] - w, Debrief_stage_info_coords[gr_screen.res][1], buf);
1934 gr_set_color_fast(&Color_white);
1937 // render the mission time at the specified y location
1938 void debrief_render_mission_time(int y_loc)
1942 game_format_time(Missiontime, time_str);
1943 gr_string(0, y_loc, XSTR( "Mission Time", 446));
1944 gr_string(Debrief_text_x2[gr_screen.res], y_loc, time_str);
1947 // render out the debriefing text to the scroll window
1948 void debrief_render()
1950 int y, z, font_height;
1952 if ( Num_stages <= 0 )
1955 font_height = gr_get_font_height();
1957 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]);
1960 while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
1961 if (z >= Num_text_lines)
1964 if (Text_type[z] == TEXT_TYPE_NORMAL)
1965 gr_set_color_fast(&Color_white);
1967 gr_set_color_fast(&Color_bright_red);
1970 gr_string(0, y, Text[z]);
1979 // render out the stats info to the scroll window
1981 void debrief_stats_render()
1983 int i, y, font_height;
1985 gr_set_color_fast(&Color_blue);
1986 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]);
1987 gr_string(0, 0, Debrief_current_callsign);
1988 font_height = gr_get_font_height();
1991 switch ( Current_stage ) {
1992 case DEBRIEF_MISSION_STATS:
1993 i = Current_stage - 1;
1997 gr_set_color_fast(&Color_white);
1999 // display mission completion time
2000 debrief_render_mission_time(y);
2003 show_stats_label(i, 0, y, font_height);
2004 show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2006 case DEBRIEF_ALLTIME_STATS:
2007 i = Current_stage - 1;
2011 gr_set_color_fast(&Color_white);
2012 show_stats_label(i, 0, y, font_height);
2013 show_stats_numbers(i, Debrief_text_x2[gr_screen.res], y, font_height);
2016 case DEBRIEF_ALLTIME_KILLS:
2017 case DEBRIEF_MISSION_KILLS:
2018 gr_set_color_fast(&Color_white);
2020 while (y + font_height <= Debrief_text_wnd_coords[gr_screen.res][3]) {
2021 if (i >= Num_text_lines)
2025 if ( Current_stage == DEBRIEF_MISSION_KILLS )
2026 gr_printf(0, y, XSTR( "Mission Kills by Ship Type", 447));
2028 gr_printf(0, y, XSTR( "All-time Kills by Ship Type", 448));
2031 gr_printf(0, y, "%s", Debrief_stats_kills[i - 2].text);
2032 gr_printf(Debrief_text_x2[gr_screen.res], y, "%d", Debrief_stats_kills[i - 2].num);
2039 if (Num_text_lines == 2) {
2040 if ( Current_stage == DEBRIEF_MISSION_KILLS )
2041 gr_printf(0, y, XSTR( "(No ship kills this mission)", 449));
2043 gr_printf(0, y, XSTR( "(No ship kills)", 450));
2056 // do action for when the replay button is pressed
2057 void debrief_replay_pressed()
2059 if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2061 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));
2068 gameseq_post_event(GS_EVENT_START_BRIEFING); // take us to the briefing
2069 gamesnd_play_iface(SND_COMMIT_PRESSED);
2072 // -------------------------------------------------------------------
2073 // debrief_redraw_pressed_buttons()
2075 // Redraw any debriefing buttons that are pressed down. This function is needed
2076 // since we sometimes need to draw pressed buttons last to ensure the entire
2077 // button gets drawn (and not overlapped by other buttons)
2079 void debrief_redraw_pressed_buttons()
2084 for ( i=0; i<NUM_BUTTONS; i++ ) {
2085 b = &Buttons[gr_screen.res][i].button;
2086 // don't draw the recommendations button if we're in stats mode
2087 if ( b->button_down() ) {
2093 // debrief specific button with hotspot 'i' has been pressed, so perform the associated action
2095 void debrief_button_pressed(int num)
2099 Buttons[gr_screen.res][RECOMMENDATIONS].button.enable();
2100 // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
2101 if (num != Current_mode){
2102 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
2107 // Debrief_ui_window.use_hack_to_get_around_stupid_problem_flag = 1; // allows failure sound to be played
2108 Buttons[gr_screen.res][RECOMMENDATIONS].button.disable();
2109 if (num != Current_mode){
2110 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
2115 case TEXT_SCROLL_UP:
2118 gamesnd_play_iface(SND_SCROLL);
2120 gamesnd_play_iface(SND_GENERAL_FAIL);
2124 case TEXT_SCROLL_DOWN:
2125 if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
2127 gamesnd_play_iface(SND_SCROLL);
2129 gamesnd_play_iface(SND_GENERAL_FAIL);
2133 case REPLAY_MISSION:
2134 if(Game_mode & GM_MULTIPLAYER){
2135 multi_debrief_replay_hit();
2137 debrief_replay_pressed();
2141 case RECOMMENDATIONS:
2142 gamesnd_play_iface(SND_USER_SELECT);
2143 Recommend_active = !Recommend_active;
2144 debrief_text_init();
2148 debrief_first_stage();
2152 debrief_prev_stage();
2156 debrief_next_stage();
2160 debrief_last_stage();
2164 gamesnd_play_iface(SND_HELP_PRESSED);
2165 launch_context_help();
2168 case OPTIONS_BUTTON:
2169 gamesnd_play_iface(SND_SWITCH_SCREENS);
2170 gameseq_post_event( GS_EVENT_OPTIONS_MENU );
2178 gamesnd_play_iface(SND_SWITCH_SCREENS);
2179 gameseq_post_event(GS_EVENT_VIEW_MEDALS);
2182 case PLAYER_SCROLL_UP:
2183 debrief_multi_list_scroll_up();
2186 case PLAYER_SCROLL_DOWN:
2187 debrief_multi_list_scroll_down();
2190 case MULTI_PINFO_POPUP:
2191 Debrief_should_show_popup = 1;
2195 debrief_kick_selected_player();
2200 void debrief_setup_ship_kill_stats(int stage_num)
2204 debrief_stats_kill_info *kill_info;
2206 Assert(Current_stage < DEBRIEF_NUM_STATS_PAGES);
2207 if ( Current_stage == DEBRIEF_MISSION_STATS || Current_stage == DEBRIEF_ALLTIME_STATS )
2210 Assert(Debrief_player != NULL);
2212 // kill_ar points to an array of MAX_SHIP_TYPE ints
2213 if ( Current_stage == DEBRIEF_MISSION_KILLS ) {
2214 kill_arr = Debrief_player->stats.m_okKills;
2216 kill_arr = Debrief_player->stats.kills;
2220 for ( i=0; i<MAX_SHIP_TYPES; i++ ) {
2222 // code used to add in mission kills, but the new system assumes that the player will accept, so
2223 // all time stats already have mission stats added in.
2224 if ( kill_arr[i] <= 0 ){
2229 kill_info = &Debrief_stats_kills[Num_text_lines++];
2231 kill_info->num = kill_arr[i];
2233 strcpy(kill_info->text, Ship_info[i].name);
2234 strcat(kill_info->text, NOX(":"));
2237 Num_text_lines += 2;
2240 // Iterate through the debriefing buttons, checking if they are pressed
2241 void debrief_check_buttons()
2245 for ( i=0; i<NUM_BUTTONS; i++ ) {
2246 if ( Buttons[gr_screen.res][i].button.pressed() ) {
2247 debrief_button_pressed(i);
2251 if ( !(Game_mode & GM_MULTIPLAYER) )
2254 if (List_region.pressed()) {
2255 List_region.get_mouse_pos(NULL, &y);
2256 z = Multi_list_offset + y / gr_get_font_height();
2257 if ((z >= 0) && (z < Multi_list_size)) {
2258 // switch stats display to this newly selected player
2259 set_player_stats(Multi_list[z].net_player_index);
2260 strcpy(Debrief_current_callsign, Multi_list[z].callsign);
2261 Debrief_player = Net_players[Multi_list[z].net_player_index].player;
2262 Multi_list_select = z;
2263 debrief_setup_ship_kill_stats(Current_stage);
2264 gamesnd_play_iface(SND_USER_SELECT);
2268 // if the player was double clicked on - we should popup a player info popup
2270 if (List_region.double_clicked()) {
2271 Debrief_should_show_popup = 1;
2276 void debrief_text_stage_init(char *src, int type)
2278 int i, n_lines, n_chars[MAX_DEBRIEF_LINES];
2279 char line[MAX_DEBRIEF_LINE_LEN];
2280 char *p_str[MAX_DEBRIEF_LINES];
2282 n_lines = split_str(src, Debrief_text_wnd_coords[gr_screen.res][2], n_chars, p_str, MAX_DEBRIEF_LINES);
2283 Assert(n_lines >= 0);
2285 // if you hit this, you proba
2286 if(n_lines >= MAX_DEBRIEF_LINES){
2287 Warning(LOCATION, "You have come close to the limit of debriefing lines, try adding more stages");
2290 for ( i=0; i<n_lines; i++ ) {
2291 Assert(n_chars[i] < MAX_DEBRIEF_LINE_LEN);
2292 Assert(Num_text_lines < MAX_TOTAL_DEBRIEF_LINES);
2293 strncpy(line, p_str[i], n_chars[i]);
2294 line[n_chars[i]] = 0;
2295 drop_white_space(line);
2296 Text_type[Num_text_lines] = type;
2297 Text[Num_text_lines++] = strdup(line);
2303 void debrief_free_text()
2307 for (i=0; i<Num_debrief_lines; i++)
2311 Num_debrief_lines = 0;
2314 // setup the debriefing text lines for rendering
2315 void debrief_text_init()
2320 // release old text lines first
2321 debrief_free_text();
2322 Num_text_lines = Text_offset = 0;
2324 if (Current_mode == DEBRIEF_TAB) {
2325 for (i=0; i<Num_debrief_stages; i++) {
2327 Text[Num_text_lines++] = NULL; // add a blank line between stages
2329 src = Debrief_stages[i]->new_text;
2331 debrief_text_stage_init(src, TEXT_TYPE_NORMAL);
2333 if (Recommend_active) {
2334 src = Debrief_stages[i]->new_recommendation_text;
2335 if (!src && (i == Num_debrief_stages - 1) && !r_count)
2336 src = XSTR( "We have no recommendations for you.", 1054);
2339 Text[Num_text_lines++] = NULL;
2340 debrief_text_stage_init(src, TEXT_TYPE_RECOMMENDATION);
2346 Num_debrief_lines = Num_text_lines;
2350 // not in debriefing mode, must be in stats mode
2352 debrief_setup_ship_kill_stats(Current_stage);
2356 // --------------------------------------------------------------------------------------
2360 Assert(!Debrief_inited);
2361 // Campaign.loop_enabled = 0;
2362 Campaign.loop_mission = CAMPAIGN_LOOP_MISSION_UNINITIALIZED;
2364 // set up the right briefing for this guy
2365 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
2366 Debriefing = &Debriefings[Net_player->p_info.team];
2368 Debriefing = &Debriefings[0];
2371 // no longer is mission
2372 Game_mode &= ~(GM_IN_MISSION);
2376 New_mode = DEBRIEF_TAB;
2377 Recommend_active = Award_active = 0;
2382 Debrief_cue_voice = 0;
2383 Num_text_lines = Num_debrief_lines = 0;
2384 Debrief_first_voice_flag = 1;
2386 Debrief_multi_voice_loaded = 0;
2389 Medal_text_bitmap = bm_load(NOX("DebriefText01"));
2390 Rank_text_bitmap = bm_load(NOX("DebriefText02"));
2391 Badge_text_bitmap = bm_load(NOX("DebriefText03"));
2394 if ( (Game_mode & GM_CAMPAIGN_MODE) && ( !MULTIPLAYER_CLIENT ) ) {
2395 // MUST store goals and events first - may be used to evaluate next mission
2396 // store goals and events
2397 mission_campaign_store_goals_and_events();
2399 // evaluate next mission
2400 mission_campaign_eval_next_mission();
2403 // call traitor init before calling scoring_level_close. traitor init will essentially nullify
2405 if ( !(Game_mode & GM_MULTIPLAYER) ) { // only do for single player
2406 debrief_traitor_init(); // initialize data needed if player becomes traitor.
2409 // call scoring level close for my stats. Needed for award_init. The stats will
2410 // be backed out if used chooses to replace them.
2411 scoring_level_close();
2413 debrief_ui_init(); // init UI items
2414 debrief_award_init();
2416 debrief_voice_init();
2417 debrief_multi_list_init();
2418 // rank_bitmaps_clear();
2419 // rank_bitmaps_load();
2421 strcpy(Debrief_current_callsign, Player->callsign);
2422 Debrief_player = Player;
2423 // Debrief_current_net_player_index = debrief_multi_list[0].net_player_index;
2425 // set up the Debrief_stages[] and Recommendations[] arrays. Only do the following stuff
2426 // for non-clients (i.e. single and game server). Multiplayer clients will get their debriefing
2427 // info directly from the server.
2428 if ( !MULTIPLAYER_CLIENT ) {
2429 debrief_set_stages_and_multi_stuff();
2431 if ( Num_debrief_stages <= 0 ) {
2432 Num_debrief_stages = 0;
2434 debrief_voice_load_all();
2437 // multiplayer client may have already received their debriefing info. If they have not,
2438 // then set the num debrief stages to 0
2439 if ( !Debrief_multi_stages_loaded ) {
2440 Num_debrief_stages = 0;
2445 if (mission_evaluate_primary_goals() == PRIMARY_GOALS_COMPLETE) {
2446 common_music_init(SCORE_DEBRIEF_SUCCESS);
2448 common_music_init(SCORE_DEBRIEF_FAIL);
2452 // start up the appropriate music
2453 if (Campaign.next_mission == Campaign.current_mission) {
2454 // you failed the mission because you suck, so you get the suck music
2455 common_music_init(SCORE_DEBRIEF_FAIL);
2456 } else if (mission_goals_met()) {
2457 // you completed all primaries and secondaries, thus you are a stud boy and you get stud boy music
2458 common_music_init(SCORE_DEBRIEF_SUCCESS);
2460 // you somehow passed the mission, so you get a little something for your efforts.
2461 common_music_init(SCORE_DEBRIEF_AVERAGE);
2464 if (Campaign.next_mission == Campaign.current_mission) {
2465 // better luck next time, increase his retries
2466 Player->failures_this_session++;
2468 // clear his retries info regardless of whether or not he accepts
2469 Player->failures_this_session = 0;
2472 if (Game_mode & GM_MULTIPLAYER) {
2473 multi_debrief_init();
2475 // if i'm not the host of the game, disable the multi kick button
2476 if (!(Net_player->flags & NETINFO_FLAG_GAME_HOST)) {
2477 Buttons[gr_screen.res][MULTI_KICK].button.disable();
2480 Buttons[gr_screen.res][PLAYER_SCROLL_UP].button.disable();
2481 Buttons[gr_screen.res][PLAYER_SCROLL_DOWN].button.disable();
2482 Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.disable();
2483 Buttons[gr_screen.res][MULTI_KICK].button.disable();
2484 Buttons[gr_screen.res][PLAYER_SCROLL_UP].button.hide();
2485 Buttons[gr_screen.res][PLAYER_SCROLL_DOWN].button.hide();
2486 Buttons[gr_screen.res][MULTI_PINFO_POPUP].button.hide();
2487 Buttons[gr_screen.res][MULTI_KICK].button.hide();
2490 if (!Award_active) {
2491 Buttons[gr_screen.res][MEDALS_BUTTON].button.disable();
2492 Buttons[gr_screen.res][MEDALS_BUTTON].button.hide();
2495 Debrief_skip_popup_already_shown = 0;
2500 // --------------------------------------------------------------------------------------
2502 void debrief_close()
2506 Assert(Debrief_inited);
2508 // if the mission wasn't accepted, clear out my stats
2509 // we need to evaluate a little differently for multiplayer since the conditions for "accepting"
2510 // are a little bit different
2511 if (Game_mode & GM_MULTIPLAYER) {
2512 // if stats weren't accepted, backout my own stats
2513 if (multi_debrief_stats_accept_code() != 1) {
2514 if(MULTIPLAYER_MASTER){
2515 for(idx=0; idx<MAX_PLAYERS; idx++){
2516 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) && (Net_players[idx].player != NULL)){
2517 scoring_backout_accept(&Net_players[idx].player->stats);
2521 scoring_backout_accept( &Player->stats );
2526 if( !Debrief_accepted || !(Game_mode & GM_CAMPAIGN_MODE) ){
2527 scoring_backout_accept( &Player->stats );
2531 // if dude passed the misson and accepted, reset his show skip popup flag
2532 if (Debrief_accepted) {
2533 Player->show_skip_popup = 1;
2536 if (Num_debrief_lines) {
2537 for (i=0; i<Num_debrief_lines; i++){
2544 // clear out debrief info parsed from mission file
2545 mission_debrief_common_reset();
2547 // unload the overlay bitmap
2549 help_overlay_unload(DEBRIEFING_OVERLAY);
2552 // clear out award text
2553 Debrief_award_text_num_lines = 0;
2555 debrief_voice_unload_all();
2556 common_music_close();
2559 // rank_bitmaps_release();
2562 if (Background_bitmap >= 0){
2563 bm_unload(Background_bitmap);
2566 if (Award_bg_bitmap >= 0){
2567 bm_unload(Award_bg_bitmap);
2570 if (Rank_bitmap >= 0){
2571 bm_unload(Rank_bitmap);
2574 if (Medal_bitmap >= 0){
2575 bm_unload(Medal_bitmap);
2578 if (Badge_bitmap >= 0){
2579 bm_unload(Badge_bitmap);
2582 if (Wings_bitmap >= 0) {
2583 bm_unload(Wings_bitmap);
2586 if (Crest_bitmap >= 0) {
2587 bm_unload(Crest_bitmap);
2591 if (Medal_text_bitmap >= 0) {
2592 bm_unload(Medal_text_bitmap);
2595 if (Badge_text_bitmap >= 0) {
2596 bm_unload(Badge_text_bitmap);
2599 if (Rank_text_bitmap >= 0) {
2600 bm_unload(Rank_text_bitmap);
2604 Debrief_ui_window.destroy();
2605 common_free_interface_palette(); // restore game palette
2608 if (Game_mode & GM_MULTIPLAYER){
2609 multi_debrief_close();
2617 // handle keypresses in debriefing
2618 void debrief_do_keys(int new_k)
2625 case KEY_SHIFTED | KEY_TAB:
2633 // multiplayer accept popup is a little bit different
2634 if (Game_mode & GM_MULTIPLAYER) {
2635 multi_debrief_esc_hit();
2637 // display the normal debrief popup
2639 if (!Turned_traitor && !Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2640 pf_flags = PF_BODY_BIG; // | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON;
2641 choice = popup(pf_flags, 3, POPUP_CANCEL, XSTR( "&Yes", 454), XSTR( "&No, retry later", 455), XSTR( "Accept this mission outcome?", 456));
2642 if (choice == 1) { // accept and continue on
2644 gameseq_post_event(GS_EVENT_MAIN_MENU);
2650 } else if (Must_replay_mission && (Game_mode & GM_CAMPAIGN_MODE)) {
2651 // need to popup saying that mission was a failure and must be replayed
2652 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));
2657 // Return to Main Hall
2658 gameseq_post_event(GS_EVENT_END_GAME);
2669 void debrief_draw_award_text()
2671 int start_y, curr_y, i, x, sw;
2672 int fh = gr_get_font_height();
2673 int field_width = (Medal_bitmap > 0) ? Debrief_award_text_width[gr_screen.res][DB_WITH_MEDAL] : Debrief_award_text_width[gr_screen.res][DB_WITHOUT_MEDAL];
2675 // vertically centered within field
2676 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);
2680 for (i=0; i<Debrief_award_text_num_lines; i++) {
2681 gr_get_string_size(&sw, NULL, Debrief_award_text[i]);
2682 x = (Medal_bitmap < 0) ? (Debrief_award_text_coords[gr_screen.res][0] + (field_width - sw) / 2) : Debrief_award_text_coords[gr_screen.res][0];
2683 if (i==AWARD_TEXT_MAX_LINES-1) x += 7; // hack because of the shape of the box
2684 gr_set_color_fast(&Color_white);
2685 gr_string(x, curr_y, Debrief_award_text[i]);
2687 // adjust y pos, including a little extra between the "pairs"
2689 if ((i == 1) || (i == 3)) {
2690 curr_y += ((gr_screen.res == GR_640) ? 2 : 6);
2695 // clears out text array so we dont have old award text showing up on new awards.
2696 void debrief_award_text_clear() {
2699 Debrief_award_text_num_lines = 0;
2700 for (i=0; i<AWARD_TEXT_MAX_LINES; i++) {
2701 //Debrief_award_text[i][0] = 0;
2702 memset(Debrief_award_text[i], 0, sizeof(char)*AWARD_TEXT_MAX_LINE_LENGTH);
2706 // this is the nastiest code I have ever written. if you are modifying this, i feel bad for you.
2707 void debrief_add_award_text(char *str)
2709 Assert(Debrief_award_text_num_lines <= AWARD_TEXT_MAX_LINES);
2710 if (Debrief_award_text_num_lines > AWARD_TEXT_MAX_LINES) {
2715 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];
2718 strcpy(Debrief_award_text[Debrief_award_text_num_lines], str);
2720 // maybe translate for displaying
2722 medals_translate_name(Debrief_award_text[Debrief_award_text_num_lines], AWARD_TEXT_MAX_LINE_LENGTH);
2723 } else if (Lcl_pl) {
2724 medals_translate_name_pl(Debrief_award_text[Debrief_award_text_num_lines], AWARD_TEXT_MAX_LINE_LENGTH);
2727 Debrief_award_text_num_lines++;
2729 // if its too long, split once ONLY
2730 // assumes text isnt > 2 lines, but this is a safe assumption due to the char limits of the ranks/badges/etc
2731 if (Debrief_award_text_num_lines < AWARD_TEXT_MAX_LINES) {
2732 line2 = split_str_once(Debrief_award_text[Debrief_award_text_num_lines-1], field_width);
2733 if (line2 != NULL) {
2734 sprintf(Debrief_award_text[Debrief_award_text_num_lines], " %s", line2); // indent a space
2736 Debrief_award_text_num_lines++; // leave blank line even if it all fits into 1
2739 #endif // !MAKE_FS1: No text for FS1, it's all bitmaps
2741 // called once per frame to drive all the input reading and rendering
2742 void debrief_do_frame(float frametime)
2745 char *please_wait_str = XSTR("Please Wait", 1242);
2749 Assert(Debrief_inited);
2751 // first thing is to load the files
2752 if ( MULTIPLAYER_CLIENT && !Debrief_multi_stages_loaded ) {
2753 // draw the background, etc
2754 GR_MAYBE_CLEAR_RES(Background_bitmap);
2755 if (Background_bitmap >= 0) {
2756 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2760 Debrief_ui_window.draw();
2762 if ( Debrief_multi_loading_bitmap > -1 ){
2763 gr_set_bitmap(Debrief_multi_loading_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2764 gr_bitmap( Please_wait_coords[gr_screen.res][0], Please_wait_coords[gr_screen.res][1] );
2767 // draw "Please Wait"
2768 gr_set_color_fast(&Color_normal);
2770 gr_get_string_size(&str_w, &str_h, please_wait_str);
2771 gr_string((gr_screen.max_w - str_w) / 2, (gr_screen.max_h - str_h) / 2, please_wait_str);
2776 // make sure we run the debrief do frame
2777 if (Game_mode & GM_MULTIPLAYER) {
2778 multi_debrief_do_frame();
2783 int keypress = game_check_key();
2784 if(keypress == KEY_ESC){
2786 multi_quit_game(PROMPT_CLIENT);
2792 // if multiplayer client, and not loaded voice, then load it
2793 if ( MULTIPLAYER_CLIENT && !Debrief_multi_voice_loaded ) {
2794 debrief_multi_fixup_stages();
2795 debrief_voice_load_all();
2796 Debrief_multi_voice_loaded = 1;
2799 if ( help_overlay_active(DEBRIEFING_OVERLAY) ) {
2800 Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
2801 Debrief_ui_window.set_ignore_gadgets(1);
2804 k = chatbox_process();
2805 if ( Game_mode & GM_NORMAL ) {
2806 new_k = Debrief_ui_window.process(k);
2808 new_k = Debrief_ui_window.process(k, 0);
2811 if ( (k > 0) || (new_k > 0) || B1_JUST_RELEASED ) {
2812 if ( help_overlay_active(DEBRIEFING_OVERLAY) ) {
2813 help_overlay_set_state(DEBRIEFING_OVERLAY, 0);
2814 Debrief_ui_window.set_ignore_gadgets(0);
2820 if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
2821 Debrief_ui_window.set_ignore_gadgets(0);
2824 // don't show pilot info popup by default
2825 Debrief_should_show_popup = 0;
2827 // see if the mode has changed and handle it if so.
2828 if ( Current_mode != New_mode ) {
2829 debrief_voice_stop();
2830 Current_mode = New_mode;
2833 if (New_mode == DEBRIEF_TAB) {
2835 Debrief_cue_voice = 0;
2837 if (Debrief_first_voice_flag) {
2838 Debrief_cue_voice = timestamp(DEBRIEF_VOICE_DELAY * 3);
2839 Debrief_first_voice_flag = 0;
2842 Num_stages = DEBRIEF_NUM_STATS_PAGES;
2846 if ((Num_stages > 0) && (New_stage != Current_stage)) {
2847 Current_stage = New_stage;
2848 debrief_text_init();
2851 debrief_voice_play();
2854 if (Game_mode & GM_MULTIPLAYER) {
2855 multi_debrief_do_frame();
2858 // Now do all the rendering for the frame
2859 GR_MAYBE_CLEAR_RES(Background_bitmap);
2860 if (Background_bitmap >= 0) {
2861 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2865 // draw the damn awarded stuff, G
2866 if ( Award_active && (Award_bg_bitmap >= 0) ) {
2867 gr_set_bitmap(Award_bg_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2868 gr_bitmap(Debrief_award_wnd_coords[gr_screen.res][0], Debrief_award_wnd_coords[gr_screen.res][1]);
2869 if (Rank_bitmap >= 0) {
2870 gr_set_bitmap(Rank_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2872 gr_bitmap(Debrief_rank_coords[0], Debrief_rank_coords[1]);
2874 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2878 if (Medal_bitmap >= 0) {
2879 gr_set_bitmap(Medal_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2880 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2883 if (Badge_bitmap >= 0) {
2884 gr_set_bitmap(Badge_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2886 gr_bitmap(Debrief_badge_coords[0], Debrief_badge_coords[1]);
2888 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2892 if (Wings_bitmap >= 0) {
2893 gr_set_bitmap(Wings_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2895 gr_bitmap(Debrief_badge_coords[0], Debrief_badge_coords[1]);
2897 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2901 // this isn't used in FS1 but doesn't hurt to leave it
2902 if (Crest_bitmap >= 0) {
2903 gr_set_bitmap(Crest_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2904 gr_bitmap(Debrief_award_coords[gr_screen.res][0], Debrief_award_coords[gr_screen.res][1]);
2907 // draw medal/badge/rank labels
2909 debrief_draw_award_text();
2911 if (Rank_text_bitmap >= 0) {
2912 gr_set_bitmap(Rank_text_bitmap);
2913 gr_bitmap(Debrief_rank_text_coords[gr_screen.res][0], Debrief_rank_text_coords[gr_screen.res][1]);
2916 if (Medal_text_bitmap >= 0) {
2917 gr_set_bitmap(Medal_text_bitmap);
2918 gr_bitmap(Debrief_medal_text_coords[gr_screen.res][0], Debrief_medal_text_coords[gr_screen.res][1]);
2921 if (Badge_text_bitmap >= 0) {
2922 gr_set_bitmap(Badge_text_bitmap);
2923 gr_bitmap(Debrief_badge_text_coords[gr_screen.res][0], Debrief_badge_text_coords[gr_screen.res][1]);
2928 Debrief_ui_window.draw();
2929 debrief_redraw_pressed_buttons();
2930 Buttons[gr_screen.res][Current_mode].button.draw_forced(2);
2931 if (Recommend_active && (Current_mode != STATS_TAB)) {
2932 Buttons[gr_screen.res][RECOMMENDATIONS].button.draw_forced(2);
2935 // draw the title of the mission
2936 gr_set_color_fast(&Color_bright_white);
2937 strcpy(buf, The_mission.name);
2938 gr_force_fit_string(buf, 255, Debrief_title_coords[gr_screen.res][2]);
2939 gr_string(Debrief_title_coords[gr_screen.res][0], Debrief_title_coords[gr_screen.res][1], buf);
2941 #if !defined(NDEBUG) || defined(INTERPLAYQA)
2942 gr_set_color_fast(&Color_normal);
2943 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);
2946 // draw the screen-specific text
2947 switch (Current_mode) {
2949 if ( Num_debrief_stages <= 0 ) {
2950 gr_set_color_fast(&Color_white);
2951 Assert( Game_current_mission_filename != NULL );
2952 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);
2961 debrief_stats_render();
2965 if (Text_offset + Debrief_text_wnd_coords[gr_screen.res][3] / gr_get_font_height() < Num_text_lines) {
2968 gr_set_color_fast(&Color_red);
2969 gr_get_string_size(&w, NULL, XSTR( "More", 459));
2970 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));
2973 debrief_render_stagenum();
2974 debrief_multi_list_draw();
2976 // render some extra stuff in multiplayer
2977 if (Game_mode & GM_MULTIPLAYER) {
2978 // render the chatbox last
2982 Debrief_ui_window.draw_tooltip();
2984 // render the status indicator for the voice system
2985 multi_common_voice_display_status();
2988 // AL 3-6-98: Needed to move key reading here, since popups are launched from this code, and we don't
2989 // want to include the mouse pointer which is drawn in the flip
2991 if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
2992 debrief_check_buttons();
2993 debrief_do_keys(new_k);
2996 // blit help overlay if active
2997 help_overlay_maybe_blit(DEBRIEFING_OVERLAY);
3001 // dont let dude skip 3-09. hack.
3002 if(Game_mode & GM_CAMPAIGN_MODE){
3003 if((Campaign.current_mission >= 0) && (Campaign.current_mission < MAX_CAMPAIGN_MISSIONS)){
3004 if ((Campaign.missions[Campaign.current_mission].name != NULL) && !stricmp(Campaign.missions[Campaign.current_mission].name, "sm3-09.fs2")) {
3005 Debrief_skip_popup_already_shown = 1;
3010 // maybe show skip mission popup
3011 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)) {
3012 int popup_choice = popup(0, 3, XSTR("Do Not Skip This Mission", 1473),
3013 XSTR("Advance To The Next Mission", 1474),
3014 XSTR("Don't Show Me This Again", 1475),
3015 XSTR("You have failed this mission five times. If you like, you may advance to the next mission.", 1472) );
3016 switch (popup_choice) {
3018 // stay on this mission, so proceed to normal debrief
3019 // in other words, do nothing.
3022 // skip this mission
3023 mission_campaign_skip_to_next();
3024 gameseq_post_event(GS_EVENT_START_GAME);
3027 // dont show this again
3028 Player->show_skip_popup = 0;
3032 Debrief_skip_popup_already_shown = 1;
3035 // check to see if we should be showing a pilot info popup in multiplayer (if a guy was double clicked)
3036 if ((Game_mode & GM_MULTIPLAYER) && Debrief_should_show_popup) {
3037 Assert((Multi_list_select >= 0) && (Multi_list_select < Multi_list_size));
3038 multi_pinfo_popup(&Net_players[Multi_list[Multi_list_select].net_player_index]);
3040 Debrief_should_show_popup = 0;
3044 void debrief_rebuild_player_list()
3048 debrief_multi_list_info *list;
3050 Multi_list_size = 0; // number of net players to choose from
3052 for ( i=0; i<MAX_PLAYERS; i++ ) {
3053 np = &Net_players[i];
3054 // remember not to include the standalone.
3055 if ( MULTI_CONNECTED((*np)) && !MULTI_STANDALONE((*np))){
3056 list = &Multi_list[Multi_list_size++];
3057 list->net_player_index = i;
3058 strcpy(list->callsign, np->player->callsign);
3060 // make sure to leave some room to blit the team indicator
3061 gr_force_fit_string(list->callsign, CALLSIGN_LEN - 1, Debrief_list_coords[gr_screen.res][2] - MULTI_LIST_TEAM_OFFSET);
3066 void debrief_handle_player_drop()
3068 debrief_rebuild_player_list();
3071 void debrief_disable_accept()