home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / physics.c < prev    next >
Text File  |  1998-06-08  |  38KB  |  1,285 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/physics.c $
  15.  * $Revision: 2.2 $
  16.  * $Author: john $
  17.  * $Date: 1995/03/24 14:48:54 $
  18.  * 
  19.  * Code for flying through the mines
  20.  * 
  21.  * $Log: physics.c $
  22.  * Revision 2.2  1995/03/24  14:48:54  john
  23.  * Added cheat for player to go thru walls.
  24.  * 
  25.  * Revision 2.1  1995/03/20  18:15:59  john
  26.  * Added code to not store the normals in the segment structure.
  27.  * 
  28.  * Revision 2.0  1995/02/27  11:32:06  john
  29.  * New version 2.0, which has no anonymous unions, builds with
  30.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  31.  * 
  32.  * Revision 1.213  1995/02/22  13:40:48  allender
  33.  * remove anonymous unions from object structure
  34.  * 
  35.  * Revision 1.212  1995/02/22  13:24:42  john
  36.  * Removed the vecmat anonymous unions.
  37.  * 
  38.  * Revision 1.211  1995/02/06  19:46:59  matt
  39.  * New function (untested), set_thrust_from_velocity()
  40.  * 
  41.  * Revision 1.210  1995/02/02  16:26:12  matt
  42.  * Changed assert that was causing a problem
  43.  * 
  44.  * Revision 1.209  1995/02/02  14:07:00  matt
  45.  * Fixed confusion about which segment you are touching when you're 
  46.  * touching a wall.  This manifested itself in spurious lava burns.
  47.  * 
  48.  * Revision 1.208  1995/02/01  21:03:24  john
  49.  * Lintified.
  50.  * 
  51.  * Revision 1.207  1995/01/25  13:53:35  rob
  52.  * Removed an Int3 from multiplayer games.
  53.  * 
  54.  * Revision 1.206  1995/01/23  17:30:47  rob
  55.  * Removed Int3 on bogus sim time.
  56.  * 
  57.  * Revision 1.205  1995/01/17  11:08:56  matt
  58.  * Disable new-ish FVI edge checking for all objects except the player,
  59.  * since it was causing problems with the fusion cannon.
  60.  * 
  61.  * Revision 1.204  1995/01/05  09:43:49  matt
  62.  * Took out int3s from new code
  63.  * 
  64.  * Revision 1.203  1995/01/04  22:19:23  matt
  65.  * Added hack to keep player from squeezing through closed walls/doors
  66.  * 
  67.  * Revision 1.202  1995/01/02  12:38:48  mike
  68.  * physics hack to crazy josh not get hung up on proximity bombs.  Matt notified via email.
  69.  * 
  70.  * Revision 1.201  1994/12/13  15:39:22  mike
  71.  * #ifndef NDEBUG some code.
  72.  * 
  73.  * Revision 1.200  1994/12/13  13:28:34  yuan
  74.  * Fixed type.
  75.  * 
  76.  * Revision 1.199  1994/12/13  13:25:00  matt
  77.  * Made bump hack compile out if so desired
  78.  * 
  79.  * Revision 1.198  1994/12/13  12:02:39  matt
  80.  * Added hack to bump player a little if stuck
  81.  * 
  82.  * Revision 1.197  1994/12/12  00:32:23  matt
  83.  * When objects other than player go out of mine, jerk to center of segment
  84.  * 
  85.  * Revision 1.196  1994/12/10  22:52:42  mike
  86.  * make physics left-the-mine checking always be in.
  87.  * 
  88.  * Revision 1.195  1994/12/08  00:53:01  mike
  89.  * oops...phys rot bug.
  90.  * 
  91.  * Revision 1.194  1994/12/07  12:54:54  mike
  92.  * tweak rotvel applied from collisions.
  93.  * 
  94.  * Revision 1.193  1994/12/07  00:36:08  mike
  95.  * fix phys_apply_rot for robots -- ai was bashing effect in next frame.
  96.  * 
  97.  * Revision 1.192  1994/12/05  17:23:10  matt
  98.  * Made a bunch of debug code compile out
  99.  * 
  100.  * Revision 1.191  1994/12/05  16:30:10  matt
  101.  * Was illegally changing an object's segment...shoot me.
  102.  * 
  103.  * Revision 1.190  1994/12/05  11:58:51  mike
  104.  * fix stupid apply_force_rot() bug.
  105.  * 
  106.  * Revision 1.189  1994/12/05  09:42:17  mike
  107.  * fix 0 mag problem when object applies force to itself.
  108.  * 
  109.  * Revision 1.188  1994/12/04  22:48:40  matt
  110.  * Physics & FVI now only build seglist for player objects, and they 
  111.  * responsilby deal with buffer full conditions
  112.  * 
  113.  * Revision 1.187  1994/12/04  22:14:07  mike
  114.  * apply instantaneous rotation to an object due to a force blow.
  115.  * 
  116.  * Revision 1.186  1994/12/04  18:51:30  matt
  117.  * When weapons get stuck, delete them!
  118.  * 
  119.  * Revision 1.185  1994/12/04  18:38:56  matt
  120.  * Added better handling of point-not-in-seg problem
  121.  * 
  122.  * Revision 1.184  1994/11/27  23:13:42  matt
  123.  * Made changes for new mprintf calling convention
  124.  * 
  125.  * Revision 1.183  1994/11/25  23:46:18  matt
  126.  * Fixed drag problems with framerates over 60Hz
  127.  * 
  128.  * Revision 1.182  1994/11/25  22:15:52  matt
  129.  * Added asserts to try to trap frametime < 0 bug
  130.  * 
  131.  * Revision 1.181  1994/11/21  11:42:44  mike
  132.  * ndebug stuff.
  133.  * 
  134.  * Revision 1.180  1994/11/19  15:15:04  mike
  135.  * remove unused code and data
  136.  * 
  137.  * Revision 1.179  1994/11/16  11:25:22  matt
  138.  * Abort physics if negative frametime
  139.  * 
  140.  * Revision 1.178  1994/10/05  19:50:41  rob
  141.  * Removed a non-critical Int3 where an object's segnum is checked.
  142.  * Left mprintf message.
  143.  * 
  144.  * Revision 1.177  1994/10/03  22:57:50  matt
  145.  * Fixed problem with matrix corruption of non-moving (but rotating) objects
  146.  * 
  147.  * Revision 1.176  1994/09/28  09:23:28  mike
  148.  * Add useful information to mprintf(1,... error messages.
  149.  * 
  150.  * Revision 1.175  1994/09/21  17:16:54  mike
  151.  * Make objects stuck in doors go away when door opens.
  152.  * 
  153.  * Revision 1.174  1994/09/12  14:19:06  matt
  154.  * Drag & thrust now handled differently
  155.  * 
  156.  * Revision 1.173  1994/09/09  14:21:12  matt
  157.  * Use new thrust flag
  158.  * 
  159.  * Revision 1.172  1994/09/08  16:21:57  matt
  160.  * Cleaned up player-hit-wall code, and added object scrape handling
  161.  * Also added weapon-on-weapon hit sound
  162.  * 
  163.  * Revision 1.171  1994/09/02  12:30:37  matt
  164.  * Fixed weapons which go through objects
  165.  * 
  166.  * Revision 1.170  1994/09/02  11:55:14  mike
  167.  * Kill redefinition of a constant which is properly defined in object.h
  168.  * 
  169.  * Revision 1.169  1994/09/02  11:35:01  matt
  170.  * Fixed typo
  171.  * 
  172.  * Revision 1.168  1994/09/02  11:32:48  matt
  173.  * Fixed object/object collisions, so you can't fly through robots anymore.
  174.  * Cleaned up object damage system.
  175.  * 
  176.  * Revision 1.167  1994/08/30  21:58:15  matt
  177.  * Made phys_apply_force() do nothing to an object if it's not a phys object
  178.  * 
  179.  * Revision 1.166  1994/08/26  10:47:01  john
  180.  * New version of controls.
  181.  * 
  182.  * Revision 1.165  1994/08/25  21:53:57  mike
  183.  * Prevent counts of -1 which eventually add up to a positive number in do_ai_frame, causing
  184.  * the too-many-retries behavior.
  185.  * 
  186.  * Revision 1.164  1994/08/25  18:43:33  john
  187.  * First revision of new control code.
  188.  * 
  189.  * Revision 1.163  1994/08/17  22:18:05  mike
  190.  * Make robots which have rotvel or rotthrust, but not movement, move.
  191.  * 
  192.  * Revision 1.162  1994/08/13  17:31:18  mike
  193.  * retry count stuff.
  194.  * 
  195.  * Revision 1.161  1994/08/11  18:59:16  mike
  196.  * *** empty log message ***
  197.  * 
  198.  * Revision 1.160  1994/08/10  19:53:47  mike
  199.  * Debug code (which is still in...)
  200.  * and adapt to changed interface to create_path_to_player.
  201.  * 
  202.  * Revision 1.159  1994/08/08  21:38:43  matt
  203.  * Cleaned up a code a little and optimized a little
  204.  * 
  205.  * Revision 1.158  1994/08/08  15:21:50  mike
  206.  * Trap retry count >= 4, but don't do AI hack unless >= 6.
  207.  * 
  208.  * Revision 1.157  1994/08/08  11:47:15  matt
  209.  * Cleaned up fvi and physics a little
  210.  * 
  211.  * Revision 1.156  1994/08/05  10:10:10  yuan
  212.  * Commented out debug stuff that was killing framerate.
  213.  * 
  214.  * Revision 1.155  1994/08/04  19:12:36  matt
  215.  * Changed a bunch of vecmat calls to use multiple-function routines, and to
  216.  * allow the use of C macros for some functions
  217.  * 
  218.  * Revision 1.154  1994/08/04  16:33:57  mike
  219.  * Kill a pile of RCS stuff.
  220.  * Call create_path_to_player for a stuck object.
  221.  * 
  222.  * Revision 1.153  1994/08/04  00:21:02  matt
  223.  * Cleaned up fvi & physics error handling; put in code to make sure objects
  224.  * are in correct segment; simplified segment finding for objects and points
  225.  * 
  226.  * Revision 1.152  1994/08/01  16:25:34  matt
  227.  * Check for moved_time == 0 when computing hit speed
  228.  * 
  229.  * Revision 1.151  1994/08/01  13:30:32  matt
  230.  * Made fvi() check holes in transparent walls, and changed fvi() calling
  231.  * parms to take all input data in query structure.
  232.  * 
  233.  * Revision 1.150  1994/07/29  23:41:46  matt
  234.  * Fixed turn banking, which changed when I added rotational velocity
  235.  * 
  236.  * Revision 1.149  1994/07/27  20:53:23  matt
  237.  * Added rotational drag & thrust, so turning now has momemtum like moving
  238.  * 
  239.  */
  240.  
  241. #pragma off (unreferenced)
  242. static char rcsid[] = "$Id: physics.c 2.2 1995/03/24 14:48:54 john Exp $";
  243. #pragma on (unreferenced)
  244.  
  245. //@@#include <malloc.h>
  246. #include <stdio.h>
  247. #include <stdlib.h>
  248.  
  249. #include "joy.h"
  250. #include "mono.h"
  251. #include "error.h"
  252.  
  253. #include "inferno.h"
  254. #include "segment.h"
  255. #include "object.h"
  256. #include "physics.h"
  257. #include "key.h"
  258. #include "game.h"
  259. #include "collide.h"
  260. #include "fvi.h"
  261. #include "newdemo.h"
  262. #include "timer.h"
  263. #include "ai.h"
  264. #include "wall.h"
  265. #include "laser.h"
  266.  
  267. //Global variables for physics system
  268.  
  269. #define ROLL_RATE         0x2000
  270. #define DAMP_ANG             0x400                  //min angle to bank
  271.  
  272. #define TURNROLL_SCALE    (0x4ec4/2)
  273.  
  274. #define BUMP_HACK    1        //if defined, bump player when he gets stuck
  275.  
  276. //--unused-- int mike_mode=0;
  277.  
  278. //check point against each side of segment. return bitmask, where bit
  279. //set means behind that side
  280.  
  281. int Physics_cheat_flag = 0;
  282.  
  283. //##//returns the distance of a point (checkp) from a plane (defined by norm & planep) 
  284. //##fix dist_to_plane(vms_vector *checkp,vms_vector *norm,vms_vector *planep)
  285. //##{
  286. //##    vms_vector deltap;
  287. //##
  288. //##    vm_vec_sub(&deltap,checkp,planep);
  289. //##
  290. //##    return vm_vec_dot(&deltap,norm);
  291. //##}
  292.  
  293. //--unused-- int dpjm_old_joy_x, dpjm_old_joy_y;
  294.  
  295. int floor_levelling=0;
  296.  
  297. //--unused-- level_with_floor()
  298. //--unused-- {
  299. //--unused--     floor_levelling=1;
  300. //--unused-- }
  301.  
  302. //make sure matrix is orthogonal
  303. check_and_fix_matrix(vms_matrix *m)
  304. {
  305.     vms_matrix tempm;
  306.  
  307.     vm_vector_2_matrix(&tempm,&m->fvec,&m->uvec,NULL);
  308.     *m  = tempm;
  309. }
  310.  
  311.  
  312. void do_physics_align_object( object * obj )
  313. {
  314.     vms_vector desired_upvec;
  315.     fixang delta_ang,roll_ang;
  316.     //vms_vector forvec = {0,0,f1_0};
  317.     vms_matrix temp_matrix;
  318.     fix d,largest_d=-f1_0;
  319.     int i,best_side;
  320.  
  321.  
  322.     // bank player according to segment orientation
  323.  
  324.     //find side of segment that player is most alligned with
  325.  
  326.     for (i=0;i<6;i++) {
  327.         #ifdef COMPACT_SEGS
  328.             vms_vector _tv1;
  329.             get_side_normal( &Segments[obj->segnum], i, 0, &_tv1 );
  330.             d = vm_vec_dot(&_tv1,&obj->orient.uvec);
  331.         #else                    
  332.             d = vm_vec_dot(&Segments[obj->segnum].sides[i].normals[0],&obj->orient.uvec);
  333.         #endif
  334.  
  335.         if (d > largest_d) {largest_d = d; best_side=i;}
  336.     }
  337.  
  338.     if (floor_levelling) {
  339.  
  340.         // old way: used floor's normal as upvec
  341.         #ifdef COMPACT_SEGS
  342.             get_side_normal(&Segments[obj->segnum], 3, 0, &desired_upvec );            
  343.         #else
  344.             desired_upvec = Segments[obj->segnum].sides[3].normals[0];
  345.         #endif
  346.  
  347.     }
  348.     else  // new player leveling code: use normal of side closest to our up vec
  349.         if (get_num_faces(&Segments[obj->segnum].sides[best_side])==2) {
  350.             #ifdef COMPACT_SEGS
  351.                 vms_vector normals[2];
  352.                 get_side_normals(&Segments[obj->segnum], best_side, &normals[0], &normals[1] );            
  353.  
  354.                 desired_upvec.x = (normals[0].x + normals[1].x) / 2;
  355.                 desired_upvec.y = (normals[0].y + normals[1].y) / 2;
  356.                 desired_upvec.z = (normals[0].z + normals[1].z) / 2;
  357.  
  358.                 vm_vec_normalize(&desired_upvec);
  359.             #else
  360.                 side *s = &Segments[obj->segnum].sides[best_side];
  361.                 desired_upvec.x = (s->normals[0].x + s->normals[1].x) / 2;
  362.                 desired_upvec.y = (s->normals[0].y + s->normals[1].y) / 2;
  363.                 desired_upvec.z = (s->normals[0].z + s->normals[1].z) / 2;
  364.         
  365.                 vm_vec_normalize(&desired_upvec);
  366.             #endif
  367.         }
  368.         else
  369.             #ifdef COMPACT_SEGS
  370.                 get_side_normal(&Segments[obj->segnum], best_side, 0, &desired_upvec );            
  371.             #else
  372.                 desired_upvec = Segments[obj->segnum].sides[best_side].normals[0];
  373.             #endif
  374.  
  375.     if (labs(vm_vec_dot(&desired_upvec,&obj->orient.fvec)) < f1_0/2) {
  376.         fixang save_delta_ang;
  377.         vms_angvec tangles;
  378.         
  379.         vm_vector_2_matrix(&temp_matrix,&obj->orient.fvec,&desired_upvec,NULL);
  380.  
  381.         save_delta_ang = delta_ang = vm_vec_delta_ang(&obj->orient.uvec,&temp_matrix.uvec,&obj->orient.fvec);
  382.  
  383.         delta_ang += obj->mtype.phys_info.turnroll;
  384.  
  385.         if (abs(delta_ang) > DAMP_ANG) {
  386.             vms_matrix rotmat, new_pm;
  387.  
  388.             roll_ang = fixmul(FrameTime,ROLL_RATE);
  389.  
  390.             if (abs(delta_ang) < roll_ang) roll_ang = delta_ang;
  391.             else if (delta_ang<0) roll_ang = -roll_ang;
  392.  
  393.             tangles.p = tangles.h = 0;  tangles.b = roll_ang;
  394.             vm_angles_2_matrix(&rotmat,&tangles);
  395.  
  396.             vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat);
  397.             obj->orient = new_pm;
  398.         }
  399.         else floor_levelling=0;
  400.     }
  401.  
  402. }
  403.  
  404. set_object_turnroll(object *obj)
  405. {
  406.     fixang desired_bank;
  407.  
  408.     desired_bank = -fixmul(obj->mtype.phys_info.rotvel.y,TURNROLL_SCALE);
  409.  
  410.     if (obj->mtype.phys_info.turnroll != desired_bank) {
  411.         fixang delta_ang,max_roll;
  412.  
  413.         max_roll = fixmul(ROLL_RATE,FrameTime);
  414.  
  415.         delta_ang = desired_bank - obj->mtype.phys_info.turnroll;
  416.  
  417.         if (labs(delta_ang) < max_roll)
  418.             max_roll = delta_ang;
  419.         else
  420.             if (delta_ang < 0)
  421.                 max_roll = -max_roll;
  422.  
  423.         obj->mtype.phys_info.turnroll += max_roll;
  424.     }
  425.  
  426. }
  427.  
  428. //list of segments went through
  429. int phys_seglist[MAX_FVI_SEGS],n_phys_segs;
  430.  
  431.  
  432. #define MAX_IGNORE_OBJS 100
  433.  
  434. #ifndef NDEBUG
  435. #define EXTRA_DEBUG 1        //no extra debug when NDEBUG is on
  436. #endif
  437.  
  438. #ifdef EXTRA_DEBUG
  439. object *debug_obj=NULL;
  440. #endif
  441.  
  442. #define XYZ(v) (v)->x,(v)->y,(v)->z
  443.  
  444. int    Total_retries=0, Total_sims=0;
  445.  
  446. #ifndef NDEBUG
  447. int    Dont_move_ai_objects=0;
  448. #endif
  449.  
  450. #define FT (f1_0/64)
  451.  
  452. extern int disable_new_fvi_stuff;
  453. //    -----------------------------------------------------------------------------------------------------------
  454. // add rotational velocity & acceleration
  455. void do_physics_sim_rot(object *obj)
  456. {
  457.     vms_angvec    tangles;
  458.     vms_matrix    rotmat,new_orient;
  459.     //fix            rotdrag_scale;
  460.     physics_info *pi;
  461.  
  462.     Assert(FrameTime > 0);    //Get MATT if hit this!
  463.  
  464.     pi = &obj->mtype.phys_info;
  465.  
  466.     if (!(pi->rotvel.x || pi->rotvel.y || pi->rotvel.z || pi->rotthrust.x || pi->rotthrust.y || pi->rotthrust.z))
  467.         return;
  468.  
  469.     if (obj->mtype.phys_info.drag) {
  470.         int count;
  471.         vms_vector accel;
  472.         fix drag,r,k;
  473.  
  474.         count = FrameTime / FT;
  475.         r = FrameTime % FT;
  476.         k = fixdiv(r,FT);
  477.  
  478.         drag = (obj->mtype.phys_info.drag*5)/2;
  479.  
  480.         if (obj->mtype.phys_info.flags & PF_USES_THRUST) {
  481.  
  482.             vm_vec_copy_scale(&accel,&obj->mtype.phys_info.rotthrust,fixdiv(f1_0,obj->mtype.phys_info.mass));
  483.  
  484.             while (count--) {
  485.  
  486.                 vm_vec_add2(&obj->mtype.phys_info.rotvel,&accel);
  487.  
  488.                 vm_vec_scale(&obj->mtype.phys_info.rotvel,f1_0-drag);
  489.             }
  490.  
  491.             //do linear scale on remaining bit of time
  492.  
  493.             vm_vec_scale_add2(&obj->mtype.phys_info.rotvel,&accel,k);
  494.             vm_vec_scale(&obj->mtype.phys_info.rotvel,f1_0-fixmul(k,drag));
  495.         }
  496.         else {
  497.             fix total_drag=f1_0;
  498.  
  499.             while (count--)
  500.                 total_drag = fixmul(total_drag,f1_0-drag);
  501.  
  502.             //do linear scale on remaining bit of time
  503.  
  504.             total_drag = fixmul(total_drag,f1_0-fixmul(k,drag));
  505.  
  506.             vm_vec_scale(&obj->mtype.phys_info.rotvel,total_drag);
  507.         }
  508.  
  509.     }
  510.  
  511.     //mprintf( (0, "Rot vel = %.3f,%.3f,%.3f\n", f2fl(obj->mtype.phys_info.rotvel.x),f2fl(obj->mtype.phys_info.rotvel.y), f2fl(obj->mtype.phys_info.rotvel.z) ));
  512.  
  513.     //now rotate object 
  514.  
  515.     //unrotate object for bank caused by turn
  516.     if (obj->mtype.phys_info.turnroll) {
  517.         vms_matrix new_pm;
  518.  
  519.         tangles.p = tangles.h = 0;
  520.         tangles.b = -obj->mtype.phys_info.turnroll;
  521.         vm_angles_2_matrix(&rotmat,&tangles);
  522.         vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat);
  523.         obj->orient = new_pm;
  524.     }
  525.   
  526.     tangles.p = fixmul(obj->mtype.phys_info.rotvel.x,FrameTime);
  527.     tangles.h = fixmul(obj->mtype.phys_info.rotvel.y,FrameTime);
  528.     tangles.b  = fixmul(obj->mtype.phys_info.rotvel.z,FrameTime);
  529.  
  530.     vm_angles_2_matrix(&rotmat,&tangles);
  531.     vm_matrix_x_matrix(&new_orient,&obj->orient,&rotmat);
  532.     obj->orient = new_orient;
  533.  
  534.     if (obj->mtype.phys_info.flags & PF_TURNROLL)
  535.         set_object_turnroll(obj);
  536.  
  537.     //re-rotate object for bank caused by turn
  538.     if (obj->mtype.phys_info.turnroll) {
  539.         vms_matrix new_pm;
  540.  
  541.         tangles.p = tangles.h = 0;
  542.         tangles.b = obj->mtype.phys_info.turnroll;
  543.         vm_angles_2_matrix(&rotmat,&tangles);
  544.         vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat);
  545.         obj->orient = new_pm;
  546.     }
  547.  
  548.     check_and_fix_matrix(&obj->orient);
  549. }
  550.  
  551. //    -----------------------------------------------------------------------------------------------------------
  552. //Simulate a physics object for this frame
  553. do_physics_sim(object *obj)
  554. {
  555.     int ignore_obj_list[MAX_IGNORE_OBJS],n_ignore_objs;
  556.     int iseg;
  557.     int try_again;
  558.     int fate;
  559.     vms_vector frame_vec;            //movement in this frame
  560.     vms_vector new_pos,ipos;        //position after this frame
  561.     int count=0;
  562.     int objnum;
  563.     int WallHitSeg, WallHitSide;
  564.     fvi_info hit_info;
  565.     fvi_query fq;
  566.     vms_vector save_pos;
  567.     int save_seg;
  568.     fix drag;
  569.     fix sim_time;
  570.     vms_vector start_pos;
  571.     int obj_stopped=0;
  572.     fix moved_time;            //how long objected moved before hit something
  573.     vms_vector save_p0,save_p1;
  574.     physics_info *pi;
  575.     int orig_segnum = obj->segnum;
  576.  
  577.     Assert(obj->type != OBJ_NONE);
  578.     Assert(obj->movement_type == MT_PHYSICS);
  579.  
  580. #ifndef NDEBUG
  581. if (Dont_move_ai_objects)
  582.     if (obj->control_type == CT_AI)
  583.         return;
  584. #endif
  585.  
  586.     pi = &obj->mtype.phys_info;
  587.  
  588.     do_physics_sim_rot(obj);
  589.  
  590.     if (!(pi->velocity.x || pi->velocity.y || pi->velocity.z || pi->thrust.x || pi->thrust.y || pi->thrust.z))
  591.         return;
  592.  
  593.     objnum = obj-Objects;
  594.  
  595.     n_phys_segs = 0;
  596.  
  597.     disable_new_fvi_stuff = (obj->type != OBJ_PLAYER);
  598.  
  599.     sim_time = FrameTime;
  600.  
  601. //debug_obj = obj;
  602.  
  603.     #ifdef EXTRA_DEBUG
  604.     if (obj == debug_obj) {
  605.         printf("object %d:\n  start pos = %x %x %x\n",objnum,XYZ(&obj->pos));
  606.         printf("  thrust = %x %x %x\n",XYZ(&obj->mtype.phys_info.thrust));
  607.         printf("  sim_time = %x\n",sim_time);
  608.     }
  609.  
  610.     //check for correct object segment 
  611.     if(!get_seg_masks(&obj->pos,obj->segnum,0).centermask==0) {
  612.         #ifndef NDEBUG
  613.         mprintf((0,"Warning: object %d not in given seg!\n",objnum));
  614.         #endif
  615.         //Int3();  Removed by Rob 10/5/94
  616.         if (!update_object_seg(obj)) {
  617.             #ifndef NDEBUG
  618.             mprintf((0,"Warning: can't find seg for object %d - moving\n",objnum));
  619.             #endif
  620.             if (!(Game_mode & GM_MULTI))
  621.                 Int3();
  622.             compute_segment_center(&obj->pos,&Segments[obj->segnum]);
  623.             obj->pos.x += objnum;
  624.         }
  625.     }
  626.     #endif
  627.  
  628.     start_pos = obj->pos;
  629.  
  630.     n_ignore_objs = 0;
  631.  
  632.     Assert(obj->mtype.phys_info.brakes==0);        //brakes not used anymore?
  633.  
  634.         //if uses thrust, cannot have zero drag
  635.     Assert(!(obj->mtype.phys_info.flags&PF_USES_THRUST) || obj->mtype.phys_info.drag!=0);
  636.  
  637. //mprintf((0,"thrust=%x  speed=%x\n",vm_vec_mag(&obj->mtype.phys_info.thrust),vm_vec_mag(&obj->mtype.phys_info.velocity)));
  638.  
  639.     //do thrust & drag
  640.     
  641.     if ((drag = obj->mtype.phys_info.drag) != 0) {
  642.  
  643.         int count;
  644.         vms_vector accel;
  645.         fix r,k;
  646.  
  647.         count = sim_time / FT;
  648.         r = sim_time % FT;
  649.         k = fixdiv(r,FT);
  650.  
  651.         if (obj->mtype.phys_info.flags & PF_USES_THRUST) {
  652.  
  653.             vm_vec_copy_scale(&accel,&obj->mtype.phys_info.thrust,fixdiv(f1_0,obj->mtype.phys_info.mass));
  654.  
  655.             while (count--) {
  656.  
  657.                 vm_vec_add2(&obj->mtype.phys_info.velocity,&accel);
  658.  
  659.                 vm_vec_scale(&obj->mtype.phys_info.velocity,f1_0-drag);
  660.             }
  661.  
  662.             //do linear scale on remaining bit of time
  663.  
  664.             vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&accel,k);
  665.  
  666.             vm_vec_scale(&obj->mtype.phys_info.velocity,f1_0-fixmul(k,drag));
  667.         }
  668.         else {
  669.             fix total_drag=f1_0;
  670.  
  671.             while (count--)
  672.                 total_drag = fixmul(total_drag,f1_0-drag);
  673.  
  674.             //do linear scale on remaining bit of time
  675.  
  676.             total_drag = fixmul(total_drag,f1_0-fixmul(k,drag));
  677.  
  678.             vm_vec_scale(&obj->mtype.phys_info.velocity,total_drag);
  679.         }
  680.     }
  681.  
  682.     #ifdef EXTRA_DEBUG
  683.     if (obj == debug_obj)
  684.         printf("  velocity = %x %x %x\n",XYZ(&obj->mtype.phys_info.velocity));
  685.     #endif
  686.  
  687.     do {
  688.         try_again = 0;
  689.  
  690.         //Move the object
  691.         vm_vec_copy_scale(&frame_vec, &obj->mtype.phys_info.velocity, sim_time);
  692.  
  693.         #ifdef EXTRA_DEBUG
  694.         if (obj == debug_obj)
  695.             printf("  pass %d, frame_vec = %x %x %x\n",count,XYZ(&frame_vec));
  696.         #endif
  697.  
  698.         if ( (frame_vec.x==0) && (frame_vec.y==0) && (frame_vec.z==0) )    
  699.             break;
  700.  
  701.         count++;
  702.  
  703.         //    If retry count is getting large, then we are trying to do something stupid.
  704.         if ( count > 3)     {
  705.             if (obj->type == OBJ_PLAYER) {
  706.                 if (count > 8)
  707.                     break;
  708.             } else
  709.                 break;
  710.         }
  711.  
  712.         vm_vec_add(&new_pos,&obj->pos,&frame_vec);
  713.  
  714.         #ifdef EXTRA_DEBUG
  715.         if (obj == debug_obj)
  716.             printf("   desired_pos  = %x %x %x\n",XYZ(&new_pos));
  717.         #endif
  718.  
  719.         ignore_obj_list[n_ignore_objs] = -1;
  720.  
  721.         #ifdef EXTRA_DEBUG
  722.         if (obj == debug_obj) {
  723.             printf("   FVI parms: p0 = %8x %8x %8x, segnum=%x, size=%x\n",XYZ(&obj->pos),obj->segnum,obj->size);
  724.             printf("              p1 = %8x %8x %8x\n",XYZ(&new_pos));
  725.         }
  726.         #endif
  727.  
  728.         fq.p0                        = &obj->pos;
  729.         fq.startseg                = obj->segnum;
  730.         fq.p1                        = &new_pos;
  731.         fq.rad                    = obj->size;
  732.         fq.thisobjnum            = objnum;
  733.         fq.ignore_obj_list    = ignore_obj_list;
  734.         fq.flags                    = FQ_CHECK_OBJS;
  735.  
  736.         if (obj->type == OBJ_WEAPON)
  737.             fq.flags |= FQ_TRANSPOINT;
  738.  
  739.         if (obj->type == OBJ_PLAYER)
  740.             fq.flags |= FQ_GET_SEGLIST;
  741.  
  742. //@@            if (get_seg_masks(&obj->pos,obj->segnum,0).centermask!=0)
  743. //@@                Int3();
  744.  
  745. save_p0 = *fq.p0;
  746. save_p1 = *fq.p1;
  747.  
  748.  
  749.         fate = find_vector_intersection(&fq,&hit_info);
  750.         //    Matt: Mike's hack.
  751.         if (fate == HIT_OBJECT) {
  752.             object    *objp = &Objects[hit_info.hit_object];
  753.  
  754.             if ((objp->type == OBJ_WEAPON) && (objp->id == PROXIMITY_ID))
  755.                 count--;
  756.         }
  757.  
  758.         #ifndef NDEBUG
  759.         if (fate == HIT_BAD_P0) {
  760.             mprintf((0,"Warning: Bad p0 in physics!  Object = %i, type = %i [%s]\n", obj-Objects, obj->type, Object_type_names[obj->type]));
  761.             Int3();
  762.         }
  763.         #endif
  764.  
  765.         if (obj->type == OBJ_PLAYER) {
  766.             int i;
  767.  
  768.             if (n_phys_segs && phys_seglist[n_phys_segs-1]==hit_info.seglist[0])
  769.                 n_phys_segs--;
  770.  
  771.             for (i=0;(i<hit_info.n_segs) && (n_phys_segs<MAX_FVI_SEGS-1);  )
  772.                 phys_seglist[n_phys_segs++] = hit_info.seglist[i++];
  773.         }
  774.  
  775.         #ifdef EXTRA_DEBUG
  776.         if (obj == debug_obj)
  777.             printf("   fate  = %d, hit_pnt = %8x %8x %8x\n",fate,XYZ(&hit_info.hit_pnt));;
  778.         #endif
  779.  
  780.         ipos = hit_info.hit_pnt;
  781.         iseg = hit_info.hit_seg;
  782.         WallHitSide = hit_info.hit_side;
  783.         WallHitSeg = hit_info.hit_side_seg;
  784.  
  785.         if (iseg==-1) {        //some sort of horrible error
  786.             #ifndef NDEBUG
  787.             mprintf((1,"iseg==-1 in physics!  Object = %i, type = %i (%s)\n", obj-Objects, obj->type, Object_type_names[obj->type]));
  788.             #endif
  789.             //Int3();
  790.             //compute_segment_center(&ipos,&Segments[obj->segnum]);
  791.             //ipos.x += objnum;
  792.             //iseg = obj->segnum;
  793.             //fate = HIT_NONE;
  794.             if (obj->type == OBJ_WEAPON)
  795.                 obj->flags |= OF_SHOULD_BE_DEAD;
  796.             break;
  797.         }
  798.  
  799.         Assert(!((fate==HIT_WALL) && ((WallHitSeg == -1) || (WallHitSeg > Highest_segment_index))));
  800.  
  801.         //if(!get_seg_masks(&hit_info.hit_pnt,hit_info.hit_seg,0).centermask==0)
  802.         //    Int3();
  803.  
  804.         save_pos = obj->pos;            //save the object's position
  805.         save_seg = obj->segnum;
  806.  
  807.         // update object's position and segment number
  808.         obj->pos = ipos;
  809.  
  810.         #ifdef EXTRA_DEBUG
  811.         if (obj == debug_obj)
  812.             printf("   new pos = %x %x %x\n",XYZ(&obj->pos));
  813.         #endif
  814.  
  815.         if ( iseg != obj->segnum )
  816.             obj_relink(objnum, iseg );
  817.  
  818.         //if start point not in segment, move object to center of segment
  819.         if (get_seg_masks(&obj->pos,obj->segnum,0).centermask!=0) {
  820.             int n;
  821.  
  822.             if ((n=find_object_seg(obj))==-1) {
  823.                 //Int3();
  824.                 if (obj->type==OBJ_PLAYER && (n=find_point_seg(&obj->last_pos,obj->segnum))!=-1) {
  825.                     obj->pos = obj->last_pos;
  826.                     obj_relink(objnum, n );
  827.                 }
  828.                 else {
  829.                     compute_segment_center(&obj->pos,&Segments[obj->segnum]);
  830.                     obj->pos.x += objnum;
  831.                 }
  832.                 if (obj->type == OBJ_WEAPON)
  833.                     obj->flags |= OF_SHOULD_BE_DEAD;
  834.             }
  835.             return;
  836.         }
  837.  
  838.         //calulate new sim time
  839.         {
  840.             //vms_vector moved_vec;
  841.             vms_vector moved_vec_n;
  842.             fix attempted_dist,actual_dist;
  843.  
  844.             actual_dist = vm_vec_normalized_dir(&moved_vec_n,&obj->pos,&save_pos);
  845.  
  846.             if (fate==HIT_WALL && vm_vec_dot(&moved_vec_n,&frame_vec) < 0) {        //moved backwards
  847.  
  848.                 //don't change position or sim_time
  849.  
  850. //*******                    mprintf((0,"Obj %d moved backwards\n",obj-Objects));
  851.  
  852.                 #ifdef EXTRA_DEBUG
  853.                 if (obj == debug_obj)
  854.                     printf("   Warning: moved backwards!\n");
  855.                 #endif
  856.  
  857.                 obj->pos = save_pos;
  858.         
  859.                 //iseg = obj->segnum;        //don't change segment
  860.  
  861.                 obj_relink(objnum, save_seg );
  862.  
  863.                 moved_time = 0;
  864.             }
  865.             else {
  866.                 fix old_sim_time;
  867.  
  868.                 //if (obj == debug_obj)
  869.                 //    printf("   moved_vec = %x %x %x\n",XYZ(&moved_vec));
  870.             
  871.                 attempted_dist = vm_vec_mag(&frame_vec);
  872.  
  873.                 old_sim_time = sim_time;
  874.  
  875.                 sim_time = fixmuldiv(sim_time,attempted_dist-actual_dist,attempted_dist);
  876.  
  877.                 moved_time = old_sim_time - sim_time;
  878.  
  879.                 if (sim_time < 0 || sim_time>old_sim_time) {
  880.                     #ifndef NDEBUG
  881.                     mprintf((0,"Bogus sim_time = %x, old = %x\n",sim_time,old_sim_time));
  882.                     if (obj == debug_obj)
  883.                         printf("   Bogus sim_time = %x, old = %x, attempted_dist = %x, actual_dist = %x\n",sim_time,old_sim_time,attempted_dist,actual_dist);
  884.                     //Int3(); Removed by Rob
  885.                     #endif
  886.                     sim_time = old_sim_time;
  887.                     //WHY DOES THIS HAPPEN??
  888.  
  889.                     moved_time = 0;
  890.                 }
  891.             }
  892.  
  893.             #ifdef EXTRA_DEBUG
  894.             if (obj == debug_obj)
  895.                 printf("   new sim_time = %x\n",sim_time);
  896.             #endif
  897.  
  898.         }
  899.  
  900.  
  901.         switch( fate )        {
  902.  
  903.             case HIT_WALL:        {
  904.                 vms_vector moved_v;
  905.                 //@@fix total_d,moved_d;
  906.                 fix hit_speed,wall_part;
  907.     
  908.                 // Find hit speed    
  909.  
  910.                 vm_vec_sub(&moved_v,&obj->pos,&save_pos);
  911.  
  912.                 wall_part = vm_vec_dot(&moved_v,&hit_info.hit_wallnorm);
  913.  
  914.                 if (wall_part != 0 && moved_time>0 && (hit_speed=-fixdiv(wall_part,moved_time))>0)
  915.                     collide_object_with_wall( obj, hit_speed, WallHitSeg, WallHitSide, &hit_info.hit_pnt );
  916.                 else
  917.                     scrape_object_on_wall(obj, WallHitSeg, WallHitSide, &hit_info.hit_pnt );
  918.  
  919.                 Assert( WallHitSeg > -1 );                
  920.                 Assert( WallHitSide > -1 );                
  921.  
  922.                 if ( !(obj->flags&OF_SHOULD_BE_DEAD) )    {
  923.  
  924.  
  925.                     Assert(! (obj->mtype.phys_info.flags & PF_STICK && obj->mtype.phys_info.flags & PF_BOUNCE));    //can't be bounce and stick
  926.  
  927.                     if (obj->mtype.phys_info.flags & PF_STICK) {        //stop moving
  928.  
  929.                         // mprintf((0, "Object %i stuck at %i:%i\n", obj-Objects, WallHitSeg, WallHitSide));
  930.                         add_stuck_object(obj, WallHitSeg, WallHitSide);
  931.  
  932.                         vm_vec_zero(&obj->mtype.phys_info.velocity);
  933.                         obj_stopped = 1;
  934.                         try_again = 0;
  935.                     }
  936.                     else {                    // Slide object along wall
  937.  
  938.                         //We're constrained by wall, so subtract wall part from 
  939.                         //velocity vector
  940.  
  941.                         wall_part = vm_vec_dot(&hit_info.hit_wallnorm,&obj->mtype.phys_info.velocity);
  942.  
  943.                         if (obj->mtype.phys_info.flags & PF_BOUNCE)        //bounce off wall
  944.                             wall_part *= 2;    //Subtract out wall part twice to achieve bounce
  945.  
  946.                         vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&hit_info.hit_wallnorm,-wall_part);
  947.  
  948.                         #ifdef EXTRA_DEBUG
  949.                         if (obj == debug_obj) {
  950.                             printf("   sliding - wall_norm %x %x %x\n",wall_part,XYZ(&hit_info.hit_wallnorm));
  951.                             printf("   wall_part %x, new velocity = %x %x %x\n",wall_part,XYZ(&obj->mtype.phys_info.velocity));
  952.                         }
  953.                         #endif
  954.  
  955.                         try_again = 1;
  956.                     }
  957.                 }
  958.                 break;
  959.             }
  960.  
  961.             case HIT_OBJECT:        {
  962.                 vms_vector old_vel;
  963.  
  964.                 // Mark the hit object so that on a retry the fvi code
  965.                 // ignores this object.
  966.  
  967.                 Assert(hit_info.hit_object != -1);
  968.  
  969.                 //    Calculcate the hit point between the two objects.
  970.                 {    vms_vector    *ppos0, *ppos1, pos_hit;
  971.                     fix            size0, size1;
  972.                     ppos0 = &Objects[hit_info.hit_object].pos;
  973.                     ppos1 = &obj->pos;
  974.                     size0 = Objects[hit_info.hit_object].size;
  975.                     size1 = obj->size;
  976.                     Assert(size0+size1 != 0);    // Error, both sizes are 0, so how did they collide, anyway?!?
  977.                     //vm_vec_scale(vm_vec_sub(&pos_hit, ppos1, ppos0), fixdiv(size0, size0 + size1));
  978.                     //vm_vec_add2(&pos_hit, ppos0);
  979.                     vm_vec_sub(&pos_hit, ppos1, ppos0);
  980.                     vm_vec_scale_add(&pos_hit,ppos0,&pos_hit,fixdiv(size0, size0 + size1));
  981.  
  982.                     old_vel = obj->mtype.phys_info.velocity;
  983.  
  984.                     collide_two_objects( obj, &Objects[hit_info.hit_object], &pos_hit);
  985.  
  986.                 }
  987.  
  988.                 // Let object continue its movement
  989.                 if ( !(obj->flags&OF_SHOULD_BE_DEAD)  )    {
  990.                     //obj->pos = save_pos;
  991.  
  992.                     if (obj->mtype.phys_info.flags&PF_PERSISTENT || (old_vel.x == obj->mtype.phys_info.velocity.x && old_vel.y == obj->mtype.phys_info.velocity.y && old_vel.z == obj->mtype.phys_info.velocity.z)) {
  993.                         //if (Objects[hit_info.hit_object].type == OBJ_POWERUP)
  994.                             ignore_obj_list[n_ignore_objs++] = hit_info.hit_object;
  995.                         try_again = 1;
  996.                     }
  997.                 }
  998.  
  999.                 break;
  1000.             }    
  1001.             case HIT_NONE:        
  1002.                 break;
  1003.  
  1004.             #ifndef NDEBUG
  1005.             case HIT_BAD_P0:
  1006.                 Int3();        // Unexpected collision type: start point not in specified segment.
  1007.                 mprintf((0,"Warning: Bad p0 in physics!!!\n"));
  1008.                 break;
  1009.             default:
  1010.                 // Unknown collision type returned from find_vector_intersection!!
  1011.                 Int3();
  1012.                 break;
  1013.             #endif
  1014.         }
  1015.  
  1016.     } while ( try_again );
  1017.  
  1018.     //    Pass retry count info to AI.
  1019.     if (obj->control_type == CT_AI) {
  1020.         if (count > 0) {
  1021.             Ai_local_info[objnum].retry_count = count-1;
  1022.             Total_retries += count-1;
  1023.             Total_sims++;
  1024.         }
  1025.     }
  1026.  
  1027.     if (! obj_stopped)    {    //Set velocity from actual movement
  1028.         vms_vector moved_vec;
  1029.         vm_vec_sub(&moved_vec,&obj->pos,&start_pos);
  1030.         vm_vec_copy_scale(&obj->mtype.phys_info.velocity,&moved_vec,fixdiv(f1_0,FrameTime));
  1031.  
  1032.         #ifdef BUMP_HACK
  1033.         if (obj==ConsoleObject && (obj->mtype.phys_info.velocity.x==0 && obj->mtype.phys_info.velocity.y==0 && obj->mtype.phys_info.velocity.z==0) &&
  1034.               !(obj->mtype.phys_info.thrust.x==0 && obj->mtype.phys_info.thrust.y==0 && obj->mtype.phys_info.thrust.z==0)) {
  1035.             vms_vector center,bump_vec;
  1036.  
  1037.             //bump player a little towards center of segment to unstick
  1038.  
  1039.             compute_segment_center(¢er,&Segments[obj->segnum]);
  1040.             vm_vec_normalized_dir_quick(&bump_vec,¢er,&obj->pos);
  1041.             vm_vec_scale_add2(&obj->pos,&bump_vec,obj->size/5);
  1042.         }
  1043.         #endif
  1044.     }
  1045.  
  1046.     //Assert(check_point_in_seg(&obj->pos,obj->segnum,0).centermask==0);
  1047.  
  1048.     //if (obj->control_type == CT_FLYING)
  1049.     if (obj->mtype.phys_info.flags & PF_LEVELLING)
  1050.         do_physics_align_object( obj );
  1051.  
  1052.  
  1053.     //hack to keep player from going through closed doors
  1054.     if (obj->type==OBJ_PLAYER && obj->segnum!=orig_segnum && (Physics_cheat_flag!=0xBADA55) ) {
  1055.         int sidenum;
  1056.  
  1057.         sidenum = find_connect_side(&Segments[obj->segnum],&Segments[orig_segnum]);
  1058.  
  1059.         if (sidenum != -1) {
  1060.  
  1061.             if (! (WALL_IS_DOORWAY(&Segments[orig_segnum],sidenum) & WID_FLY_FLAG)) {
  1062.                 side *s;
  1063.                 int vertnum,num_faces,i;
  1064.                 fix dist;
  1065.                 int vertex_list[6];
  1066.  
  1067.                 //bump object back
  1068.  
  1069.                 s = &Segments[orig_segnum].sides[sidenum];
  1070.  
  1071.                 create_abs_vertex_lists( &num_faces, vertex_list, orig_segnum, sidenum);
  1072.  
  1073.                 //let's pretend this wall is not triangulated
  1074.                 vertnum = vertex_list[0];
  1075.                 for (i=1;i<4;i++)
  1076.                     if (vertex_list[i] < vertnum)
  1077.                         vertnum = vertex_list[i];
  1078.  
  1079.                 #ifdef COMPACT_SEGS
  1080.                     {
  1081.                     vms_vector _vn;
  1082.                     get_side_normal(&Segments[orig_segnum], sidenum, 0, &_vn );
  1083.                     dist = vm_dist_to_plane(&start_pos, &_vn, &Vertices[vertnum]);
  1084.                     vm_vec_scale_add(&obj->pos,&start_pos,&_vn,obj->size-dist);
  1085.                     }
  1086.                 #else
  1087.                     dist = vm_dist_to_plane(&start_pos, &s->normals[0], &Vertices[vertnum]);
  1088.                     vm_vec_scale_add(&obj->pos,&start_pos,&s->normals[0],obj->size-dist);
  1089.                 #endif
  1090.                 update_object_seg(obj);
  1091.  
  1092.             }
  1093.         }
  1094.     }
  1095.  
  1096. //--WE ALWYS WANT THIS IN, MATT AND MIKE DECISION ON 12/10/94, TWO MONTHS AFTER FINAL     #ifndef NDEBUG
  1097.     //if end point not in segment, move object to last pos, or segment center
  1098.     if (get_seg_masks(&obj->pos,obj->segnum,0).centermask!=0) {
  1099.         if (find_object_seg(obj)==-1) {
  1100.             int n;
  1101.  
  1102.             //Int3();
  1103.             if (obj->type==OBJ_PLAYER && (n=find_point_seg(&obj->last_pos,obj->segnum))!=-1) {
  1104.                 obj->pos = obj->last_pos;
  1105.                 obj_relink(objnum, n );
  1106.             }
  1107.             else {
  1108.                 compute_segment_center(&obj->pos,&Segments[obj->segnum]);
  1109.                 obj->pos.x += objnum;
  1110.             }
  1111.             if (obj->type == OBJ_WEAPON)
  1112.                 obj->flags |= OF_SHOULD_BE_DEAD;
  1113.         }
  1114.     }
  1115. //--WE ALWYS WANT THIS IN, MATT AND MIKE DECISION ON 12/10/94, TWO MONTHS AFTER FINAL     #endif
  1116.  
  1117.  
  1118. }
  1119.  
  1120. //--unused-- //tell us what the given object will do (as far as hiting walls) in
  1121. //--unused-- //the given time (in seconds) t.  Igores acceleration (sorry) 
  1122. //--unused-- //if check_objects is set, check with objects, else just with walls
  1123. //--unused-- //returns fate, fills in hit time.  If fate==HIT_NONE, hit_time undefined
  1124. //--unused-- int physics_lookahead(object *obj,fix t,int fvi_flags,fix *hit_time, fvi_info *hit_info)
  1125. //--unused-- {
  1126. //--unused--     vms_vector new_pos;
  1127. //--unused--     int objnum,fate;
  1128. //--unused--     fvi_query fq;
  1129. //--unused-- 
  1130. //--unused--     Assert(obj->movement_type == MT_PHYSICS);
  1131. //--unused-- 
  1132. //--unused--     objnum = obj-Objects;
  1133. //--unused-- 
  1134. //--unused--     vm_vec_scale_add(&new_pos, &obj->pos, &obj->mtype.phys_info.velocity, t);
  1135. //--unused-- 
  1136. //--unused--     fq.p0                        = &obj->pos;
  1137. //--unused--     fq.startseg                = obj->segnum;
  1138. //--unused--     fq.p1                        = &new_pos;
  1139. //--unused--     fq.rad                    = obj->size;
  1140. //--unused--     fq.thisobjnum            = objnum;
  1141. //--unused--     fq.ignore_obj_list    = NULL;
  1142. //--unused--     fq.flags                    = fvi_flags;
  1143. //--unused-- 
  1144. //--unused--     fate = find_vector_intersection(&fq,hit_info);
  1145. //--unused-- 
  1146. //--unused--     if (fate != HIT_NONE) {
  1147. //--unused--         fix dist,speed;
  1148. //--unused-- 
  1149. //--unused--         dist = vm_vec_dist(&obj->pos, &hit_info->hit_pnt);
  1150. //--unused-- 
  1151. //--unused--         speed = vm_vec_mag(&obj->mtype.phys_info.velocity);
  1152. //--unused-- 
  1153. //--unused--         *hit_time = fixdiv(dist,speed);
  1154. //--unused-- 
  1155. //--unused--     }
  1156. //--unused-- 
  1157. //--unused--     return fate;
  1158. //--unused-- 
  1159. //--unused-- }
  1160.  
  1161. //Applies an instantaneous force on an object, resulting in an instantaneous
  1162. //change in velocity.
  1163. phys_apply_force(object *obj,vms_vector *force_vec)
  1164. {
  1165.  
  1166.     if (obj->movement_type != MT_PHYSICS)
  1167.         return;
  1168.  
  1169.     //Add in acceleration due to force
  1170.     vm_vec_scale_add2(&obj->mtype.phys_info.velocity,force_vec,fixdiv(f1_0,obj->mtype.phys_info.mass));
  1171.  
  1172.  
  1173. }
  1174.  
  1175. //    ----------------------------------------------------------------
  1176. //    Do *dest = *delta unless:
  1177. //                *delta is pretty small
  1178. //        and    they are of different signs.
  1179. void physics_set_rotvel_and_saturate(fix *dest, fix delta)
  1180. {
  1181.     if ((delta ^ *dest) < 0) {
  1182.         if (abs(delta) < F1_0/8) {
  1183.             // mprintf((0, "D"));
  1184.             *dest = delta/4;
  1185.         } else
  1186.             // mprintf((0, "d"));
  1187.             *dest = delta;
  1188.     } else {
  1189.         // mprintf((0, "!"));
  1190.         *dest = delta;
  1191.     }
  1192. }
  1193.  
  1194. //    ------------------------------------------------------------------------------------------------------
  1195. //    Note: This is the old ai_turn_towards_vector code.
  1196. //    phys_apply_rot used to call ai_turn_towards_vector until I fixed it, which broke phys_apply_rot.
  1197. void physics_turn_towards_vector(vms_vector *goal_vector, object *obj, fix rate)
  1198. {
  1199.     vms_angvec    dest_angles, cur_angles;
  1200.     fix            delta_p, delta_h;
  1201.     vms_vector    *rotvel_ptr = &obj->mtype.phys_info.rotvel;
  1202.  
  1203.     // Make this object turn towards the goal_vector.  Changes orientation, doesn't change direction of movement.
  1204.     // If no one moves, will be facing goal_vector in 1 second.
  1205.  
  1206.     //    Detect null vector.
  1207.     if ((goal_vector->x == 0) && (goal_vector->y == 0) && (goal_vector->z == 0))
  1208.         return;
  1209.  
  1210.     //    Make morph objects turn more slowly.
  1211.     if (obj->control_type == CT_MORPH)
  1212.         rate *= 2;
  1213.  
  1214.     vm_extract_angles_vector(&dest_angles, goal_vector);
  1215.     vm_extract_angles_vector(&cur_angles, &obj->orient.fvec);
  1216.  
  1217.     delta_p = (dest_angles.p - cur_angles.p);
  1218.     delta_h = (dest_angles.h - cur_angles.h);
  1219.  
  1220.     if (delta_p > F1_0/2) delta_p = dest_angles.p - cur_angles.p - F1_0;
  1221.     if (delta_p < -F1_0/2) delta_p = dest_angles.p - cur_angles.p + F1_0;
  1222.     if (delta_h > F1_0/2) delta_h = dest_angles.h - cur_angles.h - F1_0;
  1223.     if (delta_h < -F1_0/2) delta_h = dest_angles.h - cur_angles.h + F1_0;
  1224.  
  1225.     delta_p = fixdiv(delta_p, rate);
  1226.     delta_h = fixdiv(delta_h, rate);
  1227.  
  1228.     if (abs(delta_p) < F1_0/16) delta_p *= 4;
  1229.     if (abs(delta_h) < F1_0/16) delta_h *= 4;
  1230.  
  1231.     physics_set_rotvel_and_saturate(&rotvel_ptr->x, delta_p);
  1232.     physics_set_rotvel_and_saturate(&rotvel_ptr->y, delta_h);
  1233.     rotvel_ptr->z = 0;
  1234. }
  1235.  
  1236. //    -----------------------------------------------------------------------------
  1237. //    Applies an instantaneous whack on an object, resulting in an instantaneous
  1238. //    change in orientation.
  1239. phys_apply_rot(object *obj,vms_vector *force_vec)
  1240. {
  1241.     fix    rate, vecmag;
  1242.  
  1243.     if (obj->movement_type != MT_PHYSICS)
  1244.         return;
  1245.  
  1246.     vecmag = vm_vec_mag(force_vec)/8;
  1247.     if (vecmag < F1_0/256)
  1248.         rate = 4*F1_0;
  1249.     else if (vecmag < obj->mtype.phys_info.mass >> 14)
  1250.         rate = 4*F1_0;
  1251.     else {
  1252.         rate = fixdiv(obj->mtype.phys_info.mass, vecmag);
  1253.         if (obj->type == OBJ_ROBOT) {
  1254.             if (rate < F1_0/4)
  1255.                 rate = F1_0/4;
  1256.             obj->ctype.ai_info.SKIP_AI_COUNT = 2;
  1257.         } else {
  1258.             if (rate < F1_0/2)
  1259.                 rate = F1_0/2;
  1260.         }
  1261.     }
  1262.  
  1263.     //    Turn amount inversely proportional to mass.  Third parameter is seconds to do 360 turn.
  1264.     physics_turn_towards_vector(force_vec, obj, rate);
  1265.  
  1266.  
  1267. }
  1268.  
  1269.  
  1270. //this routine will set the thrust for an object to a value that will
  1271. //(hopefully) maintain the object's current velocity
  1272. set_thrust_from_velocity(object *obj)
  1273. {
  1274.     fix k;
  1275.  
  1276.     Assert(obj->movement_type == MT_PHYSICS);
  1277.  
  1278.     k = fixmuldiv(obj->mtype.phys_info.mass,obj->mtype.phys_info.drag,(f1_0-obj->mtype.phys_info.drag));
  1279.  
  1280.     vm_vec_copy_scale(&obj->mtype.phys_info.thrust,&obj->mtype.phys_info.velocity,k);
  1281.  
  1282. }
  1283.  
  1284. 
  1285.