home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / mission.c < prev    next >
Text File  |  1998-06-08  |  14KB  |  545 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/main/rcs/mission.c $
  15.  * $Revision: 2.9 $
  16.  * $Author: john $
  17.  * $Date: 1995/05/26 16:16:32 $
  18.  * 
  19.  * Code to handle multiple missions
  20.  * 
  21.  * $Log: mission.c $
  22.  * Revision 2.9  1995/05/26  16:16:32  john
  23.  * Split SATURN into define's for requiring cd, using cd, etc.
  24.  * Also started adding all the Rockwell stuff.
  25.  * 
  26.  * Revision 2.8  1995/03/20  15:49:31  mike
  27.  * Remove eof char from comment which confused make depend, causing
  28.  * no mission.obj: line in makefile.  Pretty stupid tool, huh?
  29.  * 
  30.  * Revision 2.7  1995/03/20  12:12:11  john
  31.  * Added ifdef SATURN.
  32.  * 
  33.  * Revision 2.6  1995/03/15  14:32:49  john
  34.  * Added code to force the Descent CD-rom in the drive.
  35.  * 
  36.  * Revision 2.5  1995/03/15  11:41:15  john
  37.  * Better Saturn CD-ROM support.
  38.  * 
  39.  * Revision 2.4  1995/03/14  18:24:14  john
  40.  * Force Destination Saturn to use CD-ROM drive.
  41.  * 
  42.  * Revision 2.3  1995/03/07  14:19:41  mike
  43.  * More destination saturn stuff.
  44.  * 
  45.  * Revision 2.2  1995/03/06  23:09:03  mike
  46.  * more saturn stuff: make briefings work for saturn mission.
  47.  * 
  48.  * Revision 2.1  1995/03/06  16:47:48  mike
  49.  * destination saturn
  50.  * 
  51.  * Revision 2.0  1995/02/27  11:27:49  john
  52.  * New version 2.0, which has no anonymous unions, builds with
  53.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  54.  * 
  55.  * Revision 1.14  1995/02/15  11:30:37  john
  56.  * Fixed bug with potential mem overwrite on line 160.
  57.  * 
  58.  * Revision 1.13  1995/02/10  17:53:20  matt
  59.  * Changed mission name again
  60.  * 
  61.  * Revision 1.12  1995/02/10  17:35:38  matt
  62.  * Changed name of built-in mission
  63.  * 
  64.  * Revision 1.11  1995/02/07  17:13:51  allender
  65.  * removed return statement in load_mission so that built in mission will
  66.  * actually set the Current_mission_name and _filename
  67.  * 
  68.  * Revision 1.10  1995/01/31  01:19:45  matt
  69.  * Made build_mission_list() sort missions by name
  70.  * 
  71.  * Revision 1.9  1995/01/30  13:49:58  allender
  72.  * changed build_mission_list in load_mission_by_name to include
  73.  * anarchy levels.
  74.  * 
  75.  * Revision 1.8  1995/01/30  13:03:51  matt
  76.  * Fixed dumb mistake
  77.  * 
  78.  * Revision 1.7  1995/01/30  12:55:22  matt
  79.  * Added vars to point to mission names
  80.  * 
  81.  * Revision 1.6  1995/01/22  18:57:28  matt
  82.  * Made player highest level work with missions
  83.  * 
  84.  * Revision 1.5  1995/01/22  14:13:08  matt
  85.  * Added flag in mission list for anarchy-only missions
  86.  * 
  87.  * Revision 1.4  1995/01/21  23:13:12  matt
  88.  * Made high scores with (not work, really) with loaded missions
  89.  * Don't give player high score when quit game
  90.  * 
  91.  * Revision 1.3  1995/01/21  16:27:12  matt
  92.  * Made endlevel briefing work with missions
  93.  * 
  94.  * Revision 1.2  1995/01/20  22:47:50  matt
  95.  * Mission system implemented, though imcompletely
  96.  * 
  97.  * Revision 1.1  1995/01/20  13:42:19  matt
  98.  * Initial revision
  99.  * 
  100.  * 
  101.  */
  102.  
  103.  
  104. #pragma off (unreferenced)
  105. static char rcsid[] = "$Id: mission.c 2.9 1995/05/26 16:16:32 john Exp $";
  106. #pragma on (unreferenced)
  107.  
  108. #include <stdio.h>
  109. #include <stdlib.h>
  110. #include <string.h>
  111. #include <dos.h>
  112. #include <ctype.h>
  113.  
  114. #include "cfile.h"
  115.  
  116. #include "inferno.h"
  117. #include "mission.h"
  118. #include "gameseq.h"
  119. #include "titles.h"
  120. #include "mono.h"
  121. #include "error.h"
  122.  
  123. mle Mission_list[MAX_MISSIONS];
  124.  
  125. int Current_mission_num;
  126. char *Current_mission_filename,*Current_mission_longname;
  127.  
  128. //this stuff should get defined elsewhere
  129.  
  130. char Level_names[MAX_LEVELS_PER_MISSION][13];
  131. char Secret_level_names[MAX_SECRET_LEVELS_PER_MISSION][13];
  132.  
  133. //strips damn newline from end of line
  134. char *mfgets(char *s,int n,FILE *f)
  135. {
  136.     char *r;
  137.  
  138.     r = fgets(s,n,f);
  139.     if (r && s[strlen(s)-1] == '\n')
  140.         s[strlen(s)-1] = 0;
  141.  
  142.     return r;
  143. }
  144.  
  145. //compare a string for a token. returns true if match
  146. int istok(char *buf,char *tok)
  147. {
  148.     return strnicmp(buf,tok,strlen(tok)) == 0;
  149.  
  150. }
  151.  
  152. //adds a terminating 0 after a string at the first white space
  153. add_term(char *s)
  154. {
  155.     while (*s && !isspace(*s)) s++;
  156.  
  157.     *s = 0;        //terminate!
  158. }
  159.  
  160. //returns ptr to string after '=' & white space, or NULL if no '='
  161. //adds 0 after parm at first white space
  162. char *get_value(char *buf)
  163. {
  164.     char *t;
  165.  
  166.     t = strchr(buf,'=')+1;
  167.  
  168.     if (t) {
  169.         while (*t && isspace(*t)) t++;
  170.  
  171.         if (*t)
  172.             return t;
  173.     }
  174.  
  175.     return NULL;        //error!
  176. }
  177.  
  178. //reads a line, returns ptr to value of passed parm.  returns NULL if none
  179. char *get_parm_value(char *parm,FILE *f)
  180. {
  181.     static char buf[80];
  182.     
  183.     if (!mfgets(buf,80,f))
  184.         return NULL;
  185.  
  186.     if (istok(buf,parm))
  187.         return get_value(buf);
  188.     else
  189.         return NULL;
  190. }
  191.  
  192. ml_sort_func(mle *e0,mle *e1)
  193. {
  194.     return strcmp(e0->mission_name,e1->mission_name);
  195.  
  196. }
  197.  
  198.  
  199. //fills in the global list of missions.  Returns the number of missions
  200. //in the list.  If anarchy_mode set, don't include non-anarchy levels.
  201. //if there is only one mission, this function will call load_mission on it.
  202. int build_mission_list(int anarchy_mode)
  203. {
  204.     int count=0;
  205.     struct find_t find;
  206.  
  207.     //fill in built-in level
  208.  
  209. #ifndef DEST_SAT
  210.         strcpy(Mission_list[0].filename,"");        //no filename for builtin
  211.         strcpy(Mission_list[0].mission_name,"Descent: First Strike");
  212.         count = 1;
  213. #endif
  214.  
  215.  
  216.     //now search for levels on disk
  217.  
  218.     if( !_dos_findfirst( "*.MSN", 0, &find ) )    {
  219.         do    {
  220.             FILE *mfile;
  221.             int is_anarchy;
  222.             char temp[13],*t;
  223.  
  224.             strcpy(temp,find.name);
  225.             if ((t = strchr(temp,'.')) == NULL)
  226.                 continue;
  227.             *t = 0;            //kill extension
  228.  
  229.             strncpy( Mission_list[count].filename, temp, 9 );
  230.             Mission_list[count].anarchy_only_flag = is_anarchy = 0;
  231.  
  232.             mfile = fopen(find.name,"rt");
  233.  
  234.             if (mfile) {
  235.                 char *p;
  236.  
  237.                 p = get_parm_value("name",mfile);
  238.  
  239.                 if (p) {
  240.                     char *t;
  241.                     if ((t=strchr(p,';'))!=NULL)
  242.                         *t=0;
  243.                     t = p + strlen(p)-1;
  244.                     while (isspace(*t)) t--;
  245.                     strncpy(Mission_list[count].mission_name,p,MISSION_NAME_LEN);
  246.                 }
  247.                 else {
  248.                     fclose(mfile);
  249.                     continue;            //abort this mission file
  250.                 }
  251.  
  252.                 p = get_parm_value("type",mfile);
  253.  
  254.                 //get mission type 
  255.                 if (p)
  256.                     Mission_list[count].anarchy_only_flag = is_anarchy = istok(p,"anarchy");
  257.  
  258.                 fclose(mfile);
  259.  
  260.                 if (!anarchy_mode && is_anarchy)
  261.                     continue;        //skip this mission
  262.  
  263.                 count++;
  264.             }
  265.  
  266.         } while( !_dos_findnext( &find ) && count<MAX_MISSIONS);
  267.     }
  268. #ifdef USE_CD
  269.     if ( strlen(destsat_cdpath) )    {
  270.         int i;
  271.         char temp_spec[128];
  272.         strcpy( temp_spec, destsat_cdpath );
  273.         strcat( temp_spec, "*.MSN" );
  274.         if( !_dos_findfirst( temp_spec, 0, &find ) )    {
  275.             do    {
  276.                 FILE *mfile;
  277.                 int is_anarchy;
  278.                 char temp[13],*t;
  279.     
  280.                 strcpy(temp,find.name);
  281.                 if ((t = strchr(temp,'.')) == NULL)
  282.                     continue;
  283.                 *t = 0;            //kill extension
  284.  
  285.                 for (i=0; i<count; i++ )    {
  286.                     if (!stricmp( Mission_list[i].filename, temp))
  287.                         break;
  288.                 }
  289.                 if ( i < count ) continue;        // Don't use same mission twice!
  290.         
  291.                 strncpy( Mission_list[count].filename, temp, 9 );
  292.                 Mission_list[count].anarchy_only_flag = is_anarchy = 0;
  293.     
  294.                 mfile = fopen(find.name,"rt");
  295.                 if (!mfile)    {
  296.                     strcpy( temp_spec, destsat_cdpath );
  297.                     strcat( temp_spec, find.name );
  298.                     mfile = fopen(temp_spec,"rt");
  299.                 }
  300.                 if (mfile) {
  301.                     char *p;
  302.     
  303.                     p = get_parm_value("name",mfile);
  304.     
  305.                     if (p) {
  306.                         char *t;
  307.                         if ((t=strchr(p,';'))!=NULL)
  308.                             *t=0;
  309.                         t = p + strlen(p)-1;
  310.                         while (isspace(*t)) t--;
  311.                         strncpy(Mission_list[count].mission_name,p,MISSION_NAME_LEN);
  312.                     }
  313.                     else {
  314.                         fclose(mfile);
  315.                         continue;            //abort this mission file
  316.                     }
  317.     
  318.                     p = get_parm_value("type",mfile);
  319.     
  320.                     //get mission type 
  321.                     if (p)
  322.                         Mission_list[count].anarchy_only_flag = is_anarchy = istok(p,"anarchy");
  323.     
  324.                     fclose(mfile);
  325.     
  326.                     if (!anarchy_mode && is_anarchy)
  327.                         continue;        //skip this mission
  328.     
  329.                     count++;
  330.                 }
  331.     
  332.             } while( !_dos_findnext( &find ) && count<MAX_MISSIONS);
  333.         }
  334.     }
  335. #endif
  336.  
  337.     if (count>1)
  338.         qsort(&Mission_list[1],count-1,sizeof(*Mission_list),ml_sort_func);
  339.  
  340.     load_mission(0);            //set built-in mission as default
  341.  
  342.     return count;
  343. }
  344.  
  345. //values for built-in mission
  346.  
  347. #define BIM_LAST_LEVEL            27
  348. #define BIM_LAST_SECRET_LEVEL    -3
  349. #define BIM_BRIEFING_FILE        "briefing.tex"
  350. #define BIM_ENDING_FILE            "endreg.tex"
  351.  
  352. //loads the specfied mission from the mission list.  build_mission_list()
  353. //must have been called.  If build_mission_list() returns 0, this function
  354. //does not need to be called.  Returns true if mission loaded ok, else false.
  355. int load_mission(int mission_num)
  356. {
  357.     Current_mission_num = mission_num;
  358.  
  359.     mprintf(( 0, "Loading mission %d\n", mission_num ));
  360.  
  361. #ifndef DEST_SAT
  362.     if (mission_num == 0) {        //built-in mission
  363.         int i;
  364.  
  365. #ifdef ROCKWELL_CODE
  366.         Last_level = 7;
  367.         Last_secret_level = 0;
  368.  
  369.         //build level names
  370.         for (i=0;i<Last_level;i++)
  371.             sprintf(Level_names[i], "LEVEL%02d.RDL", i+1);
  372. #else
  373.         Last_level = BIM_LAST_LEVEL;
  374.         Last_secret_level = BIM_LAST_SECRET_LEVEL;
  375.  
  376.         //build level names
  377.         for (i=0;i<Last_level;i++)
  378.             sprintf(Level_names[i], "LEVEL%02d.RDL", i+1);
  379.         for (i=0;i<-Last_secret_level;i++)
  380.             sprintf(Secret_level_names[i], "LEVELS%1d.RDL", i+1);
  381.  
  382.         Secret_level_table[0] = 10;
  383.         Secret_level_table[1] = 21;
  384.         Secret_level_table[2] = 24;
  385. #endif
  386.         strcpy(Briefing_text_filename,BIM_BRIEFING_FILE);
  387.         strcpy(Ending_text_filename,BIM_ENDING_FILE);
  388.         cfile_use_alternate_hogfile(NULL);        //disable alternate
  389.     } else 
  390. #endif
  391.     {         //NOTE LINK TO ABOVE IF!!!!!
  392.             //read mission from file 
  393.         FILE *mfile;
  394.         char buf[80], tmp[80], *v;
  395.  
  396.         strcpy(buf,Mission_list[mission_num].filename);
  397.         strcat(buf,".MSN");
  398.  
  399.         strcpy(tmp,Mission_list[mission_num].filename);
  400.         strcat(tmp,".HOG");
  401.         cfile_use_alternate_hogfile(tmp);
  402.  
  403.         mfile = fopen(buf,"rt");
  404. #ifdef USE_CD
  405.         if (mfile == NULL) {
  406.             if ( strlen(destsat_cdpath) )    {
  407.                 char temp_spec[128];
  408.                 strcpy( temp_spec, destsat_cdpath );
  409.                 strcat( temp_spec, buf );
  410.                 mfile = fopen( temp_spec, "rt" );
  411.             }
  412.         }
  413. #endif
  414.         if (mfile == NULL) {
  415.             Current_mission_num = -1;
  416.             return 0;        //error!
  417.         }
  418.  
  419.         //init vars
  420.         Last_level =         0;
  421.         Last_secret_level = 0;
  422.         Briefing_text_filename[0] = 0;
  423.         Ending_text_filename[0] = 0;
  424.     
  425. #ifdef DEST_SAT
  426.         if (!stricmp(Mission_list[mission_num].filename, "DESTSAT")) {        //    Destination Saturn.
  427.             strcpy(Briefing_text_filename,"briefsat.tex");
  428.             strcpy(Ending_text_filename,"endsat.tex");
  429.         }
  430. #endif
  431.  
  432.         while (mfgets(buf,80,mfile)) {
  433.  
  434.             if (istok(buf,"name"))
  435.                 continue;                        //already have name, go to next line
  436.             else if (istok(buf,"type"))
  437.                 continue;                        //already have name, go to next line                
  438.             else if (istok(buf,"hog")) {
  439.                 char    *bufp = buf;
  440.  
  441.                 while (*(bufp++) != '=')
  442.                     ;
  443.  
  444.                 if (*bufp == ' ')
  445.                     while (*(++bufp) == ' ')
  446.                         ;
  447.  
  448.                 cfile_use_alternate_hogfile(bufp);
  449.                 mprintf((0, "Hog file override = [%s]\n", bufp));
  450.             } else if (istok(buf,"briefing")) {
  451.                 if ((v = get_value(buf)) != NULL) {
  452.                     add_term(v);
  453.                     if (strlen(v) < 13)
  454.                         strcpy(Briefing_text_filename,v);
  455.                 }
  456.             }
  457.             else if (istok(buf,"ending")) {
  458.                 if ((v = get_value(buf)) != NULL) {
  459.                     add_term(v);
  460.                     if (strlen(v) < 13)
  461.                         strcpy(Ending_text_filename,v);
  462.                 }
  463.             }
  464.             else if (istok(buf,"num_levels")) {
  465.  
  466.                 if ((v=get_value(buf))!=NULL) {
  467.                     int n_levels,i;
  468.  
  469.                     n_levels = atoi(v);
  470.  
  471.                     for (i=0;i<n_levels && mfgets(buf,80,mfile);i++) {
  472.  
  473.                         add_term(buf);
  474.                         if (strlen(buf) <= 12) {
  475.                             strcpy(Level_names[i],buf);
  476.                             Last_level++;
  477.                         }
  478.                         else
  479.                             break;
  480.                     }
  481.  
  482.                 }
  483.             }
  484.             else if (istok(buf,"num_secrets")) {
  485.                 if ((v=get_value(buf))!=NULL) {
  486.                     int n_secret_levels,i;
  487.  
  488.                     n_secret_levels = atoi(v);
  489.  
  490.                     for (i=0;i<n_secret_levels && mfgets(buf,80,mfile);i++) {
  491.                         char *t;
  492.  
  493.                         
  494.                         if ((t=strchr(buf,','))!=NULL) *t++=0;
  495.                         else
  496.                             break;
  497.  
  498.                         add_term(buf);
  499.                         if (strlen(buf) <= 12) {
  500.                             strcpy(Secret_level_names[i],buf);
  501.                             Secret_level_table[i] = atoi(t);
  502.                             if (Secret_level_table[i]<1 || Secret_level_table[i]>Last_level)
  503.                                 break;
  504.                             Last_secret_level--;
  505.                         }
  506.                         else
  507.                             break;
  508.                     }
  509.  
  510.                 }
  511.             }
  512.  
  513.         }
  514.  
  515.         fclose(mfile);
  516.  
  517.         if (Last_level <= 0) {
  518.             Current_mission_num = -1;        //no valid mission loaded 
  519.             return 0;
  520.         }
  521.     }
  522.  
  523.     Current_mission_filename = Mission_list[Current_mission_num].filename;
  524.     Current_mission_longname = Mission_list[Current_mission_num].mission_name;
  525.  
  526.     return 1;
  527. }
  528.  
  529. //loads the named mission if exists.
  530. //Returns true if mission loaded ok, else false.
  531. int load_mission_by_name(char *mission_name)
  532. {
  533.     int n,i;
  534.  
  535.     n = build_mission_list(1);
  536.  
  537.     for (i=0;i<n;i++)
  538.         if (!stricmp(mission_name,Mission_list[i].filename))
  539.             return load_mission(i);
  540.  
  541.     return 0;        //couldn't find mission
  542. }
  543.  
  544. 
  545.