2 * $Logfile: /Freespace2/code/Mission/MissionLoad.cpp $
7 * C source module for mission loading
10 * Revision 1.1 2002/05/03 03:28:09 root
14 * 5 7/20/99 1:49p Dave
15 * Peter Drake build. Fixed some release build warnings.
17 * 4 10/13/98 9:28a Dave
18 * Started neatening up freespace.h. Many variables renamed and
19 * reorganized. Added AlphaColors.[h,cpp]
21 * 3 10/07/98 6:27p Dave
22 * Globalized mission and campaign file extensions. Removed Silent Threat
23 * special code. Moved \cache \players and \multidata into the \data
26 * 2 10/07/98 10:53a Dave
29 * 1 10/07/98 10:49a Dave
31 * 102 5/19/98 1:19p Allender
32 * new low level reliable socket reading code. Make all missions/campaign
33 * load/save to data missions folder (i.e. we are rid of the player
36 * 101 5/10/98 10:05p Allender
37 * only show cutscenes which have been seen before. Made Fred able to
38 * write missions anywhere, defaulting to player misison folder, not data
39 * mission folder. Fix FreeSpace code to properly read missions from
42 * 100 4/30/98 4:53p John
43 * Restructured and cleaned up cfile code. Added capability to read off
44 * of CD-ROM drive and out of multiple pack files.
46 * 99 2/23/98 6:55p Lawrance
47 * Rip out obsolete code.
49 * 98 2/23/98 8:53a John
50 * String externalization
52 * 97 1/19/98 9:37p Allender
53 * Great Compiler Warning Purge of Jan, 1998. Used pragma's in a couple
54 * of places since I was unsure of what to do with code.
56 * 96 1/17/98 8:49p Hoffoss
57 * Fixed mission_load() calls to handle failure correctly.
59 * 95 12/28/97 1:34p John
60 * Fixed yet another mission filename bug
62 * 94 12/28/97 12:42p John
63 * Put in support for reading archive files; Made missionload use the
64 * cf_get_file_list function. Moved demos directory out of data tree.
66 * 93 12/27/97 2:39p John
67 * Took out the outdated ui_getfilelist functions. Made the mission load
68 * screen use cf_get_filelist instead. Fixed a bug in mission load that
69 * crashed the program if there are no missions available.
71 * 92 12/23/97 12:00p Allender
72 * change write_pilot_file to *not* take is_single as a default parameter.
73 * causing multiplayer pilots to get written to the single player folder
75 * 91 11/11/97 4:57p Dave
76 * Put in support for single vs. multiplayer pilots. Began work on
77 * multiplayer campaign saving. Put in initial player select screen
79 * 90 10/31/97 11:27a John
80 * appended path for j:\tmp missions
82 * 89 10/31/97 11:19a John
83 * added filter catagory for j:\tmp\*.fsm
85 * 88 10/12/97 5:22p Lawrance
86 * have ESC back out of mission load screen
88 * 87 9/18/97 10:19p Lawrance
89 * Add a mission campaign filter to the load screen
91 * 86 9/16/97 2:41p Allender
92 * beginning of code to change way player starts are handled. Reordered
93 * some code when missions loading since player ship is now created at
94 * mission load time instead of before misison load
96 * 85 8/25/97 5:47p Mike
97 * Increase number of missions supported in mission load list (outside
98 * campaign) to 256 and Assert() if there are more than 256.
100 * 84 8/20/97 5:19p Hoffoss
101 * Fixed bug where creating a new pilot causes the mission load mission
102 * list box to be empty.
104 * 83 7/28/97 10:53a Lawrance
105 * initialize a timestamp
107 * 82 7/17/97 4:25p John
108 * First, broken, stage of changing config stuff
110 * 81 7/05/97 1:47p Lawrance
111 * write pilot file when a mission is loaded
113 * 80 6/26/97 5:53p Lawrance
114 * save recently played missions, allow player to choose from list
116 * 79 6/12/97 12:39p John
117 * made ui use freespace colors
119 * 78 6/12/97 11:35a John
120 * more menu backgrounds
122 * 77 5/14/97 1:33p Allender
123 * remmoved extern declaration
125 * 76 5/12/97 4:59p Allender
126 * move the rest of the mission initialization functions into
127 * game_level_init(). All mission loading now going through this
130 * 75 5/12/97 3:21p Allender
131 * re-ordered mission load code into single function in Freespace.
132 * Simulation part now runs as seperate thread
134 * 74 5/12/97 12:27p John
135 * Restructured Graphics Library to add support for multiple renderers.
137 * 73 4/28/97 5:43p Lawrance
138 * allow hotkey assignment screen to work from ship selection
140 * 72 4/25/97 11:31a Allender
141 * Campaign state now saved in campaign save file in player directory.
142 * Made some global variables follow naming convention. Solidified
143 * continuing campaigns based on new structure
145 * 71 4/23/97 4:46p Allender
148 * 70 4/23/97 3:21p Allender
149 * more campaign stuff -- mission branching through campaign file now
152 * 69 4/22/97 10:44a Allender
153 * more campaign stuff. Info about multiple campaigns now stored in
154 * player file -- not saving some player information in save games.
156 * 68 4/18/97 9:59a Allender
157 * more campaign stuff. All campaign related varaibles now stored in
160 * 67 4/17/97 9:02p Allender
161 * new campaign stuff. all campaign related material stored in external
162 * file. Continuing campaign won't work at this time
164 * 66 4/15/97 4:37p Lawrance
165 * removed unused variables
169 #include "missionload.h"
170 #include "missiongoals.h"
171 #include "missionparse.h"
172 #include "missionshipchoice.h"
173 #include "missionlog.h"
174 #include "missionmessage.h"
182 #include "managepilot.h"
184 #include "freespace.h"
190 #include "linklist.h"
193 #include "gamesequence.h"
196 #include "missionhotkey.h"
197 #include "missioncampaign.h"
198 #include "cfilesystem.h"
199 #include "alphacolors.h"
202 extern mission The_mission; // need to send this info to the briefing
203 extern int shifted_ascii_table[];
204 extern int ascii_table[];
206 // -----------------------------------------------
207 // For recording most recent missions played
208 // -----------------------------------------------
209 char Recent_missions[MAX_RECENT_MISSIONS][MAX_FILENAME_LEN];
210 int Num_recent_missions;
213 // -----------------------------------------------------
214 // ml_update_recent_missions()
216 // Update the Recent_missions[][] array
218 void ml_update_recent_missions(char *filename)
220 char tmp[MAX_RECENT_MISSIONS][MAX_FILENAME_LEN], *p;
224 for ( i = 0; i < Num_recent_missions; i++ ) {
225 strcpy( tmp[i], Recent_missions[i] );
228 // get a pointer to just the basename of the filename (including extension)
229 p = strrchr(filename, '\\');
236 Assert(strlen(p) < MAX_FILENAME_LEN);
237 strcpy( Recent_missions[0], p );
240 for ( i = 0; i < Num_recent_missions; i++ ) {
241 if ( stricmp(Recent_missions[0], tmp[i]) ) {
242 strcpy(Recent_missions[j++], tmp[i]);
243 if ( j >= MAX_RECENT_MISSIONS ) {
249 Num_recent_missions = j;
250 Assert(Num_recent_missions <= MAX_RECENT_MISSIONS);
253 // Mission_load takes no parameters.
254 // It expects the following global variables to be set correctly:
255 // Game_current_mission_filename
257 // returns -1 if failed, 0 if successful
260 char filename[128], *ext;
262 mprintf(("MISSION LOAD: '%s'\n", Game_current_mission_filename));
264 strncpy(filename, Game_current_mission_filename, 127);
265 ext = strchr(filename, '.');
267 mprintf(( "Hmmm... Extension passed to mission_load...\n" ));
268 *ext = 0; // remove any extension!
271 strcat(filename, FS_MISSION_FILE_EXT);
273 // does the magical mission parsing
274 // creates all objects, except for the player object
275 // save the player object later since the player may get
276 // to choose the type of ship that he is to fly
277 // return value of 0 indicates success, other is failure.
279 if ( parse_main(filename) )
282 if (Select_default_ship) {
284 ret = create_default_player_ship();
288 ml_update_recent_missions(Game_current_mission_filename); // update recently played missions list
293 //====================================
294 // Mission Load Menu stuff
295 #define MLM_MAX_MISSIONS 256
297 UI_WINDOW mlm_window;
298 UI_LISTBOX mlm_mission_list;
299 UI_LISTBOX recent_mission_list;
300 UI_LISTBOX campaign_filter;
302 UI_BUTTON mlm_ok, mlm_cancel;
303 char * mlm_missions[MLM_MAX_MISSIONS];
304 char * recent_missions[MAX_RECENT_MISSIONS];
305 char * campaign_names[MAX_CAMPAIGNS+2];
306 char * campaign_missions[MAX_CAMPAIGN_MISSIONS];
308 static int last_recent_current = -1;
309 static int last_mlm_current = -1;
310 static int Campaign_filter_index;
312 char * jtmp_missions[MLM_MAX_MISSIONS];
316 void ml_change_listbox()
318 if ( !Num_recent_missions || !mlm_nfiles )
321 if ( mlm_mission_list.current() != -1 ) {
322 mlm_mission_list.set_current(-1);
323 last_mlm_current = -1;
324 recent_mission_list.set_focus();
325 recent_mission_list.set_current(0);
329 if ( recent_mission_list.current() != -1 ) {
330 recent_mission_list.set_current(-1);
331 last_recent_current = -1;
332 mlm_mission_list.set_focus();
333 mlm_mission_list.set_current(0);
338 static char Campaign_missions[MAX_CAMPAIGN_MISSIONS][NAME_LENGTH];
339 static char Campaign_name_list[MAX_CAMPAIGNS+2][NAME_LENGTH];
340 static int Num_campaign_missions;
342 // get the mission filenames that make up a campaign
343 extern int mission_campaign_get_filenames(char *filename, char dest[][NAME_LENGTH], int *num);
345 void mission_load_menu_init()
349 Assert( mlm_active == 0 );
352 memset(wild_card, 0, 256);
353 strcpy(wild_card, NOX("*"));
354 strcat(wild_card, FS_MISSION_FILE_EXT);
355 mlm_nfiles = cf_get_file_list( MLM_MAX_MISSIONS, mlm_missions, CF_TYPE_MISSIONS, wild_card, CF_SORT_NAME );
358 Assert(mlm_nfiles <= MLM_MAX_MISSIONS);
360 mlm_window.create( 100,100,500,300, 0 ); //WIN_DIALOG
362 mlm_ok.create( &mlm_window, NOX("Ok"), 125, 420, 80, 40 );
363 mlm_cancel.create( &mlm_window, NOX("Cancel"), 250, 420, 80, 40 );
364 mlm_cancel.set_hotkey( KEY_ESC );
366 mlm_mission_list.create( &mlm_window, 450, 150, 150, 200, mlm_nfiles, mlm_missions );
368 for ( i = 0; i < Num_recent_missions; i++ ) {
369 recent_missions[i] = Recent_missions[i];
371 recent_mission_list.create( &mlm_window, 250, 150, 150, 200, Num_recent_missions, recent_missions );
373 mlm_mission_list.set_focus();
374 mlm_mission_list.set_current(0);
377 mission_campaign_build_list(0);
378 for ( i = 0; i < Num_campaigns; i++ ) {
379 strcpy(Campaign_name_list[i+1], Campaign_names[i]);
381 strcpy(Campaign_name_list[0], NOX("All campaigns"));
382 strcpy(Campaign_name_list[1], NOX("Player Missions"));
384 for ( i = 0; i < Num_campaigns+2; i++ ) {
385 campaign_names[i] = Campaign_name_list[i];
388 campaign_filter.create( &mlm_window, 50, 150, 150, 200, Num_campaigns+2, campaign_names );
389 Campaign_filter_index = 0;
390 campaign_filter.set_current(Campaign_filter_index);
393 void mission_load_menu_do()
395 int selected, key_in, recent_current, mlm_current, use_recent_flag, i;
398 Assert( mlm_active == 1 );
400 key_in = mlm_window.process();
404 switch ( key_in & KEY_MASK ) {
421 gameseq_post_event(GS_EVENT_MAIN_MENU);
431 if ( campaign_filter.current() != Campaign_filter_index ) {
432 Campaign_filter_index = campaign_filter.current();
434 if ( Campaign_filter_index > 1 ) {
435 mission_campaign_get_filenames(Campaign_file_names[Campaign_filter_index-2], Campaign_missions, &Num_campaign_missions);
437 for ( i = 0; i < Num_campaign_missions; i++ ) {
438 campaign_missions[i] = Campaign_missions[i];
440 mlm_mission_list.set_new_list(Num_campaign_missions, campaign_missions);
441 } else if ( Campaign_filter_index == 0 ) {
442 mlm_mission_list.set_new_list(mlm_nfiles, mlm_missions);
443 } else if ( Campaign_filter_index == 1 ) {
444 mlm_mission_list.set_new_list(jtmp_nfiles, jtmp_missions);
449 mlm_current = mlm_mission_list.current();
450 recent_current = recent_mission_list.current();
452 if ( mlm_current != last_mlm_current ) {
453 recent_mission_list.set_current(-1);
454 last_recent_current = -1;
456 last_mlm_current = mlm_current;
458 if ( recent_current != last_recent_current ) {
459 mlm_mission_list.set_current(-1);
460 last_mlm_current = -1;
462 last_recent_current = recent_current;
464 if (mlm_cancel.pressed())
465 gameseq_post_event(GS_EVENT_MAIN_MENU);
467 // Check if they hit OK, if so, use the current listbox
471 if (mlm_ok.pressed()) {
472 selected = mlm_mission_list.current();
473 if ( selected == -1 ) {
474 selected = recent_mission_list.current();
478 // If they didn't hit OK, then check for a double-click on
480 selected = mlm_mission_list.selected();
481 if ( selected == -1 ) {
482 selected = recent_mission_list.selected();
487 char mission_name_final[512] = "";
489 if ( selected > -1 ) {
490 Campaign.current_mission = -1;
491 if ( use_recent_flag ) {
492 strncpy( mission_name_final, recent_missions[selected], MAX_FILENAME_LEN );
494 char mission_name[NAME_LENGTH];
495 if ( Campaign_filter_index == 0 ) {
496 strcpy(mission_name, mlm_missions[selected]);
497 } else if (Campaign_filter_index == 1 ) {
498 strcpy( mission_name, jtmp_missions[selected]);
500 strcpy(mission_name, Campaign_missions[selected]);
502 strncpy( mission_name_final, mission_name, MAX_FILENAME_LEN );
508 if((game_find_builtin_mission(mission_name_final) != NULL) || strstr(mission_name_final, "peterdrake")){
509 strcpy(Game_current_mission_filename, mission_name_final);
510 mprintf(( "Selected '%s'\n", Game_current_mission_filename ));
511 gameseq_post_event(GS_EVENT_START_GAME);
514 strcpy(Game_current_mission_filename, mission_name_final);
515 mprintf(( "Selected '%s'\n", Game_current_mission_filename ));
516 gameseq_post_event(GS_EVENT_START_GAME);
521 gr_set_color_fast( &Color_bright );
522 gr_printf( 0x8000, 10, NOX("Select Mission") );
524 gr_printf( 50, 135, NOX("Campaign Filter"));
525 gr_printf( 250, 135, NOX("Recently Played"));
526 gr_printf( 450, 135, NOX("Mission List"));
532 void mission_load_menu_close()
536 Assert( mlm_active == 1 );
539 for (i=0; i<mlm_nfiles; i++ ) {
540 if (mlm_missions[i] ) {
541 free(mlm_missions[i]);
542 mlm_missions[i] = NULL;
546 for (i=0; i<jtmp_nfiles; i++ ) {
547 if (jtmp_missions[i] ) {
548 free(jtmp_missions[i]);
549 jtmp_missions[i] = NULL;
554 mlm_window.destroy();