home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / fuelcen.c < prev    next >
Text File  |  1998-06-08  |  47KB  |  1,329 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/fuelcen.c $
  15.  * $Revision: 2.3 $
  16.  * $Author: john $
  17.  * $Date: 1995/03/21 14:38:40 $
  18.  * 
  19.  * Functions for refueling centers.
  20.  * 
  21.  * $Log: fuelcen.c $
  22.  * Revision 2.3  1995/03/21  14:38:40  john
  23.  * Ifdef'd out the NETWORK code.
  24.  * 
  25.  * Revision 2.2  1995/03/06  15:23:09  john
  26.  * New screen techniques.
  27.  * 
  28.  * Revision 2.1  1995/02/27  13:13:26  john
  29.  * Removed floating point.
  30.  * 
  31.  * Revision 2.0  1995/02/27  11:27:20  john
  32.  * New version 2.0, which has no anonymous unions, builds with
  33.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  34.  * 
  35.  * Revision 1.159  1995/02/22  13:48:10  allender
  36.  * remove anonymous unions in object structure
  37.  * 
  38.  * Revision 1.158  1995/02/08  11:37:48  mike
  39.  * Check for failures in call to obj_create.
  40.  * 
  41.  * Revision 1.157  1995/02/07  20:39:39  mike
  42.  * fix toasters in multiplayer
  43.  * 
  44.  * 
  45.  * Revision 1.156  1995/02/02  18:40:10  john
  46.  * Fixed bug with full screen cockpit flashing non-white.
  47.  * 
  48.  * Revision 1.155  1995/01/28  15:27:22  yuan
  49.  * Make sure fuelcen nums are valid.
  50.  * 
  51.  * Revision 1.154  1995/01/03  14:26:23  rob
  52.  * Better ifdef for robot centers.
  53.  * 
  54.  * Revision 1.153  1995/01/03  11:27:49  rob
  55.  * Added include of fuelcen.c
  56.  * 
  57.  * Revision 1.152  1995/01/03  09:47:22  john
  58.  * Some ifdef SHAREWARE lines.
  59.  * 
  60.  * Revision 1.151  1995/01/02  21:02:07  rob
  61.  * added matcen support for coop/multirobot.
  62.  * 
  63.  * Revision 1.150  1994/12/15  18:31:22  mike
  64.  * fix confusing precedence problems.
  65.  * 
  66.  * Revision 1.149  1994/12/15  13:04:22  mike
  67.  * Replace Players[Player_num].time_total references with GameTime.
  68.  * 
  69.  * Revision 1.148  1994/12/15  03:05:18  matt
  70.  * Added error checking for NULL return from object_create_explosion()
  71.  * 
  72.  * Revision 1.147  1994/12/13  19:49:12  rob
  73.  * Made the fuelcen noise quieter.
  74.  * 
  75.  * Revision 1.146  1994/12/13  12:03:18  john
  76.  * Made the warning sirens not start until after "desccruction
  77.  * secquence activated voice".
  78.  * 
  79.  * Revision 1.145  1994/12/12  17:18:30  mike
  80.  * make warning siren louder.
  81.  * 
  82.  * Revision 1.144  1994/12/11  23:18:04  john
  83.  * Added -nomusic.
  84.  * Added RealFrameTime.
  85.  * Put in a pause when sound initialization error.
  86.  * Made controlcen countdown and framerate use RealFrameTime.
  87.  * 
  88.  * Revision 1.143  1994/12/11  14:10:16  mike
  89.  * louder sounds.
  90.  * 
  91.  * Revision 1.142  1994/12/06  11:33:19  yuan
  92.  * Fixed bug with fueling when above 100.
  93.  * 
  94.  * Revision 1.141  1994/12/05  23:37:14  matt
  95.  * Took out calls to warning() function
  96.  * 
  97.  * Revision 1.140  1994/12/05  23:19:18  yuan
  98.  * Fixed fuel center refuelers..
  99.  * 
  100.  * Revision 1.139  1994/12/03  12:48:12  mike
  101.  * diminish rocking due to control center destruction.
  102.  * 
  103.  * Revision 1.138  1994/12/02  23:30:32  mike
  104.  * fix bumpiness after toasting control center.
  105.  * 
  106.  * Revision 1.137  1994/12/02  22:48:14  mike
  107.  * rock the ship after toasting the control center!
  108.  * 
  109.  * Revision 1.136  1994/12/02  17:12:11  rob
  110.  * Fixed countdown sounds.
  111.  * 
  112.  * Revision 1.135  1994/11/29  20:59:43  rob
  113.  * Don't run out of fuel in net games (don't want to sync it between machines)
  114.  * 
  115.  * Revision 1.134  1994/11/29  19:10:57  john
  116.  * Took out debugging mprintf.
  117.  * 
  118.  * Revision 1.133  1994/11/29  13:19:40  john
  119.  * Made voice for "destruction actived in t-"
  120.  * be at 12.75 secs.
  121.  * 
  122.  * Revision 1.132  1994/11/29  12:19:46  john
  123.  * MAde the "Mine desctruction will commence"
  124.  * voice play at 12.5 secs.
  125.  * 
  126.  * Revision 1.131  1994/11/29  12:12:54  adam
  127.  * *** empty log message ***
  128.  * 
  129.  * Revision 1.130  1994/11/28  21:04:26  rob
  130.  * Added code to cast noise when player refuels.
  131.  * 
  132.  * Revision 1.129  1994/11/27  23:15:04  matt
  133.  * Made changes for new mprintf calling convention
  134.  * 
  135.  * Revision 1.128  1994/11/21  16:27:51  mike
  136.  * debug code for morphing.
  137.  * 
  138.  * Revision 1.127  1994/11/21  12:33:50  matt
  139.  * For control center explosions, use small fireball, not pseudo-random vclip
  140.  * 
  141.  * Revision 1.126  1994/11/20  22:12:15  mike
  142.  * Fix bug in initializing materialization centers.
  143.  * 
  144.  * Revision 1.125  1994/11/19  15:18:22  mike
  145.  * rip out unused code and data.
  146.  * 
  147.  * Revision 1.124  1994/11/08  12:18:59  mike
  148.  * Initialize Fuelcen_seconds_left.
  149.  * 
  150.  * Revision 1.123  1994/10/30  14:12:33  mike
  151.  * rip out repair center stuff
  152.  * 
  153.  * Revision 1.122  1994/10/28  14:42:45  john
  154.  * Added sound volumes to all sound calls.
  155.  * 
  156.  * Revision 1.121  1994/10/16  12:44:02  mike
  157.  * Make time to exit mine after control center destruction diff level dependent.
  158.  * 
  159.  * Revision 1.120  1994/10/09  22:03:26  mike
  160.  * Adapt to new create_n_segment_path parameters.
  161.  * 
  162.  * Revision 1.119  1994/10/06  14:52:42  mike
  163.  * Remove last of ability to damage fuel centers.
  164.  * 
  165.  * Revision 1.118  1994/10/06  14:08:45  matt
  166.  * Made morph flash effect get orientation from segment
  167.  * 
  168.  * Revision 1.117  1994/10/05  16:09:03  mike
  169.  * Put debugging code into matcen/fuelcen synchronization problem.
  170.  * 
  171.  * Revision 1.116  1994/10/04  15:32:41  john
  172.  * Took out the old PLAY_SOUND??? code and replaced it
  173.  * with direct calls into digi_link_??? so that all sounds
  174.  * can be made 3d.
  175.  * 
  176.  * Revision 1.115  1994/10/03  23:37:57  mike
  177.  * Clean up this mess of confusion to the point where maybe matcens actually work.
  178.  * 
  179.  * Revision 1.114  1994/10/03  13:34:40  matt
  180.  * Added new (and hopefully better) game sequencing functions
  181.  * 
  182.  * Revision 1.113  1994/09/30  14:41:57  matt
  183.  * Fixed bug as per Mike's instructions
  184.  * 
  185.  * Revision 1.112  1994/09/30  00:37:33  mike
  186.  * Balance materialization centers.
  187.  * 
  188.  * Revision 1.111  1994/09/28  23:12:52  matt
  189.  * Macroized palette flash system
  190.  * 
  191.  * Revision 1.110  1994/09/27  15:42:31  mike
  192.  * Add names of Specials.
  193.  * 
  194.  * Revision 1.109  1994/09/27  00:02:23  mike
  195.  * Yet more materialization center stuff.
  196.  * 
  197.  * Revision 1.108  1994/09/26  11:26:23  mike
  198.  * Balance materialization centers.
  199.  * 
  200.  * Revision 1.107  1994/09/25  23:40:47  matt
  201.  * Changed the object load & save code to read/write the structure fields one
  202.  * at a time (rather than the whole structure at once).  This mean that the
  203.  * object structure can be changed without breaking the load/save functions.
  204.  * As a result of this change, the local_object data can be and has been 
  205.  * incorporated into the object array.  Also, timeleft is now a property 
  206.  * of all objects, and the object structure has been otherwise cleaned up.
  207.  * 
  208.  * Revision 1.106  1994/09/25  15:55:58  mike
  209.  * Balance materialization centers, make them emit light, make them re-triggerable after awhile.
  210.  * 
  211.  * Revision 1.105  1994/09/24  17:42:33  mike
  212.  * Making materialization centers be activated by triggers and balancing them.
  213.  * 
  214.  * Revision 1.104  1994/09/24  14:16:06  mike
  215.  * Support new network constants.
  216.  * 
  217.  * Revision 1.103  1994/09/20  19:14:40  john
  218.  * Massaged the sound system; used a better formula for determining
  219.  * which l/r balance, also, put in Mike's stuff that searches for a connection
  220.  * between the 2 sounds' segments, stopping for closed doors, etc.
  221.  * 
  222.  * Revision 1.102  1994/09/17  01:40:51  matt
  223.  * Added status bar/sizable window mode, and in the process revamped the
  224.  * whole cockpit mode system.
  225.  * 
  226.  * Revision 1.101  1994/08/31  20:57:25  matt
  227.  * Cleaned up endlevel/death code
  228.  * 
  229.  * Revision 1.100  1994/08/30  17:54:20  mike
  230.  * Slow down rate of creation of objects by materialization centers.
  231.  * 
  232.  * Revision 1.99  1994/08/29  11:47:01  john
  233.  * Added warning if no control centers in mine.
  234.  * 
  235.  */
  236.  
  237.  
  238. #pragma off (unreferenced)
  239. static char rcsid[] = "$Id: fuelcen.c 2.3 1995/03/21 14:38:40 john Exp $";
  240. #pragma on (unreferenced)
  241.  
  242. #include <stdio.h>
  243. #include <stdlib.h>
  244. #include <math.h>
  245. #include <string.h>
  246.  
  247. #include "fuelcen.h"
  248. #include "gameseg.h"
  249. #include "game.h"        // For FrameTime
  250. #include "error.h"
  251. #include "mono.h"
  252. #include "gauges.h"
  253. #include "vclip.h"
  254. #include "fireball.h"
  255. #include "robot.h"
  256.  
  257. #include "wall.h"
  258. #include "sounds.h"
  259. #include "morph.h"
  260. #include "3d.h"
  261. #include "bm.h"
  262. #include "polyobj.h"
  263. #include "ai.h"
  264. #include "gamemine.h"
  265. #include "gamesave.h"
  266. #include "player.h"
  267. #include "collide.h"
  268. #include "laser.h"
  269. #include "network.h"
  270. #include "multi.h"
  271. #include "multibot.h"
  272.  
  273. // The max number of fuel stations per mine.
  274.  
  275. fix Fuelcen_refill_speed = i2f(1);
  276. fix Fuelcen_give_amount = i2f(25);
  277. fix Fuelcen_max_amount = i2f(100);
  278.  
  279. // Every time a robot is created in the morphing code, it decreases capacity of the morpher
  280. // by this amount... when capacity gets to 0, no more morphers...
  281. fix EnergyToCreateOneRobot = i2f(1);
  282.  
  283. int Fuelcen_control_center_destroyed = 0;
  284. int Fuelcen_seconds_left = 0;
  285.  
  286. #define MATCEN_HP_DEFAULT            F1_0*500; // Hitpoints
  287. #define MATCEN_INTERVAL_DEFAULT    F1_0*5;    //  5 seconds
  288.  
  289. matcen_info RobotCenters[MAX_ROBOT_CENTERS];
  290. int Num_robot_centers;
  291.  
  292. control_center_triggers ControlCenterTriggers;
  293.  
  294. FuelCenter Station[MAX_NUM_FUELCENS];
  295. int Num_fuelcenters = 0;
  296.  
  297. segment * PlayerSegment= NULL;
  298.  
  299. #ifdef EDITOR
  300. char    Special_names[MAX_CENTER_TYPES][11] = {
  301.     "NOTHING   ",
  302.     "FUELCEN   ",
  303.     "REPAIRCEN ",
  304.     "CONTROLCEN",
  305.     "ROBOTMAKER",
  306. };
  307. #endif
  308.  
  309. //------------------------------------------------------------
  310. // Resets all fuel center info
  311. void fuelcen_reset()
  312. {
  313.     int i;
  314.  
  315.     Num_fuelcenters = 0;
  316.     //mprintf( (0, "All fuel centers reset.\n"));
  317.  
  318.     for(i=0; i<MAX_SEGMENTS; i++ )
  319.         Segments[i].special = SEGMENT_IS_NOTHING;
  320.  
  321.     Fuelcen_control_center_destroyed = 0;
  322.     Num_robot_centers = 0;
  323.  
  324. }
  325.  
  326. #ifndef NDEBUG        //this is sometimes called by people from the debugger
  327. void reset_all_robot_centers() 
  328. {
  329.     int i;
  330.  
  331.     // Remove all materialization centers
  332.     for (i=0; i<Num_segments; i++)
  333.         if (Segments[i].special == SEGMENT_IS_ROBOTMAKER) {
  334.             Segments[i].special = SEGMENT_IS_NOTHING;
  335.             Segments[i].matcen_num = -1;
  336.         }
  337. }
  338. #endif
  339.  
  340. //------------------------------------------------------------
  341. // Turns a segment into a fully charged up fuel center...
  342. void fuelcen_create( segment * segp)
  343. {
  344.     int    station_type;
  345.  
  346.     station_type = segp->special;
  347.  
  348.     switch( station_type )    {
  349.     case SEGMENT_IS_NOTHING:
  350.         return;
  351.     case SEGMENT_IS_FUELCEN:
  352.     case SEGMENT_IS_REPAIRCEN:
  353.     case SEGMENT_IS_CONTROLCEN:
  354.     case SEGMENT_IS_ROBOTMAKER:
  355.         break;
  356.     default:
  357.         Error( "Invalid station type %d in fuelcen.c\n", station_type );
  358.     }
  359.  
  360.     Assert( (segp != NULL) );
  361.     if ( segp == NULL ) return;
  362.  
  363.     Assert( Num_fuelcenters < MAX_NUM_FUELCENS );
  364.     Assert( Num_fuelcenters > -1 );
  365.  
  366.     segp->value = Num_fuelcenters;
  367.     Station[Num_fuelcenters].Type = station_type;
  368.     Station[Num_fuelcenters].MaxCapacity = Fuelcen_max_amount;
  369.     Station[Num_fuelcenters].Capacity = Station[Num_fuelcenters].MaxCapacity;
  370.     Station[Num_fuelcenters].segnum = segp-Segments;
  371.     Station[Num_fuelcenters].Timer = -1;
  372.     Station[Num_fuelcenters].Flag = 0;
  373. //    Station[Num_fuelcenters].NextRobotType = -1;
  374. //    Station[Num_fuelcenters].last_created_obj=NULL;
  375. //    Station[Num_fuelcenters].last_created_sig = -1;
  376.     compute_segment_center(&Station[Num_fuelcenters].Center, segp );
  377.  
  378. //    if (station_type == SEGMENT_IS_ROBOTMAKER)
  379. //        Station[Num_fuelcenters].Capacity = i2f(Difficulty_level + 3);
  380.  
  381.     //mprintf( (0, "Segment %d is assigned to be fuel center %d.\n", Station[Num_fuelcenters].segnum, Num_fuelcenters ));
  382.     Num_fuelcenters++;
  383. }
  384.  
  385. //------------------------------------------------------------
  386. // Adds a matcen that already is a special type into the Station array.
  387. // This function is separate from other fuelcens because we don't want values reset.
  388. void matcen_create( segment * segp)
  389. {
  390.     int    station_type = segp->special;
  391.  
  392.     Assert( (segp != NULL) );
  393.     Assert(station_type == SEGMENT_IS_ROBOTMAKER);
  394.     if ( segp == NULL ) return;
  395.  
  396.     Assert( Num_fuelcenters < MAX_NUM_FUELCENS );
  397.     Assert( Num_fuelcenters > -1 );
  398.  
  399.     segp->value = Num_fuelcenters;
  400.     Station[Num_fuelcenters].Type = station_type;
  401.     Station[Num_fuelcenters].Capacity = i2f(Difficulty_level + 3);
  402.     Station[Num_fuelcenters].MaxCapacity = Station[Num_fuelcenters].Capacity;
  403.  
  404.     Station[Num_fuelcenters].segnum = segp-Segments;
  405.     Station[Num_fuelcenters].Timer = -1;
  406.     Station[Num_fuelcenters].Flag = 0;
  407. //    Station[Num_fuelcenters].NextRobotType = -1;
  408. //    Station[Num_fuelcenters].last_created_obj=NULL;
  409. //    Station[Num_fuelcenters].last_created_sig = -1;
  410.     compute_segment_center(&Station[Num_fuelcenters].Center, segp );
  411.  
  412.     segp->matcen_num = Num_robot_centers;
  413.     Num_robot_centers++;
  414.  
  415.     RobotCenters[segp->matcen_num].hit_points = MATCEN_HP_DEFAULT;
  416.     RobotCenters[segp->matcen_num].interval = MATCEN_INTERVAL_DEFAULT;
  417.     RobotCenters[segp->matcen_num].segnum = segp-Segments;
  418.     RobotCenters[segp->matcen_num].fuelcen_num = Num_fuelcenters;
  419.  
  420.     //mprintf( (0, "Segment %d is assigned to be fuel center %d.\n", Station[Num_fuelcenters].segnum, Num_fuelcenters ));
  421.     Num_fuelcenters++;
  422. }
  423.  
  424. //------------------------------------------------------------
  425. // Adds a segment that already is a special type into the Station array.
  426. void fuelcen_activate( segment * segp, int station_type )
  427. {
  428.     segp->special = station_type;
  429.  
  430.     if (segp->special == SEGMENT_IS_ROBOTMAKER)
  431.         matcen_create( segp);
  432.     else
  433.         fuelcen_create( segp);
  434.     
  435. }
  436.  
  437. //    The lower this number is, the more quickly the center can be re-triggered.
  438. //    If it's too low, it can mean all the robots won't be put out, but for about 5
  439. //    robots, that's not real likely.
  440. #define    MATCEN_LIFE (i2f(30-2*Difficulty_level))
  441.  
  442. //------------------------------------------------------------
  443. //    Trigger (enable) the materialization center in segment segnum
  444. void trigger_matcen(int segnum)
  445. {
  446.     segment        *segp = &Segments[segnum];
  447.     vms_vector    pos, delta;
  448.     FuelCenter    *robotcen;
  449.     int            objnum;
  450.  
  451.     mprintf((0, "Trigger matcen, segment %i\n", segnum));
  452.  
  453.     Assert(segp->special == SEGMENT_IS_ROBOTMAKER);
  454.     Assert(segp->matcen_num < Num_fuelcenters);
  455.     Assert((segp->matcen_num >= 0) && (segp->matcen_num <= Highest_segment_index));
  456.  
  457.     robotcen = &Station[RobotCenters[segp->matcen_num].fuelcen_num];
  458.  
  459.     if (robotcen->Enabled == 1)
  460.         return;
  461.  
  462.     if (!robotcen->Lives)
  463.         return;
  464.  
  465.     robotcen->Lives--;
  466.     robotcen->Timer = F1_0*1000;    //    Make sure the first robot gets emitted right away.
  467.     robotcen->Enabled = 1;            //    Say this center is enabled, it can create robots.
  468.     robotcen->Capacity = i2f(Difficulty_level + 3);
  469.     robotcen->Disable_time = MATCEN_LIFE;
  470.  
  471.     //    Create a bright object in the segment.
  472.     pos = robotcen->Center;
  473.     vm_vec_sub(&delta, &Vertices[Segments[segnum].verts[0]], &robotcen->Center);
  474.     vm_vec_scale_add2(&pos, &delta, F1_0/2);
  475.     objnum = obj_create( OBJ_LIGHT, 0, segnum, &pos, NULL, 0, CT_LIGHT, MT_NONE, RT_NONE );
  476.     if (objnum != -1) {
  477.         Objects[objnum].lifeleft = MATCEN_LIFE;
  478.         Objects[objnum].ctype.light_info.intensity = i2f(8);    //    Light cast by a fuelcen.
  479.     } else {
  480.         mprintf((1, "Can't create invisible flare for matcen.\n"));
  481.         Int3();
  482.     }
  483. //    mprintf((0, "Created invisibile flare, object=%i, segment=%i, pos=%7.3f %7.3f%7.3f\n", objnum, segnum, f2fl(pos.x), f2fl(pos.y), f2fl(pos.z)));
  484. }
  485.  
  486. #ifdef EDITOR
  487. //------------------------------------------------------------
  488. // Takes away a segment's fuel center properties.
  489. //    Deletes the segment point entry in the FuelCenter list.
  490. void fuelcen_delete( segment * segp )
  491. {
  492.     int i, j;
  493.  
  494. Restart: ;
  495.  
  496.     for (i=0; i<Num_fuelcenters; i++ )    {
  497.         if ( Station[i].segnum == segp-Segments )    {
  498.  
  499.             // If Robot maker is deleted, fix Segments and RobotCenters.
  500.             if (Station[i].Type == SEGMENT_IS_ROBOTMAKER) {
  501.                 Num_robot_centers--;
  502.  
  503.                 for (j=segp->matcen_num; j<Num_robot_centers; j++)
  504.                     RobotCenters[j] = RobotCenters[j+1];
  505.  
  506.                 for (j=0; j<Num_fuelcenters; j++) {
  507.                     if ( Station[j].Type == SEGMENT_IS_ROBOTMAKER )
  508.                         if ( Segments[Station[j].segnum].matcen_num > segp->matcen_num )
  509.                             Segments[Station[j].segnum].matcen_num--;
  510.                 }
  511.             }
  512.         
  513.             Num_fuelcenters--;
  514.             for (j=i; j<Num_fuelcenters; j++ )    {
  515.                 Station[i] = Station[i+1];
  516.                 Segments[Station[i].segnum].value = i;
  517.             }
  518.             segp->special = 0;
  519.             goto Restart;
  520.         }
  521.     }
  522.  
  523. }
  524. #endif
  525.  
  526. #define    ROBOT_GEN_TIME (i2f(5))
  527.  
  528. object * create_morph_robot( segment *segp, vms_vector *object_pos, int object_id)
  529. {
  530.     short        objnum;
  531.     object    *obj;
  532.     int        default_behavior;
  533.  
  534.     Players[Player_num].num_robots_level++;
  535.     Players[Player_num].num_robots_total++;
  536.  
  537.     objnum = obj_create(OBJ_ROBOT, object_id, segp-Segments, object_pos,
  538.                 &vmd_identity_matrix, Polygon_models[Robot_info[object_id].model_num].rad,
  539.                 CT_AI, MT_PHYSICS, RT_POLYOBJ);
  540.  
  541.     if ( objnum < 0 ) {
  542.         mprintf((1, "Can't create morph robot.  Aborting morph.\n"));
  543.         Int3();
  544.         return NULL;
  545.     }
  546.  
  547.     obj = &Objects[objnum];
  548.  
  549.     //Set polygon-object-specific data 
  550.  
  551.     obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
  552.     obj->rtype.pobj_info.subobj_flags = 0;
  553.  
  554.     //set Physics info
  555.  
  556.     obj->mtype.phys_info.mass = Robot_info[obj->id].mass;
  557.     obj->mtype.phys_info.drag = Robot_info[obj->id].drag;
  558.  
  559.     obj->mtype.phys_info.flags |= (PF_LEVELLING);
  560.  
  561.     obj->shields = Robot_info[obj->id].strength;
  562.     
  563.     default_behavior = AIB_NORMAL;
  564.     if (object_id == 10)                        //    This is a toaster guy!
  565.         default_behavior = AIB_RUN_FROM;
  566.  
  567.     init_ai_object(obj-Objects, default_behavior, -1 );        //    Note, -1 = segment this robot goes to to hide, should probably be something useful
  568.  
  569.     create_n_segment_path(obj, 6, -1);        //    Create a 6 segment path from creation point.
  570.  
  571.     if (default_behavior == AIB_RUN_FROM)
  572.         Ai_local_info[objnum].mode = AIM_RUN_FROM_OBJECT;
  573.  
  574.     return obj;
  575. }
  576.  
  577. int Num_extry_robots = 15;
  578.  
  579. #ifndef NDEBUG
  580. int    FrameCount_last_msg = 0;
  581. #endif
  582.  
  583. //    ----------------------------------------------------------------------------------------------------------
  584. void robotmaker_proc( FuelCenter * robotcen )
  585. {
  586.     fix        dist_to_player;
  587.     vms_vector    cur_object_loc; //, direction;
  588.     int        matcen_num, segnum, objnum;
  589.     object    *obj;
  590.     fix        top_time;
  591.     vms_vector    direction;
  592.  
  593.     if (robotcen->Enabled == 0)
  594.         return;
  595.  
  596.     if (robotcen->Disable_time > 0) {
  597.         robotcen->Disable_time -= FrameTime;
  598.         if (robotcen->Disable_time <= 0) {
  599.             mprintf((0, "Robot center #%i gets disabled due to time running out.\n", robotcen-Station));
  600.             robotcen->Enabled = 0;
  601.         }
  602.     }
  603.  
  604.     // mprintf((0, "Capacity of robot maker #%i is %i\n", robotcen - Station, robotcen->Capacity));
  605.  
  606.     //    No robot making in multiplayer mode.
  607. #ifdef NETWORK
  608. #ifndef SHAREWARE
  609.     if ((Game_mode & GM_MULTI) && (!(Game_mode & GM_MULTI_ROBOTS) || !network_i_am_master()))
  610.         return;
  611. #else
  612.     if (Game_mode & GM_MULTI)
  613.         return;
  614. #endif
  615. #endif
  616.  
  617.     // Wait until transmorgafier has capacity to make a robot...
  618.     if ( robotcen->Capacity <= 0 ) {
  619.         return;
  620.     }
  621.  
  622.     matcen_num = Segments[robotcen->segnum].matcen_num;
  623.     //mprintf((0, "Robotmaker #%i flags = %8x\n", matcen_num, RobotCenters[matcen_num].robot_flags));
  624.  
  625.     if ( matcen_num == -1 ) {
  626.         mprintf((0, "Non-functional robotcen at %d\n", robotcen->segnum));
  627.         return;
  628.     }
  629.  
  630.     if (RobotCenters[matcen_num].robot_flags == 0) {
  631.         //mprintf((0, "robot_flags = 0 at robot maker #%i\n", RobotCenters[matcen_num].robot_flags));
  632.         return;
  633.     }
  634.  
  635.     // Wait until we have a free slot for this puppy...
  636.    //      <<<<<<<<<<<<<<<< Num robots in mine >>>>>>>>>>>>>>>>>>>>>>>>>>    <<<<<<<<<<<< Max robots in mine >>>>>>>>>>>>>>>
  637.     if ( (Players[Player_num].num_robots_level - Players[Player_num].num_kills_level) >= (Gamesave_num_org_robots + Num_extry_robots ) ) {
  638.         #ifndef NDEBUG
  639.         if (FrameCount > FrameCount_last_msg + 20) {
  640.             mprintf((0, "Cannot morph until you kill one!\n"));
  641.             FrameCount_last_msg = FrameCount;
  642.         }
  643.         #endif
  644.         return;
  645.     }
  646.  
  647.     robotcen->Timer += FrameTime;
  648.  
  649.     switch( robotcen->Flag )    {
  650.     case 0:        // Wait until next robot can generate
  651.         if (Game_mode & GM_MULTI) 
  652.         {
  653.             top_time = ROBOT_GEN_TIME;    
  654.         }
  655.         else 
  656.         {
  657.             dist_to_player = vm_vec_dist_quick( &ConsoleObject->pos, &robotcen->Center );
  658.             top_time = dist_to_player/64 + rand() * 2 + F1_0*2;
  659.             if ( top_time > ROBOT_GEN_TIME )
  660.                 top_time = ROBOT_GEN_TIME + rand();
  661.             if ( top_time < F1_0*2 )
  662.                 top_time = F1_0*3/2 + rand()*2;
  663.         }
  664.  
  665.          // mprintf( (0, "Time between morphs %d seconds, dist_to_player = %7.3f\n", f2i(top_time), f2fl(dist_to_player) ));
  666.  
  667.         if (robotcen->Timer > top_time )    {
  668.             int    count=0;
  669.             int    i, my_station_num = robotcen-Station;
  670.             object *obj;
  671.  
  672.             //    Make sure this robotmaker hasn't put out its max without having any of them killed.
  673.             for (i=0; i<=Highest_object_index; i++)
  674.                 if (Objects[i].type == OBJ_ROBOT)
  675.                     if ((Objects[i].matcen_creator^0x80) == my_station_num)
  676.                         count++;
  677.             if (count > Difficulty_level + 3) {
  678.                 mprintf((0, "Cannot morph: center %i has already put out %i robots.\n", my_station_num, count));
  679.                 robotcen->Timer /= 2;
  680.                 return;
  681.             }
  682.  
  683.             //    Whack on any robot or player in the matcen segment.
  684.             count=0;
  685.             segnum = robotcen->segnum;
  686.             for (objnum=Segments[segnum].objects;objnum!=-1;objnum=Objects[objnum].next)    {
  687.                 count++;
  688.                 if ( count > MAX_OBJECTS )    {
  689.                     mprintf((0, "Object list in segment %d is circular.", segnum ));
  690.                     Int3();
  691.                     return;
  692.                 }
  693.                 if (Objects[objnum].type==OBJ_ROBOT) {
  694.                     collide_robot_and_materialization_center(&Objects[objnum]);
  695.                     robotcen->Timer = top_time/2;
  696.                     return;
  697.                 } else if (Objects[objnum].type==OBJ_PLAYER ) {
  698.                     collide_player_and_materialization_center(&Objects[objnum]);
  699.                     robotcen->Timer = top_time/2;
  700.                     return;
  701.                 }
  702.             }
  703.  
  704.             compute_segment_center(&cur_object_loc, &Segments[robotcen->segnum]);
  705.             // HACK!!! The 10 under here should be something equal to the 1/2 the size of the segment.
  706.             obj = object_create_explosion(robotcen->segnum, &cur_object_loc, i2f(10), VCLIP_MORPHING_ROBOT );
  707.  
  708.             if (obj)
  709.                 extract_orient_from_segment(&obj->orient,&Segments[robotcen->segnum]);
  710.  
  711.             if ( Vclip[VCLIP_MORPHING_ROBOT].sound_num > -1 )        {
  712.                 digi_link_sound_to_pos( Vclip[VCLIP_MORPHING_ROBOT].sound_num, robotcen->segnum, 0, &cur_object_loc, 0, F1_0 );
  713.             }
  714.             robotcen->Flag    = 1;
  715.             robotcen->Timer = 0;
  716.  
  717.         }
  718.         break;
  719.     case 1:            // Wait until 1/2 second after VCLIP started.
  720.         if (robotcen->Timer > (Vclip[VCLIP_MORPHING_ROBOT].play_time/2) )    {
  721.  
  722.             robotcen->Capacity -= EnergyToCreateOneRobot;
  723.             robotcen->Flag = 0;
  724.  
  725.             robotcen->Timer = 0;
  726.             compute_segment_center(&cur_object_loc, &Segments[robotcen->segnum]);
  727.  
  728.             // If this is the first materialization, set to valid robot.
  729.             if (RobotCenters[matcen_num].robot_flags != 0) {
  730.                 int    type;
  731.                 uint    flags;
  732.                 byte    legal_types[32];        //    32 bits in a word, the width of robot_flags.
  733.                 int    num_types, robot_index;
  734.  
  735.                 robot_index = 0;
  736.                 num_types = 0;
  737.                 flags = RobotCenters[matcen_num].robot_flags;
  738.                 while (flags) {
  739.                     if (flags & 1)
  740.                         legal_types[num_types++] = robot_index;
  741.                     flags >>= 1;
  742.                     robot_index++;
  743.                 }
  744.  
  745.                 //mprintf((0, "Flags = %08x, %2i legal types to morph: \n", RobotCenters[matcen_num].robot_flags, num_types));
  746.                 //for (i=0; i<num_types; i++)
  747.                 //    mprintf((0, "%2i ", legal_types[i]));
  748.                 //mprintf((0, "\n"));
  749.  
  750.                 if (num_types == 1)
  751.                     type = legal_types[0];
  752.                 else
  753.                     type = legal_types[(rand() * num_types) / 32768];
  754.  
  755.                 mprintf((0, "Morph: (type = %i) (seg = %i) (capacity = %08x)\n", type, robotcen->segnum, robotcen->Capacity));
  756.                 obj = create_morph_robot(&Segments[robotcen->segnum], &cur_object_loc, type );
  757.                 if (obj != NULL) {
  758. #ifndef SHAREWARE
  759. #ifdef NETWORK
  760.                     if (Game_mode & GM_MULTI)
  761.                         multi_send_create_robot(robotcen-Station, obj-Objects, type);
  762. #endif
  763. #endif
  764.                     obj->matcen_creator = robotcen-Station | 0x80;
  765.  
  766.                     // Make object faces player...
  767.                     vm_vec_sub( &direction, &ConsoleObject->pos,&obj->pos );
  768.                     vm_vector_2_matrix( &obj->orient, &direction, &obj->orient.uvec, NULL);
  769.     
  770.                     morph_start( obj );
  771.                     //robotcen->last_created_obj = obj;
  772.                     //robotcen->last_created_sig = robotcen->last_created_obj->signature;
  773.                 } else
  774.                     mprintf((0, "Warning: create_morph_robot returned NULL (no objects left?)\n"));
  775.  
  776.             }
  777.   
  778.         }
  779.         break;
  780.     default:
  781.         robotcen->Flag = 0;
  782.         robotcen->Timer = 0;
  783.     }
  784. }
  785.  
  786. #define    BASE_CONTROL_CENTER_EXPLOSION_TIME    30
  787. #define    DIFF_CONTROL_CENTER_EXPLOSION_TIME    (BASE_CONTROL_CENTER_EXPLOSION_TIME + (NDL-Difficulty_level-1)*5)
  788.  
  789. #define COUNTDOWN_VOICE_TIME (i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME)-fl2f(12.75))
  790.  
  791. void controlcen_proc( FuelCenter * controlcen )
  792. {
  793.     fix old_time;
  794.     int    fc;
  795.  
  796. //    mprintf( (0, "CCT: %.1f\n", f2fl(controlcen->Timer)));
  797.  
  798.     if (!Fuelcen_control_center_destroyed)    return;
  799.  
  800.     //    Control center destroyed, rock the player's ship.
  801.     fc = Fuelcen_seconds_left;
  802.     if (fc > 16)
  803.         fc = 16;
  804.     ConsoleObject->mtype.phys_info.rotvel.x += fixmul(rand() - 16384, 3*F1_0/16 + (F1_0*(16-fc))/32);
  805.     ConsoleObject->mtype.phys_info.rotvel.z += fixmul(rand() - 16384, 3*F1_0/16 + (F1_0*(16-fc))/32);
  806.     //    Hook in the rumble sound effect here.
  807.  
  808.     old_time = controlcen->Timer;
  809.     controlcen->Timer += RealFrameTime;            //timer_get_approx_seconds
  810.     Fuelcen_seconds_left = DIFF_CONTROL_CENTER_EXPLOSION_TIME - f2i(controlcen->Timer);
  811.     if ( (old_time < COUNTDOWN_VOICE_TIME ) && (controlcen->Timer >= COUNTDOWN_VOICE_TIME) )    {
  812.             digi_play_sample( SOUND_COUNTDOWN_13_SECS, F3_0 );
  813.     }
  814.     if ( f2i(old_time) != f2i(controlcen->Timer) )    {
  815.         if ( (Fuelcen_seconds_left>=0) && (Fuelcen_seconds_left<10) ) 
  816.             digi_play_sample( SOUND_COUNTDOWN_0_SECS+Fuelcen_seconds_left, F3_0 );
  817.         if ( Fuelcen_seconds_left==DIFF_CONTROL_CENTER_EXPLOSION_TIME-1)
  818.             digi_play_sample( SOUND_COUNTDOWN_29_SECS, F3_0 );
  819.     }                        
  820.  
  821.     if (controlcen->Timer < i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME)) {
  822.         vms_vector vp;    //,v,c;
  823.         fix size;
  824.         compute_segment_center(&vp, &Segments[controlcen->segnum]);
  825.         size = (0x50000*f2i(controlcen->Timer)*(FrameTime & 0xF))/16;
  826.         size = controlcen->Timer / (fl2f(0.65));
  827.         old_time = old_time / (fl2f(0.65));
  828.         if (size != old_time && (controlcen->Timer > (5*F1_0) ))        {            // Every 2 seconds!
  829.             //@@object_create_explosion( controlcen->segnum, &vp, size*10, FrameTime & 7);
  830.             object_create_explosion( controlcen->segnum, &vp, size*10, VCLIP_SMALL_EXPLOSION);
  831.             digi_play_sample( SOUND_CONTROL_CENTER_WARNING_SIREN, F3_0 );
  832.         }
  833.     }  else {
  834.         int flash_value;
  835.  
  836.         if (old_time < i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME))
  837.             digi_play_sample( SOUND_MINE_BLEW_UP, F1_0 );
  838.  
  839.         flash_value = f2i( (controlcen->Timer-i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME))*(64/4));    // 4 seconds to total whiteness
  840.         PALETTE_FLASH_SET(flash_value,flash_value,flash_value);
  841.  
  842.         //gauge_message( "YOU'RE TOO SLOW! THE MINE BLEW UP!" );
  843.         if (PaletteBlueAdd > 64 )    {
  844.             gr_set_current_canvas( NULL );        
  845.             gr_clear_canvas(BM_XRGB(31,31,31));        //make screen all white to match palette effect
  846.             reset_cockpit();                                //force cockpit redraw next time
  847.             reset_palette_add();                            //restore palette for death message
  848.             controlcen->Timer = -1;
  849.             controlcen->MaxCapacity = Fuelcen_max_amount;
  850.             //gauge_message( "Control Center Reset" );
  851.             DoPlayerDead();        //kill_player();
  852.         }                                                                                
  853.     }
  854. }
  855.  
  856. #define M_PI 3.14159
  857.  
  858. //-------------------------------------------------------------
  859. // Called once per frame, replenishes fuel supply.
  860. void fuelcen_update_all()
  861. {
  862.     int i;
  863.     fix AmountToreplenish;
  864.     
  865.     AmountToreplenish = fixmul(FrameTime,Fuelcen_refill_speed);
  866.  
  867.     for (i=0; i<Num_fuelcenters; i++ )    {
  868.         if ( Station[i].Type == SEGMENT_IS_ROBOTMAKER )    {
  869.             if (! (Game_suspended & SUSP_ROBOTS))
  870.                 robotmaker_proc( &Station[i] );
  871.         } else if ( Station[i].Type == SEGMENT_IS_CONTROLCEN )    {
  872.             controlcen_proc( &Station[i] );
  873.     
  874.         } else if ( (Station[i].MaxCapacity > 0) && (PlayerSegment!=&Segments[Station[i].segnum]) )    {
  875.             if ( Station[i].Capacity < Station[i].MaxCapacity )    {
  876.                  Station[i].Capacity += AmountToreplenish;
  877.                 //mprintf( (0, "Fuel center %d replenished to %d.\n", i, f2i(Station[i].Capacity) ));
  878.                 if ( Station[i].Capacity >= Station[i].MaxCapacity )        {
  879.                     Station[i].Capacity = Station[i].MaxCapacity;
  880.                     //gauge_message( "Fuel center is fully recharged!    " );
  881.                 }
  882.             }
  883.         }
  884.     }
  885. }
  886.  
  887. //--unused-- //-------------------------------------------------------------
  888. //--unused-- // replenishes all fuel supplies.
  889. //--unused-- void fuelcen_replenish_all()
  890. //--unused-- {
  891. //--unused--     int i;
  892. //--unused-- 
  893. //--unused--     for (i=0; i<Num_fuelcenters; i++ )    {
  894. //--unused--         Station[i].Capacity = Station[i].MaxCapacity;
  895. //--unused--     }
  896. //--unused--     //mprintf( (0, "All fuel centers are replenished\n" ));
  897. //--unused-- 
  898. //--unused-- }
  899.  
  900. //-------------------------------------------------------------
  901. fix fuelcen_give_fuel(segment *segp, fix MaxAmountCanTake )
  902. {
  903.     Assert( segp != NULL );
  904.  
  905.     PlayerSegment = segp;
  906.  
  907.     if ( (segp) && (segp->special==SEGMENT_IS_FUELCEN) )    {
  908.         fix amount;
  909.  
  910. //        if (Station[segp->value].MaxCapacity<=0)    {
  911. //            HUD_init_message( "Fuelcenter %d is destroyed.", segp->value );
  912. //            return 0;
  913. //        }
  914.  
  915. //        if (Station[segp->value].Capacity<=0)    {
  916. //            HUD_init_message( "Fuelcenter %d is empty.", segp->value );
  917. //            return 0;
  918. //        }
  919.  
  920.         if (MaxAmountCanTake <= 0 )    {
  921. //            //gauge_message( "Fueled up!");
  922.             return 0;
  923.         }
  924.  
  925.         amount = fixmul(FrameTime,Fuelcen_give_amount);
  926.  
  927.         if (amount > MaxAmountCanTake )
  928.             amount = MaxAmountCanTake;
  929.  
  930. //        if (!(Game_mode & GM_MULTI))
  931. //            if ( Station[segp->value].Capacity < amount  )    {
  932. //                amount = Station[segp->value].Capacity;
  933. //                Station[segp->value].Capacity = 0;
  934. //            } else {
  935. //                Station[segp->value].Capacity -= amount;
  936. //            }
  937.  
  938.         digi_play_sample( SOUND_REFUEL_STATION_GIVING_FUEL, F1_0/2 );
  939.  
  940.         #ifdef NETWORK
  941.         if (Game_mode & GM_MULTI)
  942.             multi_send_play_sound(SOUND_REFUEL_STATION_GIVING_FUEL, F1_0/2);
  943.         #endif
  944.  
  945.         //HUD_init_message( "Fuelcen %d has %d/%d fuel", segp->value,f2i(Station[segp->value].Capacity),f2i(Station[segp->value].MaxCapacity) );
  946.         return amount;
  947.  
  948.     } else {
  949.         return 0;
  950.     }
  951. }
  952.  
  953. //--unused-- //-----------------------------------------------------------
  954. //--unused-- // Damages a fuel center
  955. //--unused-- void fuelcen_damage(segment *segp, fix damage )
  956. //--unused-- {
  957. //--unused--     //int i;
  958. //--unused--     // int    station_num = segp->value;
  959. //--unused-- 
  960. //--unused--     Assert( segp != NULL );
  961. //--unused--     if ( segp == NULL ) return;
  962. //--unused-- 
  963. //--unused--     mprintf((0, "Obsolete function fuelcen_damage() called with seg=%i, damage=%7.3f\n", segp-Segments, f2fl(damage)));
  964. //--unused--     switch( segp->special )    {
  965. //--unused--     case SEGMENT_IS_NOTHING:
  966. //--unused--         return;
  967. //--unused--     case SEGMENT_IS_ROBOTMAKER:
  968. //--unused-- //--        // Robotmaker hit by laser
  969. //--unused-- //--        if (Station[station_num].MaxCapacity<=0 )    {
  970. //--unused-- //--            // Shooting a already destroyed materializer
  971. //--unused-- //--        } else {
  972. //--unused-- //--            Station[station_num].MaxCapacity -= damage;
  973. //--unused-- //--            if (Station[station_num].Capacity > Station[station_num].MaxCapacity )    {
  974. //--unused-- //--                Station[station_num].Capacity = Station[station_num].MaxCapacity;
  975. //--unused-- //--            }
  976. //--unused-- //--            if (Station[station_num].MaxCapacity <= 0 )    {
  977. //--unused-- //--                Station[station_num].MaxCapacity = 0;
  978. //--unused-- //--                // Robotmaker dead
  979. //--unused-- //--                for (i=0; i<6; i++ )
  980. //--unused-- //--                    segp->sides[i].tmap_num2 = 0;
  981. //--unused-- //--            }
  982. //--unused-- //--        }
  983. //--unused-- //--        //mprintf( (0, "Materializatormografier has %x capacity left\n", Station[station_num].MaxCapacity ));
  984. //--unused--         break;
  985. //--unused--     case SEGMENT_IS_FUELCEN:    
  986. //--unused-- //--        digi_play_sample( SOUND_REFUEL_STATION_HIT );
  987. //--unused-- //--        if (Station[station_num].MaxCapacity>0 )    {
  988. //--unused-- //--            Station[station_num].MaxCapacity -= damage;
  989. //--unused-- //--            if (Station[station_num].Capacity > Station[station_num].MaxCapacity )    {
  990. //--unused-- //--                Station[station_num].Capacity = Station[station_num].MaxCapacity;
  991. //--unused-- //--            }
  992. //--unused-- //--            if (Station[station_num].MaxCapacity <= 0 )    {
  993. //--unused-- //--                Station[station_num].MaxCapacity = 0;
  994. //--unused-- //--                digi_play_sample( SOUND_REFUEL_STATION_DESTROYED );
  995. //--unused-- //--            }
  996. //--unused-- //--        } else {
  997. //--unused-- //--            Station[station_num].MaxCapacity = 0;
  998. //--unused-- //--        }
  999. //--unused-- //--        HUD_init_message( "Fuelcenter %d damaged", station_num );
  1000. //--unused--         break;
  1001. //--unused--     case SEGMENT_IS_REPAIRCEN:
  1002. //--unused--         break;
  1003. //--unused--     case SEGMENT_IS_CONTROLCEN:
  1004. //--unused--         break;
  1005. //--unused--     default:
  1006. //--unused--         Error( "Invalid type in fuelcen.c" );
  1007. //--unused--     }
  1008. //--unused-- }
  1009.  
  1010. //--unused-- //    ----------------------------------------------------------------------------------------------------------
  1011. //--unused-- fixang my_delta_ang(fixang a,fixang b)
  1012. //--unused-- {
  1013. //--unused--     fixang delta0,delta1;
  1014. //--unused-- 
  1015. //--unused--     return (abs(delta0 = a - b) < abs(delta1 = b - a)) ? delta0 : delta1;
  1016. //--unused-- 
  1017. //--unused-- }
  1018.  
  1019. //--unused-- //    ----------------------------------------------------------------------------------------------------------
  1020. //--unused-- //return though which side of seg0 is seg1
  1021. //--unused-- int john_find_connect_side(int seg0,int seg1)
  1022. //--unused-- {
  1023. //--unused--     segment *Seg=&Segments[seg0];
  1024. //--unused--     int i;
  1025. //--unused-- 
  1026. //--unused--     for (i=MAX_SIDES_PER_SEGMENT;i--;) if (Seg->children[i]==seg1) return i;
  1027. //--unused-- 
  1028. //--unused--     return -1;
  1029. //--unused-- }
  1030.  
  1031. //    ----------------------------------------------------------------------------------------------------------
  1032. //--unused-- vms_angvec start_angles, delta_angles, goal_angles;
  1033. //--unused-- vms_vector start_pos, delta_pos, goal_pos;
  1034. //--unused-- int FuelStationSeg;
  1035. //--unused-- fix current_time,delta_time;
  1036. //--unused-- int next_side, side_index;
  1037. //--unused-- int * sidelist;
  1038.  
  1039. //--repair-- int Repairing;
  1040. //--repair-- vms_vector repair_save_uvec;        //the player's upvec when enter repaircen
  1041. //--repair-- object *RepairObj=NULL;        //which object getting repaired
  1042. //--repair-- int disable_repair_center=0;
  1043. //--repair-- fix repair_rate;
  1044. //--repair-- #define FULL_REPAIR_RATE i2f(10)
  1045.  
  1046. //--unused-- ubyte save_control_type,save_movement_type;
  1047.  
  1048. //--unused-- int SideOrderBack[] = {WFRONT, WRIGHT, WTOP, WLEFT, WBOTTOM, WBACK};
  1049. //--unused-- int SideOrderFront[] =  {WBACK, WLEFT, WTOP, WRIGHT, WBOTTOM, WFRONT};
  1050. //--unused-- int SideOrderLeft[] =  { WRIGHT, WBACK, WTOP, WFRONT, WBOTTOM, WLEFT };
  1051. //--unused-- int SideOrderRight[] =  { WLEFT, WFRONT, WTOP, WBACK, WBOTTOM, WRIGHT };
  1052. //--unused-- int SideOrderTop[] =  { WBOTTOM, WLEFT, WBACK, WRIGHT, WFRONT, WTOP };
  1053. //--unused-- int SideOrderBottom[] =  { WTOP, WLEFT, WFRONT, WRIGHT, WBACK, WBOTTOM };
  1054.  
  1055. //--unused-- int SideUpVector[] = {WBOTTOM, WFRONT, WBOTTOM, WFRONT, WBOTTOM, WBOTTOM };
  1056.  
  1057. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1058. //--repair-- void refuel_calc_deltas(object *obj, int next_side, int repair_seg)
  1059. //--repair-- {
  1060. //--repair--     vms_vector nextcenter, headfvec, *headuvec;
  1061. //--repair--     vms_matrix goal_orient;
  1062. //--repair-- 
  1063. //--repair--     // Find time for this movement
  1064. //--repair--     delta_time = F1_0;        // one second...
  1065. //--repair--         
  1066. //--repair--     // Find start and goal position
  1067. //--repair--     start_pos = obj->pos;
  1068. //--repair--     
  1069. //--repair--     // Find delta position to get to goal position
  1070. //--repair--     compute_segment_center(&goal_pos,&Segments[repair_seg]);
  1071. //--repair--     vm_vec_sub( &delta_pos,&goal_pos,&start_pos);
  1072. //--repair--     
  1073. //--repair--     // Find start angles
  1074. //--repair--     //angles_from_vector(&start_angles,&obj->orient.fvec);
  1075. //--repair--     vm_extract_angles_matrix(&start_angles,&obj->orient);
  1076. //--repair--     
  1077. //--repair--     // Find delta angles to get to goal orientation
  1078. //--repair--     med_compute_center_point_on_side(&nextcenter,&Segments[repair_seg],next_side);
  1079. //--repair--     vm_vec_sub(&headfvec,&nextcenter,&goal_pos);
  1080. //--repair--     //mprintf( (0, "Next_side = %d, Head fvec = %d,%d,%d\n", next_side, headfvec.x, headfvec.y, headfvec.z ));
  1081. //--repair-- 
  1082. //--repair--     if (next_side == 5)                        //last side
  1083. //--repair--         headuvec = &repair_save_uvec;
  1084. //--repair--     else
  1085. //--repair--         headuvec = &Segments[repair_seg].sides[SideUpVector[next_side]].normals[0];
  1086. //--repair-- 
  1087. //--repair--     vm_vector_2_matrix(&goal_orient,&headfvec,headuvec,NULL);
  1088. //--repair--     vm_extract_angles_matrix(&goal_angles,&goal_orient);
  1089. //--repair--     delta_angles.p = my_delta_ang(start_angles.p,goal_angles.p);
  1090. //--repair--     delta_angles.b = my_delta_ang(start_angles.b,goal_angles.b);
  1091. //--repair--     delta_angles.h = my_delta_ang(start_angles.h,goal_angles.h);
  1092. //--repair--     current_time = 0;
  1093. //--repair--     Repairing = 0;
  1094. //--repair-- }
  1095. //--repair-- 
  1096. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1097. //--repair-- //if repairing, cut it short
  1098. //--repair-- abort_repair_center()
  1099. //--repair-- {
  1100. //--repair--     if (!RepairObj || side_index==5)
  1101. //--repair--         return;
  1102. //--repair-- 
  1103. //--repair--     current_time = 0;
  1104. //--repair--     side_index = 5;
  1105. //--repair--     next_side = sidelist[side_index];
  1106. //--repair--     refuel_calc_deltas(RepairObj, next_side, FuelStationSeg);
  1107. //--repair-- }
  1108. //--repair-- 
  1109. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1110. //--repair-- void repair_ship_damage()
  1111. //--repair-- {
  1112. //--repair--      //mprintf((0,"Repairing ship damage\n"));
  1113. //--repair-- }
  1114. //--repair-- 
  1115. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1116. //--repair-- int refuel_do_repair_effect( object * obj, int first_time, int repair_seg )    {
  1117. //--repair-- 
  1118. //--repair--     obj->mtype.phys_info.velocity.x = 0;                
  1119. //--repair--     obj->mtype.phys_info.velocity.y = 0;                
  1120. //--repair--     obj->mtype.phys_info.velocity.z = 0;                
  1121. //--repair-- 
  1122. //--repair--     if (first_time)    {
  1123. //--repair--         int entry_side;
  1124. //--repair--         current_time = 0;
  1125. //--repair-- 
  1126. //--repair--         digi_play_sample( SOUND_REPAIR_STATION_PLAYER_ENTERING, F1_0 );
  1127. //--repair-- 
  1128. //--repair--         entry_side = john_find_connect_side(repair_seg,obj->segnum );
  1129. //--repair--         Assert( entry_side > -1 );
  1130. //--repair-- 
  1131. //--repair--         switch( entry_side )    {
  1132. //--repair--         case WBACK: sidelist = SideOrderBack; break;
  1133. //--repair--         case WFRONT: sidelist = SideOrderFront; break;
  1134. //--repair--         case WLEFT: sidelist = SideOrderLeft; break;
  1135. //--repair--         case WRIGHT: sidelist = SideOrderRight; break;
  1136. //--repair--         case WTOP: sidelist = SideOrderTop; break;
  1137. //--repair--         case WBOTTOM: sidelist = SideOrderBottom; break;
  1138. //--repair--         }
  1139. //--repair--         side_index = 0;
  1140. //--repair--         next_side = sidelist[side_index];
  1141. //--repair-- 
  1142. //--repair--         refuel_calc_deltas(obj,next_side, repair_seg);
  1143. //--repair--     } 
  1144. //--repair-- 
  1145. //--repair--     //update shields
  1146. //--repair--     if (Players[Player_num].shields < MAX_SHIELDS) {    //if above max, don't mess with it
  1147. //--repair-- 
  1148. //--repair--         Players[Player_num].shields += fixmul(FrameTime,repair_rate);
  1149. //--repair-- 
  1150. //--repair--         if (Players[Player_num].shields > MAX_SHIELDS)
  1151. //--repair--             Players[Player_num].shields = MAX_SHIELDS;
  1152. //--repair--     }
  1153. //--repair-- 
  1154. //--repair--     current_time += FrameTime;
  1155. //--repair-- 
  1156. //--repair--     if (current_time >= delta_time )    {
  1157. //--repair--         vms_angvec av;
  1158. //--repair--         obj->pos = goal_pos;
  1159. //--repair--         av    = goal_angles;
  1160. //--repair--         vm_angles_2_matrix(&obj->orient,&av);
  1161. //--repair-- 
  1162. //--repair--         if (side_index >= 5 )    
  1163. //--repair--             return 1;        // Done being repaired...
  1164. //--repair-- 
  1165. //--repair--         if (Repairing==0)        {
  1166. //--repair--             //mprintf( (0, "<MACHINE EFFECT ON SIDE %d>\n", next_side ));
  1167. //--repair--             //digi_play_sample( SOUND_REPAIR_STATION_FIXING );
  1168. //--repair--             Repairing=1;
  1169. //--repair-- 
  1170. //--repair--             switch( next_side )    {
  1171. //--repair--             case 0:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_1,F1_0 ); break;
  1172. //--repair--             case 1:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_2,F1_0 ); break;
  1173. //--repair--             case 2:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_3,F1_0 ); break;
  1174. //--repair--             case 3:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_4,F1_0 ); break;
  1175. //--repair--             case 4:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_1,F1_0 ); break;
  1176. //--repair--             case 5:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_2,F1_0 ); break;
  1177. //--repair--             }
  1178. //--repair--         
  1179. //--repair--             repair_ship_damage();
  1180. //--repair-- 
  1181. //--repair--         }
  1182. //--repair-- 
  1183. //--repair--         if (current_time >= (delta_time+(F1_0/2)) )    {
  1184. //--repair--             current_time = 0;
  1185. //--repair--             // Find next side...
  1186. //--repair--             side_index++;
  1187. //--repair--             if (side_index >= 6 ) return 1;
  1188. //--repair--             next_side = sidelist[side_index];
  1189. //--repair--     
  1190. //--repair--             refuel_calc_deltas(obj, next_side, repair_seg);
  1191. //--repair--         }
  1192. //--repair-- 
  1193. //--repair--     } else {
  1194. //--repair--         fix factor, p,b,h;    
  1195. //--repair--         vms_angvec av;
  1196. //--repair-- 
  1197. //--repair--         factor = fixdiv( current_time,delta_time );
  1198. //--repair-- 
  1199. //--repair--         // Find object's current position
  1200. //--repair--         obj->pos = delta_pos;
  1201. //--repair--         vm_vec_scale( &obj->pos, factor );
  1202. //--repair--         vm_vec_add2( &obj->pos, &start_pos );
  1203. //--repair--             
  1204. //--repair--         // Find object's current orientation
  1205. //--repair--         p    = fixmul(delta_angles.p,factor);
  1206. //--repair--         b    = fixmul(delta_angles.b,factor);
  1207. //--repair--         h    = fixmul(delta_angles.h,factor);
  1208. //--repair--         av.p = (fixang)p + start_angles.p;
  1209. //--repair--         av.b = (fixang)b + start_angles.b;
  1210. //--repair--         av.h = (fixang)h + start_angles.h;
  1211. //--repair--         vm_angles_2_matrix(&obj->orient,&av);
  1212. //--repair-- 
  1213. //--repair--     }
  1214. //--repair-- 
  1215. //--repair--     update_object_seg(obj);        //update segment
  1216. //--repair-- 
  1217. //--repair--     return 0;
  1218. //--repair-- }
  1219. //--repair-- 
  1220. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1221. //--repair-- //do the repair center for this frame
  1222. //--repair-- void do_repair_sequence(object *obj)
  1223. //--repair-- {
  1224. //--repair--     Assert(obj == RepairObj);
  1225. //--repair-- 
  1226. //--repair--     if (refuel_do_repair_effect( obj, 0, FuelStationSeg )) {
  1227. //--repair--         if (Players[Player_num].shields < MAX_SHIELDS)
  1228. //--repair--             Players[Player_num].shields = MAX_SHIELDS;
  1229. //--repair--         obj->control_type = save_control_type;
  1230. //--repair--         obj->movement_type = save_movement_type;
  1231. //--repair--         disable_repair_center=1;
  1232. //--repair--         RepairObj = NULL;
  1233. //--repair-- 
  1234. //--repair-- 
  1235. //--repair--         //the two lines below will spit the player out of the rapair center,
  1236. //--repair--         //but what happen is that the ship just bangs into the door
  1237. //--repair--         //if (obj->movement_type == MT_PHYSICS)
  1238. //--repair--         //    vm_vec_copy_scale(&obj->mtype.phys_info.velocity,&obj->orient.fvec,i2f(200));
  1239. //--repair--     }
  1240. //--repair-- 
  1241. //--repair-- }
  1242. //--repair-- 
  1243. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1244. //--repair-- //see if we should start the repair center
  1245. //--repair-- void check_start_repair_center(object *obj)
  1246. //--repair-- {
  1247. //--repair--     if (RepairObj != NULL) return;        //already in repair center
  1248. //--repair-- 
  1249. //--repair--     if (Lsegments[obj->segnum].special_type & SS_REPAIR_CENTER) {
  1250. //--repair-- 
  1251. //--repair--         if (!disable_repair_center) {
  1252. //--repair--             //have just entered repair center
  1253. //--repair-- 
  1254. //--repair--             RepairObj = obj;
  1255. //--repair--             repair_save_uvec = obj->orient.uvec;
  1256. //--repair-- 
  1257. //--repair--             repair_rate = fixmuldiv(FULL_REPAIR_RATE,(MAX_SHIELDS - Players[Player_num].shields),MAX_SHIELDS);
  1258. //--repair-- 
  1259. //--repair--             save_control_type = obj->control_type;
  1260. //--repair--             save_movement_type = obj->movement_type;
  1261. //--repair-- 
  1262. //--repair--             obj->control_type = CT_REPAIRCEN;
  1263. //--repair--             obj->movement_type = MT_NONE;
  1264. //--repair-- 
  1265. //--repair--             FuelStationSeg    = Lsegments[obj->segnum].special_segment;
  1266. //--repair--             Assert(FuelStationSeg != -1);
  1267. //--repair-- 
  1268. //--repair--             if (refuel_do_repair_effect( obj, 1, FuelStationSeg )) {
  1269. //--repair--                 Int3();        //can this happen?
  1270. //--repair--                 obj->control_type = CT_FLYING;
  1271. //--repair--                 obj->movement_type = MT_PHYSICS;
  1272. //--repair--             }
  1273. //--repair--         }
  1274. //--repair--     }
  1275. //--repair--     else
  1276. //--repair--         disable_repair_center=0;
  1277. //--repair-- 
  1278. //--repair-- }
  1279.  
  1280. //    --------------------------------------------------------------------------------------------
  1281. void disable_matcens(void)
  1282. {
  1283.     int    i;
  1284.  
  1285.     for (i=0; i<Num_robot_centers; i++) {
  1286.         Station[i].Enabled = 0;
  1287.         Station[i].Disable_time = 0;
  1288.     }
  1289. }
  1290.  
  1291. //    --------------------------------------------------------------------------------------------
  1292. //    Initialize all materialization centers.
  1293. //    Give them all the right number of lives.
  1294. void init_all_matcens(void)
  1295. {
  1296.     int    i;
  1297.  
  1298.     for (i=0; i<Num_fuelcenters; i++)
  1299.         if (Station[i].Type == SEGMENT_IS_ROBOTMAKER) {
  1300.             Station[i].Lives = 3;
  1301.             Station[i].Enabled = 0;
  1302.             Station[i].Disable_time = 0;
  1303. #ifndef NDEBUG
  1304. {
  1305.             //    Make sure this fuelcen is pointed at by a matcen.
  1306.             int    j;
  1307.             for (j=0; j<Num_robot_centers; j++) {
  1308.                 if (RobotCenters[j].fuelcen_num == i)
  1309.                     break;
  1310.             }
  1311.             Assert(j != Num_robot_centers);
  1312. }
  1313. #endif
  1314.  
  1315.         }
  1316.  
  1317. #ifndef NDEBUG
  1318.     //    Make sure all matcens point at a fuelcen
  1319.     for (i=0; i<Num_robot_centers; i++) {
  1320.         int    fuelcen_num = RobotCenters[i].fuelcen_num;
  1321.  
  1322.         Assert(fuelcen_num < Num_fuelcenters);
  1323.         Assert(Station[fuelcen_num].Type == SEGMENT_IS_ROBOTMAKER);
  1324.     }
  1325. #endif
  1326.  
  1327. }
  1328. 
  1329.