home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / gameseq.c < prev    next >
Text File  |  1998-06-08  |  46KB  |  1,679 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/gameseq.c $
  15.  * $Revision: 2.10 $
  16.  * $Author: john $
  17.  * $Date: 1995/12/19 15:48:25 $
  18.  * 
  19.  * Routines for EndGame, EndLevel, etc.
  20.  * 
  21.  * $Log: gameseq.c $
  22.  * Revision 2.10  1995/12/19  15:48:25  john
  23.  * Made screen reset when loading new level.
  24.  * 
  25.  * Revision 2.9  1995/07/07  16:47:52  john
  26.  * Fixed bug with reactor time..
  27.  * 
  28.  * Revision 2.8  1995/06/15  12:14:18  john
  29.  * Made end game, win game and title sequences all go
  30.  * on after 5 minutes automatically.
  31.  * 
  32.  * Revision 2.7  1995/05/26  16:16:25  john
  33.  * Split SATURN into define's for requiring cd, using cd, etc.
  34.  * Also started adding all the Rockwell stuff.
  35.  * 
  36.  * Revision 2.6  1995/03/24  13:11:20  john
  37.  * Added save game during briefing screens.
  38.  * 
  39.  * Revision 2.5  1995/03/23  17:56:20  allender
  40.  * added code to record old laser level and weapons when player gets
  41.  * new ship
  42.  * 
  43.  * Revision 2.4  1995/03/21  08:39:14  john
  44.  * Ifdef'd out the NETWORK code.
  45.  * 
  46.  * Revision 2.3  1995/03/15  14:33:33  john
  47.  * Added code to force the Descent CD-rom in the drive.
  48.  * 
  49.  * Revision 2.2  1995/03/06  16:47:26  mike
  50.  * destination saturn
  51.  * 
  52.  * Revision 2.1  1995/03/06  15:23:23  john
  53.  * New screen techniques.
  54.  * 
  55.  * Revision 2.0  1995/02/27  11:28:53  john
  56.  * New version 2.0, which has no anonymous unions, builds with
  57.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  58.  * 
  59.  * Revision 1.310  1995/02/14  10:48:09  mike
  60.  * zero bonus if you are a cheater.
  61.  * 
  62.  * Revision 1.309  1995/02/11  19:17:08  rob
  63.  * Fixed bug in laser fire rate after demo playback.
  64.  * 
  65.  * Revision 1.308  1995/02/11  14:34:08  rob
  66.  * Added include of netmisc.c
  67.  * 
  68.  * Revision 1.307  1995/02/11  14:29:04  rob
  69.  * Fixes for invul. controlcen.
  70.  * 
  71.  * Revision 1.306  1995/02/11  13:47:00  mike
  72.  * fix cheats.
  73.  * 
  74.  * Revision 1.305  1995/02/11  13:10:52  rob
  75.  * Fixed end of anarchy mission problems.
  76.  * 
  77.  * Revision 1.304  1995/02/11  12:46:12  mike
  78.  * initialize Robot_firing_enabled, part of AHIMSA cheat.
  79.  * 
  80.  * Revision 1.303  1995/02/11  12:42:03  john
  81.  * Added new song method, with FM bank switching..
  82.  * 
  83.  * Revision 1.302  1995/02/10  17:39:29  matt
  84.  * Changed secret exit message to be centered
  85.  * 
  86.  * Revision 1.301  1995/02/10  16:17:33  mike
  87.  * init Last_level_path_shown.
  88.  * 
  89.  * Revision 1.300  1995/02/09  22:18:22  john
  90.  * Took out between level saves.
  91.  * 
  92.  * Revision 1.299  1995/02/09  12:11:42  rob
  93.  * Get rid of high scores thing for multiplayer games.
  94.  * 
  95.  * Revision 1.298  1995/02/08  20:34:24  rob
  96.  * Took briefing screens back OUT of coop games (per Interplay request)
  97.  * 
  98.  * Revision 1.297  1995/02/08  19:20:09  rob
  99.  * Moved checksum calc.
  100.  * 
  101.  * Revision 1.296  1995/02/05  14:39:24  rob
  102.  * Changed object mapping to be more efficient.
  103.  * 
  104.  * Revision 1.295  1995/02/02  19:05:38  john
  105.  * Made end level menu for 27 not overwrite descent title..
  106.  * 
  107.  * Revision 1.294  1995/02/02  16:36:42  adam
  108.  * *** empty log message ***
  109.  * 
  110.  * Revision 1.293  1995/02/02  15:58:02  john
  111.  * Added turbo mode cheat.
  112.  * 
  113.  * Revision 1.292  1995/02/02  15:29:34  matt
  114.  * Changed & localized secret level text
  115.  * 
  116.  * Revision 1.291  1995/02/02  10:50:03  adam
  117.  * messed with secret level message
  118.  * 
  119.  * Revision 1.290  1995/02/02  01:20:28  adam
  120.  * changed endgame song temporarily.
  121.  * 
  122.  * Revision 1.289  1995/02/01  23:19:43  rob
  123.  * Fixed up endlevel stuff for multiplayer.
  124.  * Put in palette fades around areas that didn't have them before.
  125.  * 
  126.  * Revision 1.288  1995/02/01  17:12:34  mike
  127.  * Make score come after endgame screens.
  128.  * 
  129.  * Revision 1.287  1995/01/30  18:34:30  rob
  130.  * Put briefing screens back into coop games.
  131.  * 
  132.  * Revision 1.286  1995/01/27  13:07:59  rob
  133.  * Removed erroneous warning message.
  134.  * 
  135.  * Revision 1.285  1995/01/27  11:47:43  rob
  136.  * Removed new secret level menu from multiplayer games.
  137.  * 
  138.  * Revision 1.284  1995/01/26  22:11:11  mike
  139.  * Purple chromo-blaster (ie, fusion cannon) spruce up (chromification)
  140.  * 
  141.  * Revision 1.283  1995/01/26  16:55:13  rob
  142.  * Removed ship bonus from cooperative endgame.
  143.  * 
  144.  * Revision 1.282  1995/01/26  16:45:24  mike
  145.  * Add autofire fusion cannon stuff.
  146.  * 
  147.  * Revision 1.281  1995/01/26  14:44:44  rob
  148.  * Removed unnecessary #ifdefs around mprintfs.
  149.  * Changed NumNetPlayerPositions to be independant of MaxNumNetPlayers to
  150.  * accomodate 4-player robo-archy games with 8 start positions.
  151.  * 
  152.  * Revision 1.280  1995/01/26  12:19:01  rob
  153.  * Changed network_do_frame call.
  154.  * 
  155.  * Revision 1.279  1995/01/26  00:35:03  matt
  156.  * Changed numbering convention for HMP files for levels
  157.  * 
  158.  * Revision 1.278  1995/01/25  16:07:59  matt
  159.  * Added message (prototype) when going to secret level
  160.  * 
  161.  * Revision 1.277  1995/01/22  18:57:23  matt
  162.  * Made player highest level work with missions
  163.  * 
  164.  * Revision 1.276  1995/01/21  23:13:08  matt
  165.  * Made high scores with (not work, really) with loaded missions
  166.  * Don't give player high score when quit game
  167.  * 
  168.  * Revision 1.275  1995/01/21  17:17:39  john
  169.  * *** empty log message ***
  170.  * 
  171.  * Revision 1.274  1995/01/21  17:15:38  john
  172.  * Added include for state.h
  173.  * 
  174.  * Revision 1.273  1995/01/21  16:21:14  matt
  175.  * Fixed bugs in secret level sequencing
  176.  * 
  177.  * Revision 1.272  1995/01/20  22:47:29  matt
  178.  * Mission system implemented, though imcompletely
  179.  * 
  180.  * Revision 1.271  1995/01/19  17:00:48  john
  181.  * Made save game work between levels.
  182.  * 
  183.  * Revision 1.270  1995/01/17  17:49:10  rob
  184.  * Added key syncing for coop.
  185.  * 
  186.  * Revision 1.269  1995/01/17  14:27:37  john
  187.  * y
  188.  * 
  189.  * Revision 1.268  1995/01/17  13:36:33  john
  190.  * Moved pig loading into StartNewLevelSub.
  191.  * 
  192.  * Revision 1.267  1995/01/16  16:53:55  john
  193.  * Added code to save cheat state during save game.
  194.  * 
  195.  * Revision 1.266  1995/01/15  19:42:10  matt
  196.  * Ripped out hostage faces for registered version
  197.  * 
  198.  * Revision 1.265  1995/01/15  16:55:06  john
  199.  * Improved mine texture parsing.
  200.  * 
  201.  * Revision 1.264  1995/01/15  11:56:24  john
  202.  * Working version of paging.
  203.  * 
  204.  * Revision 1.263  1995/01/14  19:16:40  john
  205.  * First version of new bitmap paging code.
  206.  * 
  207.  * Revision 1.262  1995/01/13  17:38:58  yuan
  208.  * Removed Int3() for number players check.
  209.  * 
  210.  * Revision 1.261  1995/01/12  12:09:52  yuan
  211.  * Added coop object capability.
  212.  * 
  213.  * Revision 1.260  1995/01/05  17:16:08  yuan
  214.  * Removed Int3s.
  215.  * 
  216.  * Revision 1.259  1995/01/05  11:34:29  john
  217.  * Took out endlevel save stuff for registered.
  218.  * 
  219.  * Revision 1.258  1995/01/04  19:00:16  rob
  220.  * Added some debugging for two bugs.
  221.  * 
  222.  * Revision 1.257  1995/01/04  13:18:18  john
  223.  * Added cool 6 game save.
  224.  * 
  225.  * Revision 1.256  1995/01/04  08:46:18  rob
  226.  * JOHN CHECKED IN FOR ROB !!!
  227.  * 
  228.  * Revision 1.255  1995/01/02  20:07:35  rob
  229.  * Added score syncing.
  230.  * Get rid of endlevel score for coop games (put it back in elsewhere)
  231.  * 
  232.  * Revision 1.254  1995/01/02  16:17:43  mike
  233.  * init super boss.
  234.  * 
  235.  * Revision 1.253  1994/12/21  21:08:47  rob
  236.  * fixed a bug in coop player ship positions.
  237.  * 
  238.  * Revision 1.252  1994/12/21  12:57:08  rob
  239.  * Handle additional player ships in mines.
  240.  * 
  241.  * 
  242.  */
  243.  
  244.  
  245. #pragma off (unreferenced)
  246. static char rcsid[] = "$Id: gameseq.c 2.10 1995/12/19 15:48:25 john Exp $";
  247. #pragma on (unreferenced)
  248.  
  249. #include <stdio.h>
  250. #include <malloc.h>
  251. #include <stdlib.h>
  252. #include <string.h>
  253. #include <conio.h>
  254. #include <stdarg.h>
  255. #include <io.h>
  256. #include <errno.h>
  257. #include <time.h>
  258.  
  259. #include "inferno.h"
  260. #include "game.h"
  261. #include "key.h"
  262. #include "object.h"
  263. #include "physics.h"
  264. #include "error.h"
  265. #include "joy.h"
  266. #include "mono.h"
  267. #include "iff.h"
  268. #include "pcx.h"
  269. #include "timer.h"
  270. #include "render.h"
  271. #include "laser.h"
  272. #include "screens.h"
  273. #include "textures.h"
  274. #include "slew.h"
  275. #include "gauges.h"
  276. #include "texmap.h"
  277. #include "3d.h"
  278. #include "effects.h"
  279. #include "effect2d.h"
  280. #include "menu.h"
  281. #include "gameseg.h"
  282. #include "wall.h"
  283. #include "ai.h"
  284. #include "hostage.h"
  285. #include "fuelcen.h"
  286. #include "switch.h"
  287. #include "digi.h"
  288. #include "gamesave.h"
  289. #include "scores.h"
  290. #include "ibitblt.h"
  291. #include "mem.h"
  292. #include "palette.h"
  293. #include "morph.h"
  294. #include "lighting.h"
  295. #include "newdemo.h"
  296. #include "titles.h"
  297. #include "collide.h"
  298. #include "weapon.h"
  299. #include "sounds.h"
  300. #include "args.h"
  301. #include "gameseq.h"
  302. #include "gamefont.h"
  303. #include "newmenu.h"
  304. #include "endlevel.h"
  305. #include "network.h"
  306. #include "arcade.h"
  307. #include "playsave.h"
  308. #include "ctype.h"
  309. #include "multi.h"
  310. #include "fireball.h"
  311. #include "kconfig.h"
  312. #include "config.h"
  313. #include "robot.h"
  314. #include "automap.h"
  315. #include "cntrlcen.h"
  316. #include "powerup.h"
  317. #include "modem.h"
  318. #include "text.h"
  319. #include "cfile.h"
  320. #include "piggy.h"
  321. #include "texmerge.h"
  322. #include "paging.h"
  323. #include "mission.h"
  324. #include "State.h"
  325. #include "songs.h"
  326. #include "netmisc.h"
  327.  
  328. #ifdef EDITOR
  329. #include "editor\editor.h"
  330. #endif
  331.  
  332. //Current_level_num starts at 1 for the first level
  333. //-1,-2,-3 are secret levels
  334. //0 means not a real level loaded
  335. int    Current_level_num=0,Next_level_num;
  336. char    Current_level_name[LEVEL_NAME_LEN];        
  337.  
  338. int Last_level,Last_secret_level;
  339.  
  340. // Global variables describing the player
  341. int                 N_players=1;                        // Number of players ( >1 means a net game, eh?)
  342. int                 Player_num=0;                        // The player number who is on the console.
  343. player            Players[MAX_PLAYERS];            // Misc player info
  344. obj_position    Player_init[MAX_PLAYERS];
  345.  
  346. // Global variables telling what sort of game we have
  347. int MaxNumNetPlayers = -1;
  348. int NumNetPlayerPositions = -1;
  349.  
  350. // Extern from game.c to fix a bug in the cockpit!
  351.  
  352. extern int last_drawn_cockpit;
  353. extern int Last_level_path_created;
  354.  
  355. void HUD_clear_messages(); // From hud.c
  356.  
  357.  
  358. void verify_console_object()
  359. {
  360.     Assert( Player_num > -1 );
  361.     Assert( Players[Player_num].objnum > -1 );
  362.     ConsoleObject = &Objects[Players[Player_num].objnum];
  363.     Assert( ConsoleObject->type==OBJ_PLAYER );
  364.     Assert( ConsoleObject->id==Player_num );
  365. }
  366.  
  367. int count_number_of_robots() 
  368. {
  369.     int robot_count;
  370.     int i;
  371.  
  372.     robot_count = 0;
  373.     for (i=0;i<=Highest_object_index;i++) {
  374.         if (Objects[i].type == OBJ_ROBOT)
  375.             robot_count++;
  376.     }
  377.  
  378.     return robot_count;
  379. }
  380.  
  381.  
  382. int count_number_of_hostages() 
  383. {
  384.     int count;
  385.     int i;
  386.  
  387.     count = 0;
  388.     for (i=0;i<=Highest_object_index;i++) {
  389.         if (Objects[i].type == OBJ_HOSTAGE)
  390.             count++;
  391.     }
  392.  
  393.     return count;
  394. }
  395.  
  396.  
  397. void
  398. gameseq_init_network_players()
  399. {
  400.     int i,k,j;
  401.  
  402.     // Initialize network player start locations and object numbers
  403.  
  404.     ConsoleObject = &Objects[0];
  405.     k = 0;
  406.     j = 0;
  407.     for (i=0;i<=Highest_object_index;i++) {
  408.  
  409.         if (( Objects[i].type==OBJ_PLAYER )    || (Objects[i].type == OBJ_GHOST) || (Objects[i].type == OBJ_COOP))
  410.         {
  411. #ifndef SHAREWARE
  412.             if ( (!(Game_mode & GM_MULTI_COOP) && ((Objects[i].type == OBJ_PLAYER)||(Objects[i].type==OBJ_GHOST))) ||
  413.                ((Game_mode & GM_MULTI_COOP) && ((j == 0) || ( Objects[i].type==OBJ_COOP ))) )
  414.             {
  415.                 mprintf((0, "Created Cooperative multiplayer object\n"));
  416.                 Objects[i].type=OBJ_PLAYER;
  417. #endif
  418.                 mprintf((0, "Player init %d is ship %d.\n", k, j));
  419.                 Player_init[k].pos = Objects[i].pos;
  420.                 Player_init[k].orient = Objects[i].orient;
  421.                 Player_init[k].segnum = Objects[i].segnum;
  422.                 Players[k].objnum = i;
  423.                 Objects[i].id = k;
  424.                 k++;
  425. #ifndef SHAREWARE
  426.             }
  427.             else
  428.                 obj_delete(i);
  429.             j++;
  430. #endif
  431.         }
  432.     }
  433.     NumNetPlayerPositions = k;
  434.  
  435. #ifndef NDEBUG
  436.     if ( ((Game_mode & GM_MULTI_COOP) && (NumNetPlayerPositions != 4)) ||
  437.           (!(Game_mode & GM_MULTI_COOP) && (NumNetPlayerPositions != 8)) )
  438.     {
  439.         mprintf((1, "--NOT ENOUGH MULTIPLAYER POSITIONS IN THIS MINE!--\n"));
  440.         //Int3(); // Not enough positions!!
  441.     }
  442. #endif
  443. }
  444.  
  445. void gameseq_remove_unused_players()
  446. {
  447.     int i;
  448.  
  449.     // 'Remove' the unused players
  450.  
  451. #ifdef NETWORK
  452.     if (Game_mode & GM_MULTI)
  453.     {
  454.         for (i=0; i < NumNetPlayerPositions; i++)
  455.         {
  456.             if ((!Players[i].connected) || (i >= N_players))
  457.             {
  458.                 #ifndef NDEBUG
  459. //                mprintf((0, "Ghosting player ship %d.\n", i+1));
  460.                 #endif
  461.                 multi_make_player_ghost(i);
  462.             }
  463.         }
  464.     }
  465.     else
  466. #endif
  467.     {        // Note link to above if!!!
  468.         #ifndef NDEBUG
  469.         mprintf((0, "Removing player objects numbered %d-%d.\n", 1, NumNetPlayerPositions));
  470.         #endif
  471.         for (i=1; i < NumNetPlayerPositions; i++)
  472.         {
  473.             obj_delete(Players[i].objnum);
  474.         }
  475.     }
  476. }
  477.  
  478. // Setup player for new game
  479. void init_player_stats_game()
  480. {
  481.     Players[Player_num].score = 0;
  482.     Players[Player_num].last_score = 0;
  483.     Players[Player_num].lives = INITIAL_LIVES;
  484.     Players[Player_num].level = 1;
  485.  
  486.     Players[Player_num].time_level = 0;
  487.     Players[Player_num].time_total = 0;
  488.     Players[Player_num].hours_level = 0;
  489.     Players[Player_num].hours_total = 0;
  490.  
  491.     Players[Player_num].energy = MAX_ENERGY;
  492.     Players[Player_num].shields = MAX_SHIELDS;
  493.     Players[Player_num].killer_objnum = -1;
  494.  
  495.     Players[Player_num].net_killed_total = 0;
  496.     Players[Player_num].net_kills_total = 0;
  497.  
  498.     Players[Player_num].num_kills_level = 0;
  499.     Players[Player_num].num_kills_total = 0;
  500.     Players[Player_num].num_robots_level = 0;
  501.     Players[Player_num].num_robots_total = 0;
  502.     
  503.     Players[Player_num].hostages_rescued_total = 0;
  504.     Players[Player_num].hostages_level = 0;
  505.     Players[Player_num].hostages_total = 0;
  506.  
  507.     Players[Player_num].laser_level = 0;
  508.     Players[Player_num].flags = 0;
  509.  
  510.     init_player_stats_new_ship();
  511.  
  512. }
  513.  
  514. void init_ammo_and_energy(void)
  515. {
  516.     if (Players[Player_num].energy < MAX_ENERGY)
  517.         Players[Player_num].energy = MAX_ENERGY;
  518.     if (Players[Player_num].shields < MAX_SHIELDS)
  519.         Players[Player_num].shields = MAX_SHIELDS;
  520.  
  521. //    for (i=0; i<MAX_PRIMARY_WEAPONS; i++)
  522. //        if (Players[Player_num].primary_ammo[i] < Default_primary_ammo_level[i])
  523. //            Players[Player_num].primary_ammo[i] = Default_primary_ammo_level[i];
  524.  
  525. //    for (i=0; i<MAX_SECONDARY_WEAPONS; i++)
  526. //        if (Players[Player_num].secondary_ammo[i] < Default_secondary_ammo_level[i])
  527. //            Players[Player_num].secondary_ammo[i] = Default_secondary_ammo_level[i];
  528.     if (Players[Player_num].secondary_ammo[0] < 2 + NDL - Difficulty_level)
  529.         Players[Player_num].secondary_ammo[0] = 2 + NDL - Difficulty_level;
  530. }
  531.  
  532. // Setup player for new level (After completion of previous level)
  533. void init_player_stats_level()
  534. {
  535.     // int    i;
  536.  
  537.     Players[Player_num].last_score = Players[Player_num].score;
  538.  
  539.     Players[Player_num].level = Current_level_num;
  540.  
  541.     #ifdef NETWORK
  542.     if (!Network_rejoined)
  543.     #endif
  544.         Players[Player_num].time_level = 0;    //Note link to above if !!!!!!
  545.  
  546.     init_ammo_and_energy();
  547.  
  548.     Players[Player_num].killer_objnum = -1;
  549.  
  550.     Players[Player_num].num_kills_level = 0;
  551.     Players[Player_num].num_robots_level = count_number_of_robots();
  552.     Players[Player_num].num_robots_total += Players[Player_num].num_robots_level;
  553.  
  554.     Players[Player_num].hostages_level = count_number_of_hostages();
  555.     Players[Player_num].hostages_total += Players[Player_num].hostages_level;
  556.     Players[Player_num].hostages_on_board = 0;
  557.  
  558.     Players[Player_num].flags &= (~KEY_BLUE);
  559.     Players[Player_num].flags &= (~KEY_RED);
  560.     Players[Player_num].flags &= (~KEY_GOLD);
  561.  
  562.     Players[Player_num].flags &= (~PLAYER_FLAGS_INVULNERABLE);
  563.     Players[Player_num].flags &= (~PLAYER_FLAGS_CLOAKED);
  564.  
  565.     Players[Player_num].cloak_time = 0;
  566.     Players[Player_num].invulnerable_time = 0;
  567.  
  568.     if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
  569.         Players[Player_num].flags |= (KEY_BLUE | KEY_RED | KEY_GOLD);
  570.  
  571.     Player_is_dead = 0; // Added by RH
  572.     Players[Player_num].homing_object_dist = -F1_0; // Added by RH
  573.  
  574.     Last_laser_fired_time = Next_laser_fire_time = GameTime; // added by RH, solved demo playback bug
  575.  
  576.     init_gauges();
  577. }
  578.  
  579. // Setup player for a brand-new ship
  580. void init_player_stats_new_ship()
  581. {
  582.     int    i;
  583.  
  584.     if (Newdemo_state == ND_STATE_RECORDING) {
  585.         newdemo_record_laser_level(Players[Player_num].laser_level, 0);
  586.         newdemo_record_player_weapon(0, 0);
  587.         newdemo_record_player_weapon(1, 0);
  588.     }
  589.  
  590.     Players[Player_num].energy = MAX_ENERGY;
  591.     Players[Player_num].shields = MAX_SHIELDS;
  592.     Players[Player_num].laser_level = 0;
  593.     Players[Player_num].killer_objnum = -1;
  594.     Players[Player_num].hostages_on_board = 0;
  595.  
  596.     for (i=0; i<MAX_PRIMARY_WEAPONS; i++)
  597.         Players[Player_num].primary_ammo[i] = 0;
  598.  
  599.     for (i=1; i<MAX_SECONDARY_WEAPONS; i++)
  600.         Players[Player_num].secondary_ammo[i] = 0;
  601.     Players[Player_num].secondary_ammo[0] = 2 + NDL - Difficulty_level;
  602.  
  603.     Players[Player_num].primary_weapon_flags = HAS_LASER_FLAG;
  604.     Players[Player_num].secondary_weapon_flags = HAS_CONCUSSION_FLAG;
  605.  
  606.     Primary_weapon = 0;
  607.     Secondary_weapon = 0;
  608.  
  609.     Players[Player_num].flags &= ~(PLAYER_FLAGS_QUAD_LASERS | PLAYER_FLAGS_AFTERBURNER | PLAYER_FLAGS_CLOAKED | PLAYER_FLAGS_INVULNERABLE);
  610.  
  611.     Players[Player_num].cloak_time = 0;
  612.     Players[Player_num].invulnerable_time = 0;
  613.  
  614.     Player_is_dead = 0;        //player no longer dead
  615.  
  616.     Players[Player_num].homing_object_dist = -F1_0; // Added by RH
  617. }
  618.  
  619. #ifdef NETWORK
  620. void reset_network_objects()
  621. {
  622.     memset(local_to_remote, -1, MAX_OBJECTS*sizeof(short));
  623.     memset(remote_to_local, -1, MAX_NUM_NET_PLAYERS*MAX_OBJECTS*sizeof(short));
  624.     memset(object_owner, -1, MAX_OBJECTS);
  625. }
  626. #endif
  627.  
  628. #ifdef EDITOR
  629.  
  630. //reset stuff so game is semi-normal when playing from editor
  631. void editor_reset_stuff_on_level()
  632. {
  633.     gameseq_init_network_players();
  634.     init_player_stats_level();
  635.     Viewer = ConsoleObject;
  636.     ConsoleObject = Viewer = &Objects[Players[Player_num].objnum];
  637.     ConsoleObject->id=Player_num;
  638.     ConsoleObject->control_type = CT_FLYING;
  639.     ConsoleObject->movement_type = MT_PHYSICS;
  640.     Game_suspended = 0;
  641.     verify_console_object();
  642.     Fuelcen_control_center_destroyed = 0;
  643.     if (Newdemo_state != ND_STATE_PLAYBACK)
  644.         gameseq_remove_unused_players();
  645.     init_cockpit();
  646.     init_robots_for_level();
  647.     init_ai_objects();
  648.     init_morphs();
  649.     init_all_matcens();
  650.     init_player_stats_new_ship();
  651. }
  652. #endif
  653.  
  654. void reset_player_object();
  655.  
  656.  
  657. static fix time_out_value;
  658. #pragma off (unreferenced)
  659. void DoEndLevelScoreGlitzPoll( int nitems, newmenu_item * menus, int * key, int citem )
  660. {
  661.  
  662.     if ( timer_get_approx_seconds() > time_out_value )     {
  663.         *key = -2;
  664.     }
  665. }
  666. #pragma on (unreferenced)
  667.  
  668. //do whatever needs to be done when a player dies in multiplayer
  669.  
  670. void DoGameOver()
  671. {
  672.     time_out_value = timer_get_approx_seconds() + i2f(60*5);
  673.     nm_messagebox1( TXT_GAME_OVER, DoEndLevelScoreGlitzPoll, 1, TXT_OK, "" );
  674.  
  675.     if (Current_mission_num == 0)
  676.         scores_maybe_add_player(0);
  677.  
  678.     Function_mode = FMODE_MENU;
  679.     Game_mode = GM_GAME_OVER;
  680.     longjmp( LeaveGame, 0 );        // Exit out of game loop
  681.  
  682. }
  683.  
  684. extern do_save_game_menu();
  685.  
  686. //update various information about the player
  687. void update_player_stats()
  688. {
  689. // I took out this 'if' because it was causing the reactor invul time to be
  690. // off for players that sit in the death screen. -JS jul 6,95
  691. //    if (!Player_exploded) {
  692.         Players[Player_num].time_level += FrameTime;    //the never-ending march of time...
  693.         if ( Players[Player_num].time_level > i2f(3600) )    {
  694.             Players[Player_num].time_level -= i2f(3600);
  695.             Players[Player_num].hours_level++;
  696.         }
  697.  
  698.         Players[Player_num].time_total += FrameTime;    //the never-ending march of time...
  699.         if ( Players[Player_num].time_total > i2f(3600) )    {
  700.             Players[Player_num].time_total -= i2f(3600);
  701.             Players[Player_num].hours_total++;
  702.         }
  703. //    }
  704.  
  705. //    Players[Player_num].energy += FrameTime*Energy_regen_ratio;    //slowly regenerate energy
  706.  
  707. //MK1015:    //slowly reduces player's energy & shields if over max
  708. //MK1015:
  709. //MK1015:    if (Players[Player_num].energy > MAX_ENERGY) {
  710. //MK1015:        Players[Player_num].energy -= FrameTime/8;
  711. //MK1015:        if (Players[Player_num].energy < MAX_ENERGY)
  712. //MK1015:            Players[Player_num].energy = MAX_ENERGY;
  713. //MK1015:    }
  714. //MK1015:
  715. //MK1015:    if (Players[Player_num].shields > MAX_SHIELDS) {
  716. //MK1015:        Players[Player_num].shields -= FrameTime/8;
  717. //MK1015:        if (Players[Player_num].shields < MAX_SHIELDS)
  718. //MK1015:            Players[Player_num].shields = MAX_SHIELDS;
  719. //MK1015:    }
  720. }
  721.  
  722. //go through this level and start any eclip sounds
  723. set_sound_sources()
  724. {
  725.     int segnum,sidenum;
  726.     segment *seg;
  727.  
  728.     digi_init_sounds();        //clear old sounds
  729.  
  730.     for (seg=&Segments[0],segnum=0;segnum<=Highest_segment_index;seg++,segnum++)
  731.         for (sidenum=0;sidenum<MAX_SIDES_PER_SEGMENT;sidenum++) {
  732.             int tm,ec,sn;
  733.  
  734.             if ((tm=seg->sides[sidenum].tmap_num2) != 0)
  735.                 if ((ec=TmapInfo[tm&0x3fff].eclip_num)!=-1)
  736.                     if ((sn=Effects[ec].sound_num)!=-1) {
  737.                         vms_vector pnt;
  738.  
  739.                         compute_center_point_on_side(&pnt,seg,sidenum);
  740.                         digi_link_sound_to_pos(sn,segnum,sidenum,&pnt,1, F1_0/2);
  741.  
  742.                     }
  743.         }
  744.  
  745. }
  746.  
  747.  
  748. //fix flash_dist=i2f(1);
  749. fix flash_dist=fl2f(.9);
  750.  
  751. //create flash for player appearance
  752. void create_player_appearance_effect(object *player_obj)
  753. {
  754.     vms_vector pos;
  755.     object *effect_obj;
  756.  
  757. #ifndef NDEBUG
  758.     {
  759.         int objnum = player_obj-Objects;
  760.         if ( (objnum < 0) || (objnum > Highest_object_index) )
  761.             Int3(); // See Rob, trying to track down weird network bug
  762.     }
  763. #endif
  764.  
  765.     if (player_obj == Viewer)
  766.         vm_vec_scale_add(&pos, &player_obj->pos, &player_obj->orient.fvec, fixmul(player_obj->size,flash_dist));
  767.     else
  768.         pos = player_obj->pos;
  769.  
  770.     effect_obj = object_create_explosion(player_obj->segnum, &pos, player_obj->size, VCLIP_PLAYER_APPEARANCE );
  771.  
  772.     if (effect_obj) {
  773.         effect_obj->orient = player_obj->orient;
  774.  
  775.         if ( Vclip[VCLIP_PLAYER_APPEARANCE].sound_num > -1 )
  776.             digi_link_sound_to_object( Vclip[VCLIP_PLAYER_APPEARANCE].sound_num, effect_obj-Objects, 0, F1_0);
  777.     }
  778. }
  779.  
  780. //
  781. // New Game sequencing functions
  782. //
  783.  
  784. //pairs of chars describing ranges
  785. char playername_allowed_chars[] = "azAZ09__--";
  786.  
  787. int MakeNewPlayerFile(int allow_abort)
  788. {
  789.     int x;
  790.     char filename[14];
  791.     newmenu_item m;
  792.     char text[CALLSIGN_LEN+1]="";
  793.     FILE *fp;
  794.  
  795.     strncpy(text, Players[Player_num].callsign,CALLSIGN_LEN);
  796.  
  797. try_again:
  798.     m.type=NM_TYPE_INPUT; m.text_len = 8; m.text = text;
  799.  
  800.     Newmenu_allowed_chars = playername_allowed_chars;
  801.     x = newmenu_do( NULL, TXT_ENTER_PILOT_NAME, 1, &m, NULL );
  802.     Newmenu_allowed_chars = NULL;
  803.  
  804.     if ( x < 0 ) {
  805.         if ( allow_abort ) return 0;
  806.         goto try_again;
  807.     }
  808.  
  809.     if (text[0]==0)    //null string
  810.         goto try_again;
  811.  
  812.     sprintf( filename, "%s.plr", text );
  813.  
  814.     fp = fopen( filename, "rb" );
  815.  
  816.     //if the callsign is the name of a tty device, prepend a char
  817.     if (fp && isatty(fileno(fp))) {
  818.         fclose(fp);
  819.         sprintf(filename,"$%.7s.plr",text);
  820.         fp = fopen(filename,"rb");
  821.     }
  822.     
  823.     if ( fp )    {
  824.         nm_messagebox(NULL, 1, TXT_OK, "%s '%s' %s", TXT_PLAYER, text, TXT_ALREADY_EXISTS );
  825.         fclose(fp);
  826.         goto try_again;
  827.     }
  828.  
  829.     if ( !new_player_config() )
  830.         goto try_again;            // They hit Esc during New player config
  831.  
  832.     strncpy(Players[Player_num].callsign, text, CALLSIGN_LEN);
  833.  
  834.     init_game_list();                //init to defaults
  835.  
  836.     write_player_file();
  837.  
  838.     return 1;
  839. }
  840.  
  841. //Inputs the player's name, without putting up the background screen
  842. RegisterPlayer()
  843. {
  844.     int i,j;
  845.     char filename[14];
  846.     int allow_abort_flag = 1;
  847.  
  848.     if ( Players[Player_num].callsign[0] == 0 )    {
  849.         //---------------------------------------------------------------------
  850.         // Set default config options in case there is no config file
  851.         // kc_keyboard, kc_joystick, kc_mouse are statically defined.
  852.         Config_joystick_sensitivity = 8;
  853.         Config_control_type =CONTROL_NONE;
  854.         for (i=0; i<CONTROL_MAX_TYPES; i++ )
  855.             for (j=0; j<MAX_CONTROLS; j++ )
  856.                 kconfig_settings[i][j] = default_kconfig_settings[i][j];
  857.         kc_set_controls();
  858.         //----------------------------------------------------------------
  859.  
  860.         // Read the last player's name from config file, not lastplr.txt
  861.         strncpy( Players[Player_num].callsign, config_last_player, CALLSIGN_LEN );
  862.  
  863.         if (config_last_player[0]==0)
  864.             allow_abort_flag = 0;
  865.     }
  866.  
  867. do_menu_again:
  868.     ;
  869.  
  870.     if (!newmenu_get_filename( TXT_SELECT_PILOT, "*.plr", filename, allow_abort_flag ))    {
  871.         return 0;        // They hit Esc in file selector
  872.     }
  873.  
  874.     if ( filename[0] == '<' )    {
  875.         // They selected 'create new pilot'
  876.         if (!MakeNewPlayerFile(allow_abort_flag))
  877.             //return 0;        // They hit Esc during enter name stage
  878.             goto do_menu_again;
  879.     } else {
  880.         strncpy(Players[Player_num].callsign,filename, CALLSIGN_LEN);
  881.     }
  882.  
  883.     read_player_file();
  884.  
  885.     Auto_leveling_on = Default_leveling_on;
  886.  
  887.     WriteConfigFile();        // Update lastplr
  888.  
  889.     return 1;
  890. }
  891.  
  892. extern int descent_critical_error;
  893.  
  894. //load a level off disk. level numbers start at 1.  Secret levels are -1,-2,-3
  895. void LoadLevel(int level_num) 
  896. {
  897.     char *level_name;
  898.     player save_player;
  899.  
  900. #ifdef REQUIRE_CD
  901.     {
  902.         FILE *fp;
  903.         int i;
  904.         char fname[128];
  905.         strcpy( fname, destsat_cdpath );
  906. #ifdef DEST_SAT
  907.         strcat( fname, "saturn.hog" );
  908. #else
  909.         strcat( fname, "descent.hog" );
  910. #endif
  911.         do {
  912.             descent_critical_error = 0;
  913.             fp = fopen( fname, "rb" );
  914.             if ( fp==NULL || descent_critical_error )    {
  915.                 if ( fp )    {
  916.                     fclose(fp);
  917.                     fp = NULL;
  918.                 }
  919.                 gr_set_current_canvas(NULL);
  920.                 gr_clear_canvas( gr_find_closest_color_current(0,0,0) );
  921.                 gr_palette_load( gr_palette );
  922.                 i = nm_messagebox( "Insert CD", 2, "Retry", "Exit", "Please put the\nDescent CD\nin your CD-ROM drive!\n" );
  923.                 if ( i==1 )
  924.                     exit(0);
  925.             }
  926.         } while ( fp == NULL );
  927.         fclose( fp );
  928.     }
  929. #endif
  930.  
  931.     save_player = Players[Player_num];    
  932.  
  933.     Assert(level_num <= Last_level  && level_num >= Last_secret_level  && level_num != 0);
  934.  
  935. #ifdef SHAREWARE
  936.     {
  937.         static char t[13];
  938.         sprintf(t, "LEVEL%02d.SDL", level_num);
  939.         level_name = t;
  940.     }
  941. #else
  942.     if (level_num<0)        //secret level
  943.         level_name = Secret_level_names[-level_num-1];
  944.     else                    //normal level
  945.         level_name = Level_names[level_num-1];
  946. #endif
  947.  
  948.     show_boxed_message(TXT_LOADING);
  949.  
  950.     if (!load_level(level_name))
  951.         Current_level_num=level_num;
  952.  
  953.     #ifdef NETWORK
  954.     my_segments_checksum = netmisc_calc_checksum(Segments, sizeof(segment)*(Highest_segment_index+1));
  955.     #endif
  956.  
  957.     load_endlevel_data(level_num);
  958.  
  959.     clear_boxed_message();
  960.  
  961.     #ifdef NETWORK
  962.     reset_network_objects();
  963.     #endif
  964.  
  965.     Players[Player_num] = save_player;
  966.  
  967.     set_sound_sources();
  968.  
  969.     songs_play_level_song( Current_level_num );
  970.  
  971. }
  972.  
  973. //sets up Player_num & ConsoleObject  
  974. InitPlayerObject()
  975. {
  976.     Assert(Player_num>=0 && Player_num<MAX_PLAYERS);
  977.  
  978.     if (Player_num != 0 )    {
  979.         Players[0] = Players[Player_num];
  980.         Player_num = 0;
  981.     }
  982.  
  983.     Players[Player_num].objnum = 0;
  984.  
  985.     ConsoleObject = &Objects[Players[Player_num].objnum];
  986.  
  987.     ConsoleObject->type                = OBJ_PLAYER;
  988.     ConsoleObject->id                    = Player_num;
  989.     ConsoleObject->control_type    = CT_FLYING;
  990.     ConsoleObject->movement_type    = MT_PHYSICS;
  991. }
  992.  
  993. extern void game_disable_cheats();
  994.  
  995. //starts a new game on the given level
  996. StartNewGame(int start_level)
  997. {
  998.     Game_mode = GM_NORMAL;
  999.     Function_mode = FMODE_GAME;
  1000.  
  1001.     Next_level_num = 0;
  1002.  
  1003.     InitPlayerObject();                //make sure player's object set up
  1004.  
  1005.     init_player_stats_game();        //clear all stats
  1006.  
  1007.     N_players = 1;
  1008.     #ifdef NETWORK
  1009.     Network_new_game = 0;
  1010.     #endif
  1011.  
  1012.     StartNewLevel(start_level);
  1013.  
  1014.     Players[Player_num].starting_level = start_level;        // Mark where they started
  1015.  
  1016.     game_disable_cheats();
  1017. }
  1018.  
  1019. //starts a resumed game loaded from disk
  1020. ResumeSavedGame(int start_level)
  1021. {
  1022.     Game_mode = GM_NORMAL;
  1023.     Function_mode = FMODE_GAME;
  1024.  
  1025.     N_players = 1;
  1026.     #ifdef NETWORK
  1027.     Network_new_game = 0;
  1028.     #endif
  1029.  
  1030.     InitPlayerObject();                //make sure player's object set up
  1031.  
  1032.     StartNewLevel(start_level);
  1033.  
  1034.     game_disable_cheats();
  1035. }
  1036.  
  1037. #ifdef NETWORK
  1038. extern void network_endlevel_poll2( int nitems, newmenu_item * menus, int * key, int citem ); // network.c
  1039. #endif
  1040.  
  1041.  
  1042. //    -----------------------------------------------------------------------------
  1043. //    Does the bonus scoring.
  1044. //    Call with dead_flag = 1 if player died, but deserves some portion of bonus (only skill points), anyway.
  1045. void DoEndLevelScoreGlitz(int network)
  1046. {
  1047.     int level_points, skill_points, energy_points, shield_points, hostage_points;
  1048.     int    all_hostage_points;
  1049.     int    endgame_points;
  1050.     char    all_hostage_text[64];
  1051.     char    endgame_text[64];
  1052.     #define N_GLITZITEMS 9
  1053.     char                m_str[N_GLITZITEMS][30];
  1054.     newmenu_item    m[9];
  1055.     int                i,c;
  1056.     char                title[128];
  1057.     int                is_last_level;
  1058.  
  1059.     level_points = Players[Player_num].score-Players[Player_num].last_score;
  1060.  
  1061.     if (!Cheats_enabled) {
  1062.         if (Difficulty_level > 1) {
  1063.             skill_points = level_points*(Difficulty_level-1)/2;
  1064.             skill_points -= skill_points % 100;
  1065.         } else
  1066.             skill_points = 0;
  1067.  
  1068.         shield_points = f2i(Players[Player_num].shields) * 10 * (Difficulty_level+1);
  1069.         energy_points = f2i(Players[Player_num].energy) * 5 * (Difficulty_level+1);
  1070.         hostage_points = Players[Player_num].hostages_on_board * 500 * (Difficulty_level+1);
  1071.     } else {
  1072.         skill_points = 0;
  1073.         shield_points = 0;
  1074.         energy_points = 0;
  1075.         hostage_points = 0;
  1076.     }
  1077.  
  1078.     all_hostage_text[0] = 0;
  1079.     endgame_text[0] = 0;
  1080.  
  1081.     if (!Cheats_enabled && (Players[Player_num].hostages_on_board == Players[Player_num].hostages_level)) {
  1082.         all_hostage_points = Players[Player_num].hostages_on_board * 1000 * (Difficulty_level+1);
  1083.         sprintf(all_hostage_text, "%s%i\n", TXT_FULL_RESCUE_BONUS, all_hostage_points);
  1084.     } else
  1085.         all_hostage_points = 0;
  1086.  
  1087.     if (!Cheats_enabled && !(Game_mode & GM_MULTI) && (Players[Player_num].lives) && (Current_level_num == Last_level)) {        //player has finished the game!
  1088.         endgame_points = Players[Player_num].lives * 10000;
  1089.         sprintf(endgame_text, "%s%i\n", TXT_SHIP_BONUS, endgame_points);
  1090.         is_last_level=1;
  1091.     } else
  1092.         endgame_points = is_last_level = 0;
  1093.  
  1094.     add_bonus_points_to_score(skill_points + energy_points + shield_points + hostage_points + all_hostage_points + endgame_points);
  1095.  
  1096.     c = 0;
  1097.     sprintf(m_str[c++], "%s%i", TXT_SHIELD_BONUS, shield_points);        // Return at start to lower menu...
  1098.     sprintf(m_str[c++], "%s%i", TXT_ENERGY_BONUS, energy_points);
  1099.     sprintf(m_str[c++], "%s%i", TXT_HOSTAGE_BONUS, hostage_points);
  1100.     sprintf(m_str[c++], "%s%i", TXT_SKILL_BONUS, skill_points);
  1101.  
  1102.     sprintf(m_str[c++], "%s", all_hostage_text);
  1103.     if (!(Game_mode & GM_MULTI) && (Players[Player_num].lives) && (Current_level_num == Last_level))
  1104.         sprintf(m_str[c++], "%s", endgame_text);
  1105.  
  1106.     sprintf(m_str[c++], "%s%i\n", TXT_TOTAL_BONUS, shield_points+energy_points+hostage_points+skill_points+all_hostage_points+endgame_points);
  1107.     sprintf(m_str[c++], "%s%i", TXT_TOTAL_SCORE, Players[Player_num].score);
  1108.  
  1109.     for (i=0; i<c; i++) {
  1110.         m[i].type = NM_TYPE_TEXT;
  1111.         m[i].text = m_str[i];
  1112.     }
  1113.  
  1114.     // m[c].type = NM_TYPE_MENU;    m[c++].text = "Ok";
  1115.  
  1116.     if (Current_level_num < 0)
  1117.         sprintf(title,"%s%s %d %s\n %s %s",is_last_level?"\n\n\n":"\n",TXT_SECRET_LEVEL, -Current_level_num, TXT_COMPLETE, Current_level_name, TXT_DESTROYED);
  1118.     else
  1119.         sprintf(title,"%s%s %d %s\n%s %s",is_last_level?"\n\n\n":"\n",TXT_LEVEL, Current_level_num, TXT_COMPLETE, Current_level_name, TXT_DESTROYED);
  1120.  
  1121.     Assert(c <= N_GLITZITEMS);
  1122.  
  1123.     gr_palette_fade_out(gr_palette, 32, 0);
  1124.  
  1125.     time_out_value = timer_get_approx_seconds() + i2f(60*5);
  1126.  
  1127. #ifdef NETWORK
  1128.     if ( network && (Game_mode & GM_NETWORK) )
  1129.         newmenu_do2(NULL, title, c, m, network_endlevel_poll2, 0, "MENU.PCX");
  1130.     else
  1131. #endif    // Note link!
  1132.         newmenu_do2(NULL, title, c, m, DoEndLevelScoreGlitzPoll, 0, "MENU.PCX");
  1133. }
  1134.  
  1135. //give the player the opportunity to save his game
  1136. DoEndlevelMenu()
  1137. {
  1138. #ifdef SHAREWARE
  1139.     if (!Cheats_enabled)
  1140.         do_save_game_menu();
  1141. #else
  1142. //No between level saves......!!!    state_save_all(1);
  1143. #endif
  1144. }
  1145.  
  1146. //called when the player has finished a level
  1147. PlayerFinishedLevel(int secret_flag)
  1148. {
  1149.     int    rval;
  1150.     int     was_multi = 0;
  1151.  
  1152.     //credit the player for hostages
  1153.     Players[Player_num].hostages_rescued_total += Players[Player_num].hostages_on_board;
  1154.  
  1155.     if (!(Game_mode & GM_MULTI) && (secret_flag)) {
  1156.         newmenu_item    m[1];
  1157.  
  1158.         m[0].type = NM_TYPE_TEXT;
  1159.         m[0].text = " ";            //TXT_SECRET_EXIT;
  1160.  
  1161.         newmenu_do2(NULL, TXT_SECRET_EXIT, 1, m, NULL, 0, "MENU.PCX");
  1162.     }
  1163.  
  1164. // -- mk mk mk -- used to be here -- mk mk mk --
  1165.  
  1166.     if (Game_mode & GM_NETWORK)
  1167.         if (secret_flag)
  1168.             Players[Player_num].connected = 4; // Finished and went to secret level
  1169.         else
  1170.             Players[Player_num].connected = 2; // Finished but did not die
  1171.  
  1172.     last_drawn_cockpit = -1;
  1173.  
  1174.     if (Current_level_num == Last_level) {
  1175.         #ifdef NETWORK
  1176.         if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
  1177.         {
  1178.             was_multi = 1;
  1179.             multi_endlevel_score();
  1180.             rval = AdvanceLevel(secret_flag);                //now go on to the next one (if one)
  1181.         }
  1182.         else 
  1183.         #endif
  1184.         {    // Note link to above else!
  1185.             rval = AdvanceLevel(secret_flag);                //now go on to the next one (if one)
  1186.             DoEndLevelScoreGlitz(0);        //give bonuses
  1187.         }
  1188.     } else {
  1189.         #ifdef NETWORK
  1190.         if (Game_mode & GM_MULTI)
  1191.             multi_endlevel_score();
  1192.         else 
  1193.         #endif    // Note link!!
  1194.             DoEndLevelScoreGlitz(0);        //give bonuses
  1195.         rval = AdvanceLevel(secret_flag);                //now go on to the next one (if one)
  1196.     }
  1197.  
  1198.     if (!was_multi && rval) {
  1199.         if (Current_mission_num == 0)
  1200.             scores_maybe_add_player(0);
  1201.         longjmp( LeaveGame, 0 );        // Exit out of game loop
  1202.     }
  1203.     else if (rval)
  1204.         longjmp( LeaveGame, 0 );
  1205. }
  1206.  
  1207.  
  1208. extern void do_end_game(void);
  1209.  
  1210. //from which level each do you get to each secret level 
  1211. int Secret_level_table[MAX_SECRET_LEVELS_PER_MISSION];
  1212.  
  1213. //called to go to the next level (if there is one)
  1214. //if secret_flag is true, advance to secret level, else next normal one
  1215. //    Return true if game over.
  1216. int AdvanceLevel(int secret_flag)
  1217. {
  1218.  
  1219.     int result;
  1220.  
  1221.     Fuelcen_control_center_destroyed = 0;
  1222.  
  1223.     #ifdef EDITOR
  1224.     if (Current_level_num == 0)
  1225.         return 0;        //not a real level
  1226.     #endif
  1227.  
  1228.     #ifdef NETWORK
  1229.     if (Game_mode & GM_MULTI)
  1230.     {
  1231.         result = multi_endlevel(&secret_flag); // Wait for other players to reach this point
  1232.         if (result) // failed to sync
  1233.             return (Current_level_num == Last_level);
  1234.     }
  1235.     #endif
  1236.  
  1237.     if (Current_level_num == Last_level) {        //player has finished the game!
  1238.         
  1239.         Function_mode = FMODE_MENU;
  1240.         if ((Newdemo_state == ND_STATE_RECORDING) || (Newdemo_state == ND_STATE_PAUSED))
  1241.             newdemo_stop_recording();
  1242.  
  1243.         songs_play_song( SONG_ENDGAME, 0 );
  1244.  
  1245.         do_end_game();
  1246.         return 1;
  1247.  
  1248.     } else {
  1249.  
  1250.         Next_level_num = Current_level_num+1;        //assume go to next normal level
  1251.  
  1252.         if (secret_flag) {            //go to secret level instead
  1253.             int i;
  1254.  
  1255.             for (i=0;i<-Last_secret_level;i++)
  1256.                 if (Secret_level_table[i]==Current_level_num) {
  1257.                     Next_level_num = -(i+1);
  1258.                     break;
  1259.                 }
  1260.             Assert(i<-Last_secret_level);        //couldn't find which secret level
  1261.         }
  1262.  
  1263.         if (Current_level_num < 0)    {            //on secret level, where to go?
  1264.  
  1265.             Assert(!secret_flag);                //shouldn't be going to secret level
  1266.             Assert(Current_level_num<=-1 && Current_level_num>=Last_secret_level);
  1267.  
  1268.             Next_level_num = Secret_level_table[(-Current_level_num)-1]+1;
  1269.         }
  1270.  
  1271.         if (!(Game_mode & GM_MULTI))
  1272.             DoEndlevelMenu(); // Let use save their game
  1273.  
  1274.         StartNewLevel(Next_level_num);
  1275.  
  1276.     }
  1277.  
  1278.     return 0;
  1279. }
  1280.  
  1281.  
  1282. void
  1283. died_in_mine_message(void)
  1284. {
  1285.     // Tell the player he died in the mine, explain why
  1286.     int old_fmode, pcx_error;
  1287.  
  1288.     if (Game_mode & GM_MULTI)
  1289.         return;
  1290.  
  1291.     gr_palette_fade_out(gr_palette, 32, 0);
  1292.  
  1293.     gr_set_current_canvas(NULL);
  1294.     
  1295.     pcx_error = pcx_read_bitmap("STARS.PCX",&grd_curcanv->cv_bitmap,grd_curcanv->cv_bitmap.bm_type,NULL);
  1296.     Assert(pcx_error == PCX_ERROR_NONE);
  1297.  
  1298.     old_fmode = Function_mode;
  1299.     Function_mode = FMODE_MENU;
  1300.     nm_messagebox(NULL, 1, TXT_OK, TXT_DIED_IN_MINE);
  1301.     Function_mode = old_fmode;
  1302. }
  1303.  
  1304. //called when the player has died
  1305. DoPlayerDead()
  1306. {
  1307.     reset_palette_add();
  1308.  
  1309.     gr_palette_load (gr_palette);
  1310.  
  1311.     dead_player_end();        //terminate death sequence (if playing)
  1312.  
  1313. #ifdef HOSTAGE_FACES
  1314.     stop_all_hostage_clips();
  1315. #endif
  1316.  
  1317.     #ifdef EDITOR
  1318.     if (Game_mode == GM_EDITOR) {            //test mine, not real level
  1319.         object * player = &Objects[Players[Player_num].objnum];
  1320.         //nm_messagebox( "You're Dead!", 1, "Continue", "Not a real game, though." );
  1321.         load_level("gamesave.lvl");
  1322.         init_player_stats_new_ship();
  1323.         player->flags &= ~OF_SHOULD_BE_DEAD;
  1324.         StartLevel(0);
  1325.         return;
  1326.     }
  1327.     #endif
  1328.  
  1329.     #ifdef NETWORK
  1330.     if ( Game_mode&GM_MULTI )
  1331.     {
  1332.         multi_do_death(Players[Player_num].objnum);
  1333.     }
  1334.     else 
  1335.     #endif        
  1336.     {                //Note link to above else!
  1337.         Players[Player_num].lives--;
  1338.         if (Players[Player_num].lives == 0)
  1339.         {    
  1340.             DoGameOver();
  1341.             return;
  1342.         }
  1343.     }
  1344.                 
  1345.     if ( Fuelcen_control_center_destroyed ) {
  1346.         int    rval;
  1347.  
  1348.         //clear out stuff so no bonus
  1349.         Players[Player_num].hostages_on_board = 0;
  1350.         Players[Player_num].energy = 0;
  1351.         Players[Player_num].shields = 0;
  1352.         Players[Player_num].connected = 3;
  1353.  
  1354.         died_in_mine_message(); // Give them some indication of what happened
  1355.  
  1356.         if (Current_level_num == Last_level) {
  1357.             #ifdef NETWORK
  1358.             if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
  1359.             {
  1360.                 multi_endlevel_score();
  1361.                 rval = AdvanceLevel(0);            //if finished, go on to next level
  1362.             }
  1363.             else
  1364.             #endif    
  1365.             {            // Note link to above else!
  1366.                 rval = AdvanceLevel(0);            //if finished, go on to next level
  1367.                 DoEndLevelScoreGlitz(0);    
  1368.             }
  1369.             init_player_stats_new_ship();
  1370.             last_drawn_cockpit = -1;
  1371.         } else {
  1372.             #ifdef NETWORK
  1373.             if (Game_mode & GM_MULTI)
  1374.                 multi_endlevel_score();
  1375.             else
  1376.             #endif
  1377.                 DoEndLevelScoreGlitz(0);        // Note above link!
  1378.  
  1379.             rval = AdvanceLevel(0);            //if finished, go on to next level
  1380.             init_player_stats_new_ship();
  1381.             last_drawn_cockpit = -1;
  1382.         }
  1383.  
  1384.         if (rval) {
  1385.             if (Current_mission_num == 0)
  1386.                 scores_maybe_add_player(0);
  1387.             longjmp( LeaveGame, 0 );        // Exit out of game loop
  1388.         }
  1389.     } else {
  1390.         init_player_stats_new_ship();
  1391.         StartLevel(1);
  1392.     }
  1393.  
  1394. }
  1395.  
  1396. //called when the player is starting a new level for normal game mode and restore state
  1397. StartNewLevelSub(int level_num, int page_in_textures)
  1398. {
  1399.     if (!(Game_mode & GM_MULTI)) {
  1400.         last_drawn_cockpit = -1;
  1401.     }
  1402.  
  1403.     if (Newdemo_state == ND_STATE_PAUSED)
  1404.         Newdemo_state = ND_STATE_RECORDING;
  1405.  
  1406.     if (Newdemo_state == ND_STATE_RECORDING) {
  1407.         newdemo_set_new_level(level_num);
  1408.         newdemo_record_start_frame(FrameCount, FrameTime );
  1409.     }
  1410.  
  1411.     if (Game_mode & GM_MULTI)
  1412.         Function_mode = FMODE_MENU; // Cheap fix to prevent problems with errror dialogs in loadlevel.
  1413.  
  1414.     LoadLevel(level_num);
  1415.  
  1416.     if ( page_in_textures )    {
  1417.         piggy_load_level_data();
  1418.     }
  1419.  
  1420.     Assert(Current_level_num == level_num);    //make sure level set right
  1421.  
  1422.     gameseq_init_network_players(); // Initialize the Players array for 
  1423.                                               // this level
  1424.  
  1425. #ifdef NETWORK
  1426.     if (Game_mode & GM_NETWORK)
  1427.     {
  1428.         if(network_level_sync()) // After calling this, Player_num is set
  1429.             return;
  1430.     }
  1431.     if ((Game_mode & GM_SERIAL) || (Game_mode & GM_MODEM))
  1432.     {
  1433.         if(com_level_sync())
  1434.             return;
  1435.     }
  1436. #endif
  1437.  
  1438.     Assert(Function_mode == FMODE_GAME);
  1439.  
  1440.     #ifndef NDEBUG
  1441.     mprintf((0, "Player_num = %d, N_players = %d.\n", Player_num, N_players)); // DEBUG
  1442.     #endif
  1443.  
  1444.     HUD_clear_messages();
  1445.  
  1446.     automap_clear_visited();
  1447.  
  1448.     #ifdef NETWORK
  1449.     if (Network_new_game == 1)
  1450.     {
  1451.         Network_new_game = 0;
  1452.         init_player_stats_new_ship();
  1453.     }
  1454.     #endif
  1455.     init_player_stats_level();
  1456.  
  1457. #ifndef SHAREWARE
  1458. #ifdef NETWORK
  1459.     if ((Game_mode & GM_MULTI_COOP) && Network_rejoined)
  1460.     {
  1461.         int i;
  1462.         for (i = 0; i < N_players; i++)
  1463.             Players[i].flags |= Netgame.player_flags[i];
  1464.     }
  1465. #endif
  1466. #endif
  1467.  
  1468.     Viewer = &Objects[Players[Player_num].objnum];
  1469.  
  1470. #ifdef NETWORK
  1471.     if (Game_mode & GM_MULTI)
  1472.     {
  1473.         multi_prep_level(); // Removes robots from level if necessary
  1474.     }
  1475. #endif
  1476.  
  1477.     gameseq_remove_unused_players();
  1478.  
  1479.     Game_suspended = 0;
  1480.  
  1481.     Fuelcen_control_center_destroyed = 0;
  1482.  
  1483.     init_cockpit();
  1484.     init_robots_for_level();
  1485.     init_ai_objects();
  1486.     init_morphs();
  1487.     init_all_matcens();
  1488.     reset_palette_add();
  1489.  
  1490.     if (!(Game_mode & GM_MULTI) && !Cheats_enabled)
  1491.         set_highest_level(Current_level_num);
  1492.  
  1493.     reset_special_effects();
  1494.  
  1495. #ifdef NETWORK
  1496.     if (Network_rejoined == 1)
  1497.     {
  1498.         #ifndef NDEBUG
  1499.         mprintf((0, "Restarting - joining in random location.\n"));
  1500.         #endif
  1501.         Network_rejoined = 0;
  1502.         StartLevel(1);
  1503.     }
  1504.     else
  1505. #endif
  1506.         StartLevel(0);        // Note link to above if!
  1507.  
  1508.     copy_defaults_to_robot_all();
  1509.     init_controlcen_for_level();
  1510.  
  1511.     //    Say player can use FLASH cheat to mark path to exit.
  1512.     Last_level_path_created = -1;
  1513. }
  1514.  
  1515. //called when the player is starting a new level for normal game model
  1516. StartNewLevel(int level_num)
  1517. {
  1518.     if (!(Game_mode & GM_MULTI)) {
  1519.         do_briefing_screens(level_num);
  1520.     }
  1521.     StartNewLevelSub(level_num, 1 );        
  1522.  
  1523. }
  1524.  
  1525. //initialize the player object position & orientation (at start of game, or new ship)
  1526. InitPlayerPosition(int random)
  1527. {
  1528.     int NewPlayer;
  1529.  
  1530.     if (! ((Game_mode & GM_MULTI) && !(Game_mode&GM_MULTI_COOP)) ) // If not deathmatch
  1531.         NewPlayer = Player_num;
  1532. #ifdef NETWORK
  1533.     else if (random == 1)
  1534.     {
  1535.         int i, closest = -1, trys=0;
  1536.         fix closest_dist = 0x7ffffff, dist;
  1537.  
  1538.         srand(clock());
  1539.  
  1540. #ifndef NDEBUG
  1541.         if (NumNetPlayerPositions != MAX_NUM_NET_PLAYERS)
  1542.         {
  1543.             mprintf((1, "WARNING: There are only %d start positions!\n"));
  1544.             //Int3();
  1545.         }
  1546. #endif
  1547.  
  1548.         do {
  1549.             if (trys > 0)    
  1550.             {
  1551.                 mprintf((0, "Can't start in location %d because its too close to player %d\n", NewPlayer, closest ));
  1552.             }
  1553.             trys++;
  1554.             NewPlayer = rand() % NumNetPlayerPositions;
  1555.  
  1556.             closest = -1;
  1557.             closest_dist = 0x7fffffff;
  1558.     
  1559.             for (i=0; i<N_players; i++ )    {
  1560.                 if ( (i!=Player_num) && (Objects[Players[i].objnum].type == OBJ_PLAYER) )    {
  1561.                     dist = find_connected_distance(&Objects[Players[i].objnum].pos, Objects[Players[i].objnum].segnum, &Player_init[NewPlayer].pos, Player_init[NewPlayer].segnum, 5, WID_FLY_FLAG );
  1562. //                    mprintf((0, "Distance from start location %d to player %d is %f.\n", NewPlayer, i, f2fl(dist)));
  1563.                     if ( (dist < closest_dist) && (dist >= 0) )    {
  1564.                         closest_dist = dist;
  1565.                         closest = i;
  1566.                     }
  1567.                 }
  1568.             }
  1569.             mprintf((0, "Closest from pos %d is %f to plr %d.\n", NewPlayer, f2fl(closest_dist), closest));
  1570.         } while ( (closest_dist<i2f(10*20)) && (trys<MAX_NUM_NET_PLAYERS*2) );
  1571.     } 
  1572. #endif
  1573.     else {
  1574.         mprintf((0, "Starting position is not being changed.\n"));
  1575.         goto done; // If deathmatch and not random, positions were already determined by sync packet
  1576.     }
  1577.     Assert(NewPlayer >= 0);
  1578.     Assert(NewPlayer < NumNetPlayerPositions);
  1579.  
  1580.     ConsoleObject->pos = Player_init[NewPlayer].pos;
  1581.     ConsoleObject->orient = Player_init[NewPlayer].orient;
  1582.  
  1583.     mprintf((0, "Re-starting in location %d of %d.\n", NewPlayer+1, NumNetPlayerPositions));
  1584.  
  1585.      obj_relink(ConsoleObject-Objects,Player_init[NewPlayer].segnum);
  1586.  
  1587. done:
  1588.     reset_player_object();
  1589.     reset_cruise();
  1590. }
  1591.  
  1592. //    -----------------------------------------------------------------------------------------------------
  1593. //    Initialize default parameters for one robot, copying from Robot_info to *objp.
  1594. //    What about setting size!?  Where does that come from?
  1595. void copy_defaults_to_robot(object *objp)
  1596. {
  1597.     robot_info    *robptr;
  1598.     int            objid;
  1599.  
  1600.     Assert(objp->type == OBJ_ROBOT);
  1601.     objid = objp->id;
  1602.     Assert(objid < N_robot_types);
  1603.  
  1604.     robptr = &Robot_info[objid];
  1605.  
  1606.     objp->shields = robptr->strength;
  1607.  
  1608. }
  1609.  
  1610. //    -----------------------------------------------------------------------------------------------------
  1611. //    Copy all values from the robot info structure to all instances of robots.
  1612. //    This allows us to change bitmaps.tbl and have these changes manifested in existing robots.
  1613. //    This function should be called at level load time.
  1614. void copy_defaults_to_robot_all(void)
  1615. {
  1616.     int    i;
  1617.  
  1618.     for (i=0; i<=Highest_object_index; i++)
  1619.         if (Objects[i].type == OBJ_ROBOT)
  1620.             copy_defaults_to_robot(&Objects[i]);
  1621. }
  1622.  
  1623. int    Do_appearance_effect=0;
  1624.  
  1625. extern int Rear_view;
  1626. extern void vr_reset_display();
  1627.  
  1628. //    -----------------------------------------------------------------------------------------------------
  1629. //called when the player is starting a level (new game or new ship)
  1630. StartLevel(int random)
  1631. {
  1632.     Assert(!Player_is_dead);
  1633.  
  1634.     InitPlayerPosition(random);
  1635.  
  1636.     verify_console_object();
  1637.  
  1638.     ConsoleObject->control_type    = CT_FLYING;
  1639.     ConsoleObject->movement_type    = MT_PHYSICS;
  1640.  
  1641.     disable_matcens();
  1642.  
  1643.     clear_transient_objects(0);        //0 means leave proximity bombs
  1644.  
  1645.     // create_player_appearance_effect(ConsoleObject);
  1646.     Do_appearance_effect = 1;
  1647.  
  1648. #ifdef NETWORK
  1649.     if (Game_mode & GM_MULTI)
  1650.     {
  1651. #ifndef SHAREWARE
  1652.         if (Game_mode & GM_MULTI_COOP)
  1653.             multi_send_score();
  1654. #endif
  1655.         multi_send_position(Players[Player_num].objnum);
  1656.          multi_send_reappear();
  1657.     }        
  1658.  
  1659.     if (Game_mode & GM_NETWORK)
  1660.         network_do_frame(1, 1);
  1661. #endif
  1662.  
  1663.     ai_reset_all_paths();
  1664.     ai_init_boss_for_ship();
  1665.     reset_time();
  1666.  
  1667.     reset_rear_view();
  1668.     Auto_fire_fusion_cannon_time = 0;
  1669.     Fusion_charge = 0;
  1670.  
  1671.     Robot_firing_enabled = 1;
  1672.  
  1673.     if (VR_screen_mode == SCREEN_MENU)
  1674.         vr_reset_display();
  1675. }
  1676.  
  1677.  
  1678. 
  1679.