]> icculus.org git repositories - taylor/freespace2.git/blob - src/mission/missionload.cpp
GCC 3.4 fixes.
[taylor/freespace2.git] / src / mission / missionload.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Mission/MissionLoad.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C source module for mission loading
16  *
17  * $Log$
18  * Revision 1.2  2002/06/09 04:41:22  relnev
19  * added copyright header
20  *
21  * Revision 1.1.1.1  2002/05/03 03:28:09  root
22  * Initial import.
23  *
24  * 
25  * 5     7/20/99 1:49p Dave
26  * Peter Drake build. Fixed some release build warnings.
27  * 
28  * 4     10/13/98 9:28a Dave
29  * Started neatening up freespace.h. Many variables renamed and
30  * reorganized. Added AlphaColors.[h,cpp]
31  * 
32  * 3     10/07/98 6:27p Dave
33  * Globalized mission and campaign file extensions. Removed Silent Threat
34  * special code. Moved \cache \players and \multidata into the \data
35  * directory.
36  * 
37  * 2     10/07/98 10:53a Dave
38  * Initial checkin.
39  * 
40  * 1     10/07/98 10:49a Dave
41  * 
42  * 102   5/19/98 1:19p Allender
43  * new low level reliable socket reading code.  Make all missions/campaign
44  * load/save to data missions folder (i.e. we are rid of the player
45  * missions folder)
46  * 
47  * 101   5/10/98 10:05p Allender
48  * only show cutscenes which have been seen before.  Made Fred able to
49  * write missions anywhere, defaulting to player misison folder, not data
50  * mission folder.  Fix FreeSpace code to properly read missions from
51  * correct locations
52  * 
53  * 100   4/30/98 4:53p John
54  * Restructured and cleaned up cfile code.  Added capability to read off
55  * of CD-ROM drive and out of multiple pack files.
56  * 
57  * 99    2/23/98 6:55p Lawrance
58  * Rip out obsolete code.
59  * 
60  * 98    2/23/98 8:53a John
61  * String externalization
62  * 
63  * 97    1/19/98 9:37p Allender
64  * Great Compiler Warning Purge of Jan, 1998.  Used pragma's in a couple
65  * of places since I was unsure of what to do with code.
66  * 
67  * 96    1/17/98 8:49p Hoffoss
68  * Fixed mission_load() calls to handle failure correctly.
69  * 
70  * 95    12/28/97 1:34p John
71  * Fixed yet another mission filename bug
72  * 
73  * 94    12/28/97 12:42p John
74  * Put in support for reading archive files; Made missionload use the
75  * cf_get_file_list function.   Moved demos directory out of data tree.
76  * 
77  * 93    12/27/97 2:39p John
78  * Took out the outdated ui_getfilelist functions.  Made the mission load
79  * screen use cf_get_filelist instead.  Fixed a bug in mission load that
80  * crashed the program if there are no missions available.
81  * 
82  * 92    12/23/97 12:00p Allender
83  * change write_pilot_file to *not* take is_single as a default parameter.
84  * causing multiplayer pilots to get written to the single player folder
85  * 
86  * 91    11/11/97 4:57p Dave
87  * Put in support for single vs. multiplayer pilots. Began work on
88  * multiplayer campaign saving. Put in initial player select screen
89  * 
90  * 90    10/31/97 11:27a John
91  * appended path for j:\tmp missions
92  * 
93  * 89    10/31/97 11:19a John
94  * added filter catagory for j:\tmp\*.fsm
95  * 
96  * 88    10/12/97 5:22p Lawrance
97  * have ESC back out of mission load screen
98  * 
99  * 87    9/18/97 10:19p Lawrance
100  * Add a mission campaign filter to the load screen
101  * 
102  * 86    9/16/97 2:41p Allender
103  * beginning of code to change way player starts are handled.  Reordered
104  * some code when missions loading since player ship is now created at
105  * mission load time instead of before misison load
106  * 
107  * 85    8/25/97 5:47p Mike
108  * Increase number of missions supported in mission load list (outside
109  * campaign) to 256 and Assert() if there are more than 256.
110  * 
111  * 84    8/20/97 5:19p Hoffoss
112  * Fixed bug where creating a new pilot causes the mission load mission
113  * list box to be empty.
114  * 
115  * 83    7/28/97 10:53a Lawrance
116  * initialize a timestamp
117  * 
118  * 82    7/17/97 4:25p John
119  * First, broken, stage of changing config stuff
120  * 
121  * 81    7/05/97 1:47p Lawrance
122  * write pilot file when a mission is loaded
123  * 
124  * 80    6/26/97 5:53p Lawrance
125  * save recently played missions, allow player to choose from list
126  * 
127  * 79    6/12/97 12:39p John
128  * made ui use freespace colors
129  * 
130  * 78    6/12/97 11:35a John
131  * more menu backgrounds
132  * 
133  * 77    5/14/97 1:33p Allender
134  * remmoved extern declaration
135  * 
136  * 76    5/12/97 4:59p Allender
137  * move the rest of the mission initialization functions into
138  * game_level_init().  All mission loading now going through this
139  * fucntion.
140  * 
141  * 75    5/12/97 3:21p Allender
142  * re-ordered mission load code into single function in Freespace.
143  * Simulation part now runs as seperate thread
144  * 
145  * 74    5/12/97 12:27p John
146  * Restructured Graphics Library to add support for multiple renderers.
147  * 
148  * 73    4/28/97 5:43p Lawrance
149  * allow hotkey assignment screen to work from ship selection
150  * 
151  * 72    4/25/97 11:31a Allender
152  * Campaign state now saved in campaign save file in player directory.
153  * Made some global variables follow naming convention.  Solidified
154  * continuing campaigns based on new structure
155  * 
156  * 71    4/23/97 4:46p Allender
157  * remove unused code
158  * 
159  * 70    4/23/97 3:21p Allender
160  * more campaign stuff -- mission branching through campaign file now
161  * works!!!!
162  * 
163  * 69    4/22/97 10:44a Allender
164  * more campaign stuff.  Info about multiple campaigns now stored in
165  * player file -- not saving some player information in save games.
166  * 
167  * 68    4/18/97 9:59a Allender
168  * more campaign stuff.  All campaign related varaibles now stored in
169  * campaign structure
170  * 
171  * 67    4/17/97 9:02p Allender
172  * new campaign stuff.  all campaign related material stored in external
173  * file.  Continuing campaign won't work at this time
174  * 
175  * 66    4/15/97 4:37p Lawrance
176  * removed unused variables
177  *
178 */
179
180 #include "missionload.h"
181 #include "missiongoals.h"
182 #include "missionparse.h"    
183 #include "missionshipchoice.h"
184 #include "missionlog.h"
185 #include "missionmessage.h"
186 #include "cfile.h"
187 #include "osapi.h"
188 #include "vecmat.h"
189 #include "player.h"
190 #include "object.h"
191 #include "ship.h"
192 #include "ailocal.h"
193 #include "managepilot.h"
194 #include "hud.h"
195 #include "freespace.h"
196 #include "key.h"
197 #include "2d.h"
198 #include "line.h"
199 #include "timer.h"
200 #include "math.h"
201 #include "linklist.h"
202 #include "mouse.h"
203 #include "weapon.h"
204 #include "gamesequence.h"
205 #include "ui.h"
206 #include "sexp.h"
207 #include "missionhotkey.h"
208 #include "missioncampaign.h"
209 #include "cfilesystem.h"
210 #include "alphacolors.h"
211
212
213 extern mission The_mission;  // need to send this info to the briefing
214 extern int shifted_ascii_table[];
215 extern int ascii_table[];
216
217 // -----------------------------------------------
218 // For recording most recent missions played
219 // -----------------------------------------------
220 char    Recent_missions[MAX_RECENT_MISSIONS][MAX_FILENAME_LEN];
221 int     Num_recent_missions;
222
223
224 // -----------------------------------------------------
225 // ml_update_recent_missions()
226 //
227 //      Update the Recent_missions[][] array
228 //
229 void ml_update_recent_missions(char *filename)
230 {
231         char    tmp[MAX_RECENT_MISSIONS][MAX_FILENAME_LEN], *p;
232         int     i,j;
233         
234
235         for ( i = 0; i < Num_recent_missions; i++ ) {
236                 strcpy( tmp[i], Recent_missions[i] );
237         }
238
239         // get a pointer to just the basename of the filename (including extension)
240         p = strrchr(filename, '\\');
241         if ( p == NULL ) {
242                 p = filename;
243         } else {
244                 p++;
245         }
246
247         Assert(strlen(p) < MAX_FILENAME_LEN);
248         strcpy( Recent_missions[0], p );
249
250         j = 1;
251         for ( i = 0; i < Num_recent_missions; i++ ) {
252                 if ( stricmp(Recent_missions[0], tmp[i]) ) {
253                         strcpy(Recent_missions[j++], tmp[i]);
254                         if ( j >= MAX_RECENT_MISSIONS ) {
255                                 break;
256                         }
257                 }
258         }
259
260         Num_recent_missions = j;
261         Assert(Num_recent_missions <= MAX_RECENT_MISSIONS);
262 }
263
264 // Mission_load takes no parameters.
265 // It expects the following global variables to be set correctly:
266 //   Game_current_mission_filename
267
268 // returns -1 if failed, 0 if successful
269 int mission_load()
270 {
271         char filename[128], *ext;       
272
273         mprintf(("MISSION LOAD: '%s'\n", Game_current_mission_filename));
274
275         strncpy(filename, Game_current_mission_filename, 127);
276         ext = strchr(filename, '.');
277         if (ext) {
278                 mprintf(( "Hmmm... Extension passed to mission_load...\n" ));
279                 *ext = 0;                               // remove any extension!
280         }
281
282         strcat(filename, FS_MISSION_FILE_EXT);
283
284         // does the magical mission parsing
285         // creates all objects, except for the player object
286         // save the player object later since the player may get
287         // to choose the type of ship that he is to fly
288         // return value of 0 indicates success, other is failure.
289
290         if ( parse_main(filename) )
291                 return -1;
292
293         if (Select_default_ship) {
294                 int ret;
295                 ret = create_default_player_ship();
296                 Assert(!ret);
297         }
298
299         ml_update_recent_missions(Game_current_mission_filename);  // update recently played missions list
300         write_pilot_file();
301         return 0;
302 }
303
304 //====================================
305 // Mission Load Menu stuff
306 #define MLM_MAX_MISSIONS 256
307 int mlm_active=0;
308 UI_WINDOW mlm_window;
309 UI_LISTBOX mlm_mission_list;
310 UI_LISTBOX recent_mission_list;
311 UI_LISTBOX campaign_filter;
312
313 UI_BUTTON mlm_ok, mlm_cancel;
314 char * mlm_missions[MLM_MAX_MISSIONS];
315 char * recent_missions[MAX_RECENT_MISSIONS];
316 char * campaign_names[MAX_CAMPAIGNS+2];
317 char * campaign_missions[MAX_CAMPAIGN_MISSIONS];
318 int mlm_nfiles = 0;
319 static int      last_recent_current = -1;
320 static int      last_mlm_current = -1;
321 static int      Campaign_filter_index;
322
323 char * jtmp_missions[MLM_MAX_MISSIONS];
324 int jtmp_nfiles = 0;
325
326
327 void ml_change_listbox()
328 {
329         if ( !Num_recent_missions       || !mlm_nfiles )
330                 return;
331
332         if ( mlm_mission_list.current() != -1 ) {
333                 mlm_mission_list.set_current(-1);
334                 last_mlm_current = -1;
335                 recent_mission_list.set_focus();
336                 recent_mission_list.set_current(0);
337                 return;
338         }
339
340         if ( recent_mission_list.current() != -1 ) {
341                 recent_mission_list.set_current(-1);
342                 last_recent_current = -1;
343                 mlm_mission_list.set_focus();
344                 mlm_mission_list.set_current(0);
345                 return;
346         }
347 }
348
349 static char Campaign_missions[MAX_CAMPAIGN_MISSIONS][NAME_LENGTH];
350 static char Campaign_name_list[MAX_CAMPAIGNS+2][NAME_LENGTH];
351 static int      Num_campaign_missions;
352
353 // get the mission filenames that make up a campaign
354 extern int mission_campaign_get_filenames(char *filename, char dest[][NAME_LENGTH], int *num);
355
356 void mission_load_menu_init()
357 {
358         int i;
359         char wild_card[256];
360         Assert( mlm_active == 0 );
361         mlm_active = 1;
362
363         memset(wild_card, 0, 256);
364         strcpy(wild_card, NOX("*"));
365         strcat(wild_card, FS_MISSION_FILE_EXT);
366         mlm_nfiles = cf_get_file_list( MLM_MAX_MISSIONS, mlm_missions, CF_TYPE_MISSIONS, wild_card, CF_SORT_NAME );
367         jtmp_nfiles = 0;        
368                 
369         Assert(mlm_nfiles <= MLM_MAX_MISSIONS);
370
371         mlm_window.create( 100,100,500,300, 0 );        //WIN_DIALOG
372
373         mlm_ok.create( &mlm_window, NOX("Ok"), 125, 420, 80, 40 );
374         mlm_cancel.create( &mlm_window, NOX("Cancel"), 250, 420, 80, 40 );
375         mlm_cancel.set_hotkey( KEY_ESC );
376
377         mlm_mission_list.create( &mlm_window, 450, 150, 150, 200, mlm_nfiles, mlm_missions );
378
379         for ( i = 0; i < Num_recent_missions; i++ ) {
380                 recent_missions[i] = Recent_missions[i];
381         }
382         recent_mission_list.create( &mlm_window, 250, 150, 150, 200, Num_recent_missions, recent_missions );
383
384         mlm_mission_list.set_focus();   
385         mlm_mission_list.set_current(0);
386
387
388         mission_campaign_build_list(0);
389         for ( i = 0; i < Num_campaigns; i++ ) {
390                 strcpy(Campaign_name_list[i+1], Campaign_names[i]);
391         }
392         strcpy(Campaign_name_list[0], NOX("All campaigns"));
393         strcpy(Campaign_name_list[1], NOX("Player Missions"));
394
395         for ( i = 0; i < Num_campaigns+2; i++ ) {
396                 campaign_names[i] = Campaign_name_list[i];
397         }
398
399         campaign_filter.create( &mlm_window, 50, 150, 150, 200, Num_campaigns+2, campaign_names );
400         Campaign_filter_index = 0;
401         campaign_filter.set_current(Campaign_filter_index);
402 }
403
404 void mission_load_menu_do()
405 {
406         int     selected, key_in, recent_current, mlm_current, use_recent_flag, i;
407         
408
409         Assert( mlm_active == 1 );
410
411         key_in = mlm_window.process();
412
413         if ( key_in ) {
414
415                 switch ( key_in & KEY_MASK ) {
416
417                 case KEY_UP:
418                 case KEY_DOWN:
419                 case KEY_HOME:
420                 case KEY_END:
421                 case KEY_PAGEUP:
422                 case KEY_PAGEDOWN:
423                 case KEY_ENTER:
424                         break;
425
426                 case KEY_RIGHT:
427                 case KEY_LEFT:
428                         ml_change_listbox();
429                         break;
430
431                 case KEY_ESC:
432                         gameseq_post_event(GS_EVENT_MAIN_MENU);
433                         break;
434
435                 default:
436                         break;
437
438                 } // end switch
439
440         }
441
442         if ( campaign_filter.current() != Campaign_filter_index ) {
443                 Campaign_filter_index = campaign_filter.current();
444
445                 if ( Campaign_filter_index > 1 ) {
446                         mission_campaign_get_filenames(Campaign_file_names[Campaign_filter_index-2], Campaign_missions, &Num_campaign_missions);
447
448                         for ( i = 0; i < Num_campaign_missions; i++ ) {
449                                 campaign_missions[i] = Campaign_missions[i];
450                         }
451                         mlm_mission_list.set_new_list(Num_campaign_missions, campaign_missions);
452                 } else if ( Campaign_filter_index == 0 ) {
453                         mlm_mission_list.set_new_list(mlm_nfiles, mlm_missions);
454                 } else if ( Campaign_filter_index == 1 ) {
455                         mlm_mission_list.set_new_list(jtmp_nfiles, jtmp_missions); 
456                 }
457                 mlm_current = 0;
458         }
459
460         mlm_current = mlm_mission_list.current();
461         recent_current = recent_mission_list.current();
462
463         if ( mlm_current != last_mlm_current ) {
464                 recent_mission_list.set_current(-1);
465                 last_recent_current = -1;
466         }
467         last_mlm_current = mlm_current;
468
469         if ( recent_current != last_recent_current ) {
470                 mlm_mission_list.set_current(-1);
471                 last_mlm_current = -1;
472         }
473         last_recent_current = recent_current;
474
475         if (mlm_cancel.pressed())
476                 gameseq_post_event(GS_EVENT_MAIN_MENU);
477
478         // Check if they hit OK, if so, use the current listbox
479         // selection.
480         selected = -1;
481         use_recent_flag = 0;
482         if (mlm_ok.pressed())   {
483                 selected = mlm_mission_list.current();
484                 if ( selected == -1 ) {
485                         selected = recent_mission_list.current();
486                         use_recent_flag = 1;
487                 }
488         } else  {
489                 // If they didn't hit OK, then check for a double-click on
490                 // a list box item.
491                 selected = mlm_mission_list.selected();
492                 if ( selected == -1 ) {
493                         selected = recent_mission_list.selected();
494                         use_recent_flag = 1;
495                 }
496         }
497
498         char mission_name_final[512] = "";
499
500         if ( selected > -1  )   {
501                 Campaign.current_mission = -1;
502                 if ( use_recent_flag ) {
503                         strncpy( mission_name_final, recent_missions[selected], MAX_FILENAME_LEN );
504                 } else {
505                         char mission_name[NAME_LENGTH];
506                         if ( Campaign_filter_index == 0 )       {
507                                 strcpy(mission_name, mlm_missions[selected]);
508                         } else if (Campaign_filter_index == 1 ) {
509                                 strcpy( mission_name, jtmp_missions[selected]);
510                         } else {
511                                 strcpy(mission_name, Campaign_missions[selected]);
512                         }
513                         strncpy( mission_name_final, mission_name, MAX_FILENAME_LEN );
514                 }
515
516                 // go
517 #ifdef PD_BUILD
518                 // if this valid
519                 if((game_find_builtin_mission(mission_name_final) != NULL) || strstr(mission_name_final, "peterdrake")){
520                         strcpy(Game_current_mission_filename, mission_name_final);
521                         mprintf(( "Selected '%s'\n", Game_current_mission_filename ));
522                         gameseq_post_event(GS_EVENT_START_GAME);                        
523                 }
524 #else
525                 strcpy(Game_current_mission_filename, mission_name_final);
526                 mprintf(( "Selected '%s'\n", Game_current_mission_filename ));
527                 gameseq_post_event(GS_EVENT_START_GAME);                        
528 #endif
529         }
530
531         gr_clear();
532         gr_set_color_fast( &Color_bright );
533         gr_printf( 0x8000, 10, NOX("Select Mission") );
534
535         gr_printf( 50, 135, NOX("Campaign Filter"));
536         gr_printf( 250, 135, NOX("Recently Played"));
537         gr_printf( 450, 135, NOX("Mission List"));
538         mlm_window.draw();
539
540         gr_flip();
541 }
542
543 void mission_load_menu_close()
544 {
545         int i;
546
547         Assert( mlm_active == 1 );
548         mlm_active = 0;
549
550         for (i=0; i<mlm_nfiles; i++ )   {
551                 if (mlm_missions[i] )   {
552                         free(mlm_missions[i]);
553                         mlm_missions[i] = NULL;
554                 }
555         }
556
557         for (i=0; i<jtmp_nfiles; i++ )  {
558                 if (jtmp_missions[i] )  {
559                         free(jtmp_missions[i]);
560                         jtmp_missions[i] = NULL;
561                 }
562         }
563
564
565         mlm_window.destroy();
566
567 }
568