2006-03-20 17:12:09 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING . txt .
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below .
* See COPYING . txt for license details .
2006-03-20 17:12:09 +00:00
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ( " PARALLAX " ) . PARALLAX , IN DISTRIBUTING THE CODE TO
END - USERS , AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN , GRANTS A
ROYALTY - FREE , PERPETUAL LICENSE TO SUCH END - USERS FOR USE BY SUCH END - USERS
IN USING , DISPLAYING , AND CREATING DERIVATIVE WORKS THEREOF , SO LONG AS
SUCH USE , DISPLAY OR CREATION IS FOR NON - COMMERCIAL , ROYALTY OR REVENUE
FREE PURPOSES . IN NO EVENT SHALL THE END - USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE - BEARING PURPOSES . THE END - USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE .
COPYRIGHT 1993 - 1999 PARALLAX SOFTWARE CORPORATION . ALL RIGHTS RESERVED .
*/
/*
*
* Code for flying through the mines
*
*/
# include <stdio.h>
# include <stdlib.h>
# include "joy.h"
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "inferno.h"
# include "segment.h"
# include "object.h"
# include "physics.h"
2015-04-02 02:36:57 +00:00
# include "robot.h"
2006-03-20 17:12:09 +00:00
# include "key.h"
# include "game.h"
# include "collide.h"
# include "fvi.h"
# include "newdemo.h"
2013-12-26 04:18:28 +00:00
# include "gameseg.h"
2006-03-20 17:12:09 +00:00
# include "timer.h"
# include "ai.h"
# include "wall.h"
# include "laser.h"
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
# include "bm.h"
# include "player.h"
2013-03-03 01:03:33 +00:00
# define MAX_OBJECT_VEL i2f(100)
# endif
2006-03-20 17:12:09 +00:00
2013-12-22 16:04:18 +00:00
# include "dxxsconf.h"
# include "compiler-range_for.h"
2006-03-20 17:12:09 +00:00
//Global variables for physics system
2013-02-21 00:20:26 +00:00
# define ROLL_RATE 0x2000
2006-03-21 14:01:57 +00:00
# define DAMP_ANG 0x400 //min angle to bank
2006-03-20 17:12:09 +00:00
# define TURNROLL_SCALE (0x4ec4 / 2)
//check point against each side of segment. return bitmask, where bit
//set means behind that side
//make sure matrix is orthogonal
2014-11-04 01:30:49 +00:00
void check_and_fix_matrix ( vms_matrix & m )
2006-03-20 17:12:09 +00:00
{
2014-11-04 01:30:49 +00:00
m = vm_vector_2_matrix ( m . fvec , & m . uvec , nullptr ) ;
2006-03-20 17:12:09 +00:00
}
2016-04-23 17:59:47 +00:00
static void do_physics_align_object ( object_base & obj )
2006-03-20 17:12:09 +00:00
{
vms_vector desired_upvec ;
fixang delta_ang , roll_ang ;
//vms_vector forvec = {0,0,f1_0};
2015-11-15 22:30:41 +00:00
fix largest_d = - f1_0 ;
const side * best_side = nullptr ;
2006-03-20 17:12:09 +00:00
// bank player according to segment orientation
//find side of segment that player is most alligned with
2016-04-23 17:59:47 +00:00
range_for ( auto & i , vcsegptr ( obj . segnum ) - > sides )
2015-11-15 22:30:41 +00:00
{
2016-04-23 17:59:47 +00:00
const auto d = vm_vec_dot ( i . normals [ 0 ] , obj . orient . uvec ) ;
2006-03-20 17:12:09 +00:00
2015-11-15 22:30:41 +00:00
if ( largest_d < d )
{
largest_d = d ;
best_side = & i ;
}
2006-03-20 17:12:09 +00:00
}
2015-11-15 22:30:41 +00:00
// new player leveling code: use normal of side closest to our up vec
2017-02-19 19:33:38 +00:00
if ( ! get_side_is_quad ( * best_side ) )
2015-11-15 22:30:41 +00:00
{
desired_upvec = vm_vec_avg ( best_side - > normals [ 0 ] , best_side - > normals [ 1 ] ) ;
2014-09-28 21:11:03 +00:00
vm_vec_normalize ( desired_upvec ) ;
2006-03-20 17:12:09 +00:00
}
else
2015-11-15 22:30:41 +00:00
desired_upvec = best_side - > normals [ 0 ] ;
2006-03-20 17:12:09 +00:00
2016-04-23 17:59:47 +00:00
if ( labs ( vm_vec_dot ( desired_upvec , obj . orient . fvec ) ) < f1_0 / 2 )
{
2006-03-20 17:12:09 +00:00
vms_angvec tangles ;
2016-04-23 17:59:47 +00:00
const auto temp_matrix = vm_vector_2_matrix ( obj . orient . fvec , & desired_upvec , nullptr ) ;
2006-03-20 17:12:09 +00:00
2016-04-23 17:59:47 +00:00
delta_ang = vm_vec_delta_ang ( obj . orient . uvec , temp_matrix . uvec , obj . orient . fvec ) ;
2006-03-20 17:12:09 +00:00
2016-04-23 17:59:47 +00:00
delta_ang + = obj . mtype . phys_info . turnroll ;
2006-03-20 17:12:09 +00:00
if ( abs ( delta_ang ) > DAMP_ANG ) {
roll_ang = fixmul ( FrameTime , ROLL_RATE ) ;
if ( abs ( delta_ang ) < roll_ang ) roll_ang = delta_ang ;
else if ( delta_ang < 0 ) roll_ang = - roll_ang ;
tangles . p = tangles . h = 0 ; tangles . b = roll_ang ;
2015-02-05 03:03:51 +00:00
const auto & & rotmat = vm_angles_2_matrix ( tangles ) ;
2016-04-23 17:59:47 +00:00
obj . orient = vm_matrix_x_matrix ( obj . orient , rotmat ) ;
2006-03-20 17:12:09 +00:00
}
}
}
2016-04-23 17:59:47 +00:00
static void set_object_turnroll ( object_base & obj )
2006-03-20 17:12:09 +00:00
{
fixang desired_bank ;
2016-04-23 17:59:47 +00:00
desired_bank = - fixmul ( obj . mtype . phys_info . rotvel . y , TURNROLL_SCALE ) ;
2006-03-20 17:12:09 +00:00
2016-04-23 17:59:47 +00:00
if ( obj . mtype . phys_info . turnroll ! = desired_bank )
{
2006-03-20 17:12:09 +00:00
fixang delta_ang , max_roll ;
max_roll = fixmul ( ROLL_RATE , FrameTime ) ;
2016-04-23 17:59:47 +00:00
delta_ang = desired_bank - obj . mtype . phys_info . turnroll ;
2006-03-20 17:12:09 +00:00
if ( labs ( delta_ang ) < max_roll )
max_roll = delta_ang ;
else
if ( delta_ang < 0 )
max_roll = - max_roll ;
2016-04-23 17:59:47 +00:00
obj . mtype . phys_info . turnroll + = max_roll ;
2006-03-20 17:12:09 +00:00
}
}
# define MAX_IGNORE_OBJS 100
# ifndef NDEBUG
int Total_retries = 0 , Total_sims = 0 ;
int Dont_move_ai_objects = 0 ;
# endif
# define FT (f1_0 / 64)
// -----------------------------------------------------------------------------------------------------------
// add rotational velocity & acceleration
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-04-23 17:59:47 +00:00
static void do_physics_sim_rot ( object_base & obj )
2006-03-20 17:12:09 +00:00
{
vms_angvec tangles ;
2013-02-21 00:20:26 +00:00
//fix rotdrag_scale;
2006-03-20 17:12:09 +00:00
physics_info * pi ;
Assert ( FrameTime > 0 ) ; //Get MATT if hit this!
2016-04-23 17:59:47 +00:00
pi = & obj . mtype . phys_info ;
2006-03-20 17:12:09 +00:00
if ( ! ( pi - > rotvel . x | | pi - > rotvel . y | | pi - > rotvel . z | | pi - > rotthrust . x | | pi - > rotthrust . y | | pi - > rotthrust . z ) )
return ;
2016-04-23 17:59:47 +00:00
if ( obj . mtype . phys_info . drag )
{
2006-03-20 17:12:09 +00:00
int count ;
fix drag , r , k ;
count = FrameTime / FT ;
r = FrameTime % FT ;
k = fixdiv ( r , FT ) ;
2016-04-23 17:59:47 +00:00
drag = ( obj . mtype . phys_info . drag * 5 ) / 2 ;
2006-03-20 17:12:09 +00:00
2016-04-23 17:59:47 +00:00
if ( obj . mtype . phys_info . flags & PF_USES_THRUST )
{
const auto accel = vm_vec_copy_scale ( obj . mtype . phys_info . rotthrust , fixdiv ( f1_0 , obj . mtype . phys_info . mass ) ) ;
2006-03-20 17:12:09 +00:00
while ( count - - ) {
2016-04-23 17:59:47 +00:00
vm_vec_add2 ( obj . mtype . phys_info . rotvel , accel ) ;
vm_vec_scale ( obj . mtype . phys_info . rotvel , f1_0 - drag ) ;
2006-03-20 17:12:09 +00:00
}
//do linear scale on remaining bit of time
2016-04-23 17:59:47 +00:00
vm_vec_scale_add2 ( obj . mtype . phys_info . rotvel , accel , k ) ;
vm_vec_scale ( obj . mtype . phys_info . rotvel , f1_0 - fixmul ( k , drag ) ) ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
else
# if defined(DXX_BUILD_DESCENT_II)
2016-04-23 17:59:47 +00:00
if ( ! ( obj . mtype . phys_info . flags & PF_FREE_SPINNING ) )
2013-03-03 01:03:33 +00:00
# endif
2013-03-30 20:29:29 +00:00
{
2006-03-20 17:12:09 +00:00
fix total_drag = f1_0 ;
while ( count - - )
total_drag = fixmul ( total_drag , f1_0 - drag ) ;
//do linear scale on remaining bit of time
total_drag = fixmul ( total_drag , f1_0 - fixmul ( k , drag ) ) ;
2016-04-23 17:59:47 +00:00
vm_vec_scale ( obj . mtype . phys_info . rotvel , total_drag ) ;
2006-03-20 17:12:09 +00:00
}
}
//now rotate object
//unrotate object for bank caused by turn
2016-04-23 17:59:47 +00:00
if ( obj . mtype . phys_info . turnroll )
{
2006-03-20 17:12:09 +00:00
tangles . p = tangles . h = 0 ;
2016-04-23 17:59:47 +00:00
tangles . b = - obj . mtype . phys_info . turnroll ;
2015-02-05 03:03:51 +00:00
const auto & & rotmat = vm_angles_2_matrix ( tangles ) ;
2016-04-23 17:59:47 +00:00
obj . orient = vm_matrix_x_matrix ( obj . orient , rotmat ) ;
2006-03-20 17:12:09 +00:00
}
2016-04-23 17:59:47 +00:00
const auto frametime = FrameTime ;
tangles . p = fixmul ( obj . mtype . phys_info . rotvel . x , frametime ) ;
tangles . h = fixmul ( obj . mtype . phys_info . rotvel . y , frametime ) ;
tangles . b = fixmul ( obj . mtype . phys_info . rotvel . z , frametime ) ;
2006-03-20 17:12:09 +00:00
2016-04-23 17:59:47 +00:00
obj . orient = vm_matrix_x_matrix ( obj . orient , vm_angles_2_matrix ( tangles ) ) ;
2006-03-20 17:12:09 +00:00
2016-04-23 17:59:47 +00:00
if ( obj . mtype . phys_info . flags & PF_TURNROLL )
2006-03-20 17:12:09 +00:00
set_object_turnroll ( obj ) ;
//re-rotate object for bank caused by turn
2016-04-23 17:59:47 +00:00
if ( obj . mtype . phys_info . turnroll )
{
2006-03-20 17:12:09 +00:00
tangles . p = tangles . h = 0 ;
2016-04-23 17:59:47 +00:00
tangles . b = obj . mtype . phys_info . turnroll ;
obj . orient = vm_matrix_x_matrix ( obj . orient , vm_angles_2_matrix ( tangles ) ) ;
2006-03-20 17:12:09 +00:00
}
2016-04-23 17:59:47 +00:00
check_and_fix_matrix ( obj . orient ) ;
2006-03-20 17:12:09 +00:00
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
2011-05-18 23:25:38 +00:00
// On joining edges fvi tends to get inaccurate as hell. Approach is to check if the object interects with the wall and if so, move away from it.
2017-06-10 03:31:02 +00:00
static void fix_illegal_wall_intersection ( const vmobjptridx_t obj )
2011-05-04 00:15:10 +00:00
{
2011-05-18 23:35:44 +00:00
if ( ! ( obj - > type = = OBJ_PLAYER | | obj - > type = = OBJ_ROBOT ) )
2011-05-04 00:15:10 +00:00
return ;
2015-02-14 22:48:27 +00:00
object_intersects_wall_result_t hresult ;
if ( object_intersects_wall_d ( obj , hresult ) )
2011-05-04 11:06:30 +00:00
{
2015-02-14 22:48:27 +00:00
vm_vec_scale_add2 ( obj - > pos , Segments [ hresult . seg ] . sides [ hresult . side ] . normals [ 0 ] , FrameTime * 10 ) ;
2011-05-18 23:25:38 +00:00
update_object_seg ( obj ) ;
2011-05-04 11:06:30 +00:00
}
2011-05-04 00:15:10 +00:00
}
2015-02-05 03:03:51 +00:00
namespace {
class ignore_objects_array_t
{
typedef array < objnum_t , MAX_IGNORE_OBJS > array_t ;
array_t a ;
array_t : : iterator e ;
public :
ignore_objects_array_t ( ) :
e ( a . begin ( ) )
{
}
bool push_back ( objnum_t o )
{
if ( e = = a . end ( ) )
return false ;
* e + + = o ;
return true ;
}
operator std : : pair < const objnum_t * , const objnum_t * > ( ) const
{
return { a . begin ( ) , e } ;
}
} ;
}
2006-03-20 17:12:09 +00:00
// -----------------------------------------------------------------------------------------------------------
//Simulate a physics object for this frame
2016-08-25 04:05:32 +00:00
namespace dsx {
2017-08-02 02:49:13 +00:00
window_event_result do_physics_sim ( const vmobjptridx_t obj , phys_visited_seglist * const phys_segs )
2006-03-20 17:12:09 +00:00
{
2015-02-05 03:03:51 +00:00
ignore_objects_array_t ignore_obj_list ;
2006-03-20 17:12:09 +00:00
int try_again ;
2007-12-29 14:18:49 +00:00
int fate = 0 ;
2014-10-30 03:11:06 +00:00
vms_vector ipos ; //position after this frame
2013-12-29 04:28:07 +00:00
segnum_t WallHitSeg ;
int WallHitSide ;
2006-03-20 17:12:09 +00:00
fvi_info hit_info ;
fvi_query fq ;
vms_vector save_pos ;
fix drag ;
2013-03-30 20:29:29 +00:00
fix sim_time ;
2006-03-20 17:12:09 +00:00
vms_vector start_pos ;
int obj_stopped = 0 ;
fix moved_time ; //how long objected moved before hit something
physics_info * pi ;
2014-11-20 03:00:36 +00:00
auto orig_segnum = obj - > segnum ;
2006-03-20 17:12:09 +00:00
int bounced = 0 ;
2016-12-02 12:37:08 +00:00
bool Player_ScrapeFrame = false ;
2016-12-24 08:50:29 +00:00
auto result = window_event_result : : handled ;
2006-03-20 17:12:09 +00:00
Assert ( obj - > movement_type = = MT_PHYSICS ) ;
# ifndef NDEBUG
2006-03-21 14:01:57 +00:00
if ( Dont_move_ai_objects )
if ( obj - > control_type = = CT_AI )
2016-12-24 08:50:29 +00:00
return window_event_result : : ignored ;
2006-03-20 17:12:09 +00:00
# endif
pi = & obj - > mtype . phys_info ;
do_physics_sim_rot ( obj ) ;
if ( ! ( pi - > velocity . x | | pi - > velocity . y | | pi - > velocity . z | | pi - > thrust . x | | pi - > thrust . y | | pi - > thrust . z ) )
2016-12-24 08:50:29 +00:00
return window_event_result : : ignored ;
2006-03-20 17:12:09 +00:00
2014-08-17 21:56:08 +00:00
sim_time = FrameTime ;
2006-03-20 17:12:09 +00:00
start_pos = obj - > pos ;
//if uses thrust, cannot have zero drag
Assert ( ! ( obj - > mtype . phys_info . flags & PF_USES_THRUST ) | | obj - > mtype . phys_info . drag ! = 0 ) ;
//do thrust & drag
if ( ( drag = obj - > mtype . phys_info . drag ) ! = 0 ) {
int count ;
2008-09-30 00:07:07 +00:00
fix r , k , have_accel ;
2006-03-20 17:12:09 +00:00
2008-09-30 00:07:07 +00:00
count = FrameTime / FT ;
r = FrameTime % FT ;
2006-03-20 17:12:09 +00:00
k = fixdiv ( r , FT ) ;
if ( obj - > mtype . phys_info . flags & PF_USES_THRUST ) {
2014-11-02 03:43:47 +00:00
const auto accel = vm_vec_copy_scale ( obj - > mtype . phys_info . thrust , fixdiv ( f1_0 , obj - > mtype . phys_info . mass ) ) ;
2008-09-30 00:07:07 +00:00
have_accel = ( accel . x | | accel . y | | accel . z ) ;
2006-03-20 17:12:09 +00:00
while ( count - - ) {
2008-09-30 00:07:07 +00:00
if ( have_accel )
2014-09-28 21:43:00 +00:00
vm_vec_add2 ( obj - > mtype . phys_info . velocity , accel ) ;
2006-03-20 17:12:09 +00:00
2014-09-28 21:11:05 +00:00
vm_vec_scale ( obj - > mtype . phys_info . velocity , f1_0 - drag ) ;
2006-03-20 17:12:09 +00:00
}
//do linear scale on remaining bit of time
2014-09-28 21:43:14 +00:00
vm_vec_scale_add2 ( obj - > mtype . phys_info . velocity , accel , k ) ;
2008-09-30 00:07:07 +00:00
if ( drag )
2014-09-28 21:11:05 +00:00
vm_vec_scale ( obj - > mtype . phys_info . velocity , f1_0 - fixmul ( k , drag ) ) ;
2006-03-20 17:12:09 +00:00
}
2008-09-30 00:07:07 +00:00
else if ( drag )
{
2006-03-20 17:12:09 +00:00
fix total_drag = f1_0 ;
while ( count - - )
total_drag = fixmul ( total_drag , f1_0 - drag ) ;
//do linear scale on remaining bit of time
total_drag = fixmul ( total_drag , f1_0 - fixmul ( k , drag ) ) ;
2014-09-28 21:11:05 +00:00
vm_vec_scale ( obj - > mtype . phys_info . velocity , total_drag ) ;
2006-03-20 17:12:09 +00:00
}
}
2015-11-26 02:56:54 +00:00
int count = 0 ;
2006-03-20 17:12:09 +00:00
do {
try_again = 0 ;
//Move the object
2014-11-02 03:43:47 +00:00
const auto frame_vec = vm_vec_copy_scale ( obj - > mtype . phys_info . velocity , sim_time ) ;
2006-03-20 17:12:09 +00:00
if ( ( frame_vec . x = = 0 ) & & ( frame_vec . y = = 0 ) & & ( frame_vec . z = = 0 ) )
break ;
count + + ;
// If retry count is getting large, then we are trying to do something stupid.
2011-01-23 10:59:48 +00:00
if ( count > 8 ) break ; // in original code this was 3 for all non-player objects. still leave us some limit in case fvi goes apeshit.
2006-03-20 17:12:09 +00:00
2014-10-30 03:11:06 +00:00
const auto new_pos = vm_vec_add ( obj - > pos , frame_vec ) ;
2006-03-20 17:12:09 +00:00
fq . p0 = & obj - > pos ;
fq . startseg = obj - > segnum ;
fq . p1 = & new_pos ;
fq . rad = obj - > size ;
2014-01-11 22:37:36 +00:00
fq . thisobjnum = obj ;
2006-03-20 17:12:09 +00:00
fq . ignore_obj_list = ignore_obj_list ;
fq . flags = FQ_CHECK_OBJS ;
if ( obj - > type = = OBJ_WEAPON )
fq . flags | = FQ_TRANSPOINT ;
2017-08-02 02:49:13 +00:00
if ( phys_segs )
2006-03-20 17:12:09 +00:00
fq . flags | = FQ_GET_SEGLIST ;
2015-01-20 02:46:42 +00:00
fate = find_vector_intersection ( fq , hit_info ) ;
2006-03-20 17:12:09 +00:00
// Matt: Mike's hack.
if ( fate = = HIT_OBJECT ) {
2015-07-12 01:04:21 +00:00
const auto & & objp = vcobjptr ( hit_info . hit_object ) ;
2006-03-20 17:12:09 +00:00
2013-10-07 23:52:33 +00:00
if ( ( ( objp - > type = = OBJ_WEAPON ) & & is_proximity_bomb_or_smart_mine ( get_weapon_id ( objp ) ) ) | | objp - > type = = OBJ_POWERUP ) // do not increase count for powerups since they *should* not change our movement
2006-03-20 17:12:09 +00:00
count - - ;
}
2006-03-21 14:01:57 +00:00
# ifndef NDEBUG
2006-03-20 17:12:09 +00:00
if ( fate = = HIT_BAD_P0 ) {
Int3 ( ) ;
}
2006-03-21 14:01:57 +00:00
# endif
2006-03-20 17:12:09 +00:00
2017-08-02 02:49:13 +00:00
if ( phys_segs & & ! hit_info . seglist . empty ( ) )
{
auto n_phys_segs = phys_segs - > nsegs ;
if ( n_phys_segs & & phys_segs - > seglist [ n_phys_segs - 1 ] = = hit_info . seglist [ 0 ] )
2006-03-20 17:12:09 +00:00
n_phys_segs - - ;
2013-12-22 16:04:18 +00:00
range_for ( const auto & hs , hit_info . seglist )
{
2017-08-02 02:49:13 +00:00
if ( ! ( n_phys_segs < phys_segs - > seglist . size ( ) - 1 ) )
2013-12-22 16:04:18 +00:00
break ;
2017-08-02 02:49:13 +00:00
phys_segs - > seglist [ n_phys_segs + + ] = hs ;
2013-12-22 16:04:18 +00:00
}
2017-08-02 02:49:13 +00:00
phys_segs - > nsegs = n_phys_segs ;
2006-03-20 17:12:09 +00:00
}
ipos = hit_info . hit_pnt ;
2014-11-20 03:00:36 +00:00
auto iseg = hit_info . hit_seg ;
2006-03-20 17:12:09 +00:00
WallHitSide = hit_info . hit_side ;
WallHitSeg = hit_info . hit_side_seg ;
2013-12-26 22:21:16 +00:00
if ( iseg = = segment_none ) { //some sort of horrible error
2006-03-20 17:12:09 +00:00
if ( obj - > type = = OBJ_WEAPON )
obj - > flags | = OF_SHOULD_BE_DEAD ;
break ;
}
2013-12-26 22:21:16 +00:00
Assert ( ! ( ( fate = = HIT_WALL ) & & ( ( WallHitSeg = = segment_none ) | | ( WallHitSeg > Highest_segment_index ) ) ) ) ;
2006-03-20 17:12:09 +00:00
save_pos = obj - > pos ; //save the object's position
2014-11-20 03:00:36 +00:00
auto save_seg = obj - > segnum ;
2006-03-20 17:12:09 +00:00
// update object's position and segment number
obj - > pos = ipos ;
if ( iseg ! = obj - > segnum )
2018-03-12 03:43:46 +00:00
obj_relink ( vmobjptr , vmsegptr , obj , vmsegptridx ( iseg ) ) ;
2006-03-20 17:12:09 +00:00
//if start point not in segment, move object to center of segment
2017-08-11 23:43:54 +00:00
if ( get_seg_masks ( vcvertptr , obj - > pos , vcsegptr ( obj - > segnum ) , 0 ) . centermask ! = 0 )
2006-03-20 17:12:09 +00:00
{
2016-01-09 16:38:14 +00:00
auto n = find_object_seg ( obj ) ;
if ( n = = segment_none )
{
2006-03-20 17:12:09 +00:00
//Int3();
2017-06-10 03:31:02 +00:00
if ( obj - > type = = OBJ_PLAYER & & ( n = find_point_seg ( obj - > last_pos , vmsegptridx ( obj - > segnum ) ) ) ! = segment_none )
2016-01-09 16:38:13 +00:00
{
2006-03-20 17:12:09 +00:00
obj - > pos = obj - > last_pos ;
2018-03-12 03:43:46 +00:00
obj_relink ( vmobjptr , vmsegptr , obj , n ) ;
2006-03-20 17:12:09 +00:00
}
else {
2018-03-12 03:43:47 +00:00
compute_segment_center ( vcvertptr , obj - > pos , vcsegptr ( obj - > segnum ) ) ;
2014-01-11 22:37:36 +00:00
obj - > pos . x + = obj ;
2006-03-20 17:12:09 +00:00
}
if ( obj - > type = = OBJ_WEAPON )
obj - > flags | = OF_SHOULD_BE_DEAD ;
}
2016-12-24 08:50:29 +00:00
return window_event_result : : ignored ;
2006-03-20 17:12:09 +00:00
}
//calulate new sim time
{
//vms_vector moved_vec;
vms_vector moved_vec_n ;
fix attempted_dist , actual_dist ;
2014-10-01 02:28:41 +00:00
actual_dist = vm_vec_normalized_dir ( moved_vec_n , obj - > pos , save_pos ) ;
2006-03-20 17:12:09 +00:00
2014-09-28 21:11:48 +00:00
if ( fate = = HIT_WALL & & vm_vec_dot ( moved_vec_n , frame_vec ) < 0 ) { //moved backwards
2006-03-20 17:12:09 +00:00
//don't change position or sim_time
obj - > pos = save_pos ;
//iseg = obj->segnum; //don't change segment
2018-03-12 03:43:46 +00:00
obj_relink ( vmobjptr , vmsegptr , obj , vmsegptridx ( save_seg ) ) ;
2006-03-20 17:12:09 +00:00
moved_time = 0 ;
}
else {
2013-03-30 20:29:29 +00:00
fix old_sim_time ;
2006-03-20 17:12:09 +00:00
2014-09-28 21:11:03 +00:00
attempted_dist = vm_vec_mag ( frame_vec ) ;
2006-03-20 17:12:09 +00:00
2013-03-30 20:29:29 +00:00
old_sim_time = sim_time ;
2006-03-20 17:12:09 +00:00
sim_time = fixmuldiv ( sim_time , attempted_dist - actual_dist , attempted_dist ) ;
moved_time = old_sim_time - sim_time ;
if ( sim_time < 0 | | sim_time > old_sim_time ) {
sim_time = old_sim_time ;
//WHY DOES THIS HAPPEN??
moved_time = 0 ;
}
}
}
switch ( fate ) {
case HIT_WALL : {
2008-09-30 00:07:07 +00:00
fix hit_speed = 0 , wall_part = 0 ;
2011-04-13 19:08:11 +00:00
2006-03-20 17:12:09 +00:00
// Find hit speed
2014-10-29 03:24:31 +00:00
const auto moved_v = vm_vec_sub ( obj - > pos , save_pos ) ;
2006-03-20 17:12:09 +00:00
2014-09-28 21:11:48 +00:00
wall_part = vm_vec_dot ( moved_v , hit_info . hit_wallnorm ) ;
2006-03-20 17:12:09 +00:00
2012-03-28 09:02:30 +00:00
if ( ( wall_part ! = 0 & & moved_time > 0 & & ( hit_speed = - fixdiv ( wall_part , moved_time ) ) > 0 ) | | obj - > type = = OBJ_WEAPON | | obj - > type = = OBJ_DEBRIS )
2017-06-10 03:31:02 +00:00
result = collide_object_with_wall ( obj , hit_speed , vmsegptridx ( WallHitSeg ) , WallHitSide , hit_info . hit_pnt ) ;
2016-12-02 12:37:08 +00:00
/*
* Due to the nature of this loop , it ' s possible that a local player may receive scrape damage multiple times in one frame .
* Check if we received damage and do not apply more damage ( nor produce damage sounds / flashes / bumps , etc ) for the rest of the loop .
* It ' s possible that other walls later in the loop would still be valid for scraping but due to the generalized outcome , this should be negligible ( practical wall sliding is handled below ) .
* NOTE : Remote players will return false and never receive damage . But since we handle only one object ( remote or local ) per loop , this is no problem .
*/
if ( obj - > type = = OBJ_PLAYER & & Player_ScrapeFrame = = false )
2017-06-10 03:31:02 +00:00
Player_ScrapeFrame = scrape_player_on_wall ( obj , vmsegptridx ( WallHitSeg ) , WallHitSide , hit_info . hit_pnt ) ;
2006-03-20 17:12:09 +00:00
2013-12-26 22:21:16 +00:00
Assert ( WallHitSeg ! = segment_none ) ;
2006-03-20 17:12:09 +00:00
Assert ( WallHitSide > - 1 ) ;
if ( ! ( obj - > flags & OF_SHOULD_BE_DEAD ) ) {
int forcefield_bounce ; //bounce off a forcefield
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
if ( ! cheats . bouncyfire )
# endif
Assert ( ! ( obj - > mtype . phys_info . flags & PF_STICK & & obj - > mtype . phys_info . flags & PF_BOUNCE ) ) ; //can't be bounce and stick
# if defined(DXX_BUILD_DESCENT_I)
/*
* Force fields are not supported in Descent 1. Use
* this as a placeholder to make the code match the
* force field handling in Descent 2.
*/
forcefield_bounce = 0 ;
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
forcefield_bounce = ( TmapInfo [ Segments [ WallHitSeg ] . sides [ WallHitSide ] . tmap_num ] . flags & TMI_FORCE_FIELD ) ;
2013-03-03 01:03:33 +00:00
int check_vel = 0 ;
# endif
2006-03-20 17:12:09 +00:00
if ( ! forcefield_bounce & & ( obj - > mtype . phys_info . flags & PF_STICK ) ) { //stop moving
2017-06-10 03:31:02 +00:00
add_stuck_object ( obj , vmsegptr ( WallHitSeg ) , WallHitSide ) ;
2006-03-20 17:12:09 +00:00
2014-09-28 21:11:04 +00:00
vm_vec_zero ( obj - > mtype . phys_info . velocity ) ;
2006-03-20 17:12:09 +00:00
obj_stopped = 1 ;
try_again = 0 ;
}
else { // Slide object along wall
2014-09-28 21:11:48 +00:00
wall_part = vm_vec_dot ( hit_info . hit_wallnorm , obj - > mtype . phys_info . velocity ) ;
2006-03-20 17:12:09 +00:00
2011-04-07 20:49:42 +00:00
// if wall_part, make sure the value is sane enough to get usable velocity computed
if ( wall_part < 0 & & wall_part > - f1_0 ) wall_part = - f1_0 ;
if ( wall_part > 0 & & wall_part < f1_0 ) wall_part = f1_0 ;
2006-03-20 17:12:09 +00:00
if ( forcefield_bounce | | ( obj - > mtype . phys_info . flags & PF_BOUNCE ) ) { //bounce off wall
wall_part * = 2 ; //Subtract out wall part twice to achieve bounce
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
if ( forcefield_bounce ) {
check_vel = 1 ; //check for max velocity
if ( obj - > type = = OBJ_PLAYER )
wall_part * = 2 ; //player bounce twice as much
}
if ( obj - > mtype . phys_info . flags & PF_BOUNCES_TWICE ) {
Assert ( obj - > mtype . phys_info . flags & PF_BOUNCE ) ;
if ( obj - > mtype . phys_info . flags & PF_BOUNCED_ONCE )
obj - > mtype . phys_info . flags & = ~ ( PF_BOUNCE + PF_BOUNCED_ONCE + PF_BOUNCES_TWICE ) ;
else
obj - > mtype . phys_info . flags | = PF_BOUNCED_ONCE ;
}
bounced = 1 ; //this object bounced
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
}
2014-09-28 21:43:14 +00:00
vm_vec_scale_add2 ( obj - > mtype . phys_info . velocity , hit_info . hit_wallnorm , - wall_part ) ;
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
if ( check_vel ) {
2014-09-28 21:11:03 +00:00
fix vel = vm_vec_mag_quick ( obj - > mtype . phys_info . velocity ) ;
2006-03-20 17:12:09 +00:00
if ( vel > MAX_OBJECT_VEL )
2014-09-28 21:11:05 +00:00
vm_vec_scale ( obj - > mtype . phys_info . velocity , fixdiv ( MAX_OBJECT_VEL , vel ) ) ;
2006-03-20 17:12:09 +00:00
}
if ( bounced & & obj - > type = = OBJ_WEAPON )
2014-10-01 02:28:42 +00:00
vm_vector_2_matrix ( obj - > orient , obj - > mtype . phys_info . velocity , & obj - > orient . uvec , nullptr ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
try_again = 1 ;
}
}
2011-03-14 10:07:39 +00:00
2006-03-20 17:12:09 +00:00
break ;
}
case HIT_OBJECT : {
vms_vector old_vel ;
// Mark the hit object so that on a retry the fvi code
// ignores this object.
2013-12-26 22:21:16 +00:00
Assert ( hit_info . hit_object ! = object_none ) ;
2006-03-20 17:12:09 +00:00
// Calculcate the hit point between the two objects.
2014-10-29 03:24:31 +00:00
{
2006-03-20 17:12:09 +00:00
fix size0 , size1 ;
2015-12-22 04:18:51 +00:00
const auto & & hit = obj . absolute_sibling ( hit_info . hit_object ) ;
2014-11-02 03:43:04 +00:00
const auto & ppos0 = hit - > pos ;
const auto & ppos1 = obj - > pos ;
2014-08-23 23:53:56 +00:00
size0 = hit - > size ;
2006-03-20 17:12:09 +00:00
size1 = obj - > size ;
Assert ( size0 + size1 ! = 0 ) ; // Error, both sizes are 0, so how did they collide, anyway?!?
//vm_vec_scale(vm_vec_sub(&pos_hit, ppos1, ppos0), fixdiv(size0, size0 + size1));
//vm_vec_add2(&pos_hit, ppos0);
2014-11-02 03:43:04 +00:00
auto pos_hit = vm_vec_sub ( ppos1 , ppos0 ) ;
vm_vec_scale_add ( pos_hit , ppos0 , pos_hit , fixdiv ( size0 , size0 + size1 ) ) ;
2006-03-20 17:12:09 +00:00
old_vel = obj - > mtype . phys_info . velocity ;
2014-10-10 02:30:13 +00:00
collide_two_objects ( obj , hit , pos_hit ) ;
2006-03-20 17:12:09 +00:00
}
// Let object continue its movement
if ( ! ( obj - > flags & OF_SHOULD_BE_DEAD ) ) {
//obj->pos = save_pos;
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 ) ) {
//if (Objects[hit_info.hit_object].type == OBJ_POWERUP)
2015-02-05 03:03:51 +00:00
if ( ignore_obj_list . push_back ( hit_info . hit_object ) )
2006-03-20 17:12:09 +00:00
try_again = 1 ;
}
}
break ;
}
case HIT_NONE :
break ;
2006-03-21 14:01:57 +00:00
# ifndef NDEBUG
2006-03-20 17:12:09 +00:00
case HIT_BAD_P0 :
Int3 ( ) ; // Unexpected collision type: start point not in specified segment.
break ;
default :
// Unknown collision type returned from find_vector_intersection!!
Int3 ( ) ;
break ;
2006-03-21 14:01:57 +00:00
# endif
2006-03-20 17:12:09 +00:00
}
} while ( try_again ) ;
// Pass retry count info to AI.
if ( obj - > control_type = = CT_AI ) {
if ( count > 0 ) {
2013-12-25 03:16:41 +00:00
obj - > ctype . ai_info . ail . retry_count = count - 1 ;
2006-03-21 14:01:57 +00:00
# ifndef NDEBUG
2006-03-20 17:12:09 +00:00
Total_retries + = count - 1 ;
Total_sims + + ;
2006-03-21 14:01:57 +00:00
# endif
2006-03-20 17:12:09 +00:00
}
}
2008-09-30 00:07:07 +00:00
// After collision with objects and walls, set velocity from actual movement
2010-02-05 18:49:24 +00:00
if ( ! obj_stopped & & ! bounced
& & ( ( obj - > type = = OBJ_PLAYER ) | | ( obj - > type = = OBJ_ROBOT ) | | ( obj - > type = = OBJ_DEBRIS ) )
& & ( ( fate = = HIT_WALL ) | | ( fate = = HIT_OBJECT ) | | ( fate = = HIT_BAD_P0 ) )
)
2009-01-13 01:19:19 +00:00
{
2014-10-29 03:24:31 +00:00
const auto moved_vec = vm_vec_sub ( obj - > pos , start_pos ) ;
2014-09-28 21:43:14 +00:00
vm_vec_copy_scale ( obj - > mtype . phys_info . velocity , moved_vec , fixdiv ( f1_0 , FrameTime ) ) ;
2006-03-20 17:12:09 +00:00
}
2014-10-17 02:06:55 +00:00
fix_illegal_wall_intersection ( obj ) ;
2011-05-04 00:15:10 +00:00
2006-03-20 17:12:09 +00:00
//Assert(check_point_in_seg(&obj->pos,obj->segnum,0).centermask==0);
//if (obj->control_type == CT_FLYING)
if ( obj - > mtype . phys_info . flags & PF_LEVELLING )
do_physics_align_object ( obj ) ;
//hack to keep player from going through closed doors
2011-02-14 21:27:07 +00:00
if ( obj - > type = = OBJ_PLAYER & & obj - > segnum ! = orig_segnum & & ( ! cheats . ghostphysics ) ) {
2006-03-20 17:12:09 +00:00
2014-11-23 04:58:45 +00:00
const auto orig_segp = vcsegptr ( orig_segnum ) ;
2015-07-12 01:04:21 +00:00
const auto & & sidenum = find_connect_side ( vcsegptridx ( obj - > segnum ) , orig_segp ) ;
2016-01-03 20:21:35 +00:00
if ( sidenum ! = side_none )
{
2006-03-20 17:12:09 +00:00
2014-11-23 04:58:45 +00:00
if ( ! ( WALL_IS_DOORWAY ( orig_segp , sidenum ) & WID_FLY_FLAG ) ) {
2006-03-20 17:12:09 +00:00
fix dist ;
//bump object back
2017-02-19 19:33:38 +00:00
const auto s = & orig_segp - > sides [ sidenum ] ;
2006-03-20 17:12:09 +00:00
2015-10-18 21:01:20 +00:00
const auto v = create_abs_vertex_lists ( orig_segp , s , sidenum ) ;
2014-12-14 05:23:00 +00:00
const auto & vertex_list = v . second ;
2006-03-20 17:12:09 +00:00
//let's pretend this wall is not triangulated
2017-02-19 19:33:38 +00:00
const auto b = begin ( vertex_list ) ;
const auto vertnum = * std : : min_element ( b , std : : next ( b , 4 ) ) ;
2006-03-20 17:12:09 +00:00
2017-08-11 23:43:54 +00:00
dist = vm_dist_to_plane ( start_pos , s - > normals [ 0 ] , vcvertptr ( vertnum ) ) ;
2014-09-28 21:43:14 +00:00
vm_vec_scale_add ( obj - > pos , start_pos , s - > normals [ 0 ] , obj - > size - dist ) ;
2006-03-20 17:12:09 +00:00
update_object_seg ( obj ) ;
}
}
}
//--WE ALWYS WANT THIS IN, MATT AND MIKE DECISION ON 12/10/94, TWO MONTHS AFTER FINAL #ifndef NDEBUG
//if end point not in segment, move object to last pos, or segment center
2017-08-11 23:43:54 +00:00
if ( get_seg_masks ( vcvertptr , obj - > pos , vcsegptr ( obj - > segnum ) , 0 ) . centermask ! = 0 )
2006-03-20 17:12:09 +00:00
{
2013-12-26 22:21:16 +00:00
if ( find_object_seg ( obj ) = = segment_none ) {
2013-12-29 04:28:07 +00:00
segnum_t n ;
2006-03-20 17:12:09 +00:00
//Int3();
2017-06-10 03:31:02 +00:00
const auto & & obj_segp = vmsegptridx ( obj - > segnum ) ;
2015-11-19 03:23:34 +00:00
if ( obj - > type = = OBJ_PLAYER & & ( n = find_point_seg ( obj - > last_pos , obj_segp ) ) ! = segment_none )
{
2006-03-20 17:12:09 +00:00
obj - > pos = obj - > last_pos ;
2018-03-12 03:43:46 +00:00
obj_relink ( vmobjptr , vmsegptr , obj , vmsegptridx ( n ) ) ;
2006-03-20 17:12:09 +00:00
}
else {
2018-03-12 03:43:47 +00:00
compute_segment_center ( vcvertptr , obj - > pos , obj_segp ) ;
2014-01-11 22:37:36 +00:00
obj - > pos . x + = obj ;
2006-03-20 17:12:09 +00:00
}
if ( obj - > type = = OBJ_WEAPON )
obj - > flags | = OF_SHOULD_BE_DEAD ;
}
}
2016-12-24 08:50:29 +00:00
return result ;
2006-03-20 17:12:09 +00:00
//--WE ALWYS WANT THIS IN, MATT AND MIKE DECISION ON 12/10/94, TWO MONTHS AFTER FINAL #endif
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
2016-04-06 03:34:14 +00:00
namespace dcx {
2006-03-20 17:12:09 +00:00
//Applies an instantaneous force on an object, resulting in an instantaneous
//change in velocity.
2016-04-06 03:34:14 +00:00
void phys_apply_force ( object_base & obj , const vms_vector & force_vec )
2006-03-20 17:12:09 +00:00
{
2016-04-06 03:34:14 +00:00
if ( obj . movement_type ! = MT_PHYSICS )
2013-03-03 01:03:33 +00:00
return ;
2006-03-20 17:12:09 +00:00
// Put in by MK on 2/13/96 for force getting applied to Omega blobs, which have 0 mass,
// in collision with crazy reactor robot thing on d2levf-s.
2016-04-06 03:34:14 +00:00
if ( obj . mtype . phys_info . mass = = 0 )
2006-03-20 17:12:09 +00:00
return ;
//Add in acceleration due to force
2016-04-06 03:34:14 +00:00
vm_vec_scale_add2 ( obj . mtype . phys_info . velocity , force_vec , fixdiv ( f1_0 , obj . mtype . phys_info . mass ) ) ;
}
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------
// Do *dest = *delta unless:
// *delta is pretty small
// and they are of different signs.
2014-12-22 04:35:49 +00:00
static void physics_set_rotvel_and_saturate ( fix & dest , fix delta )
2006-03-20 17:12:09 +00:00
{
2014-12-22 04:35:49 +00:00
if ( ( delta ^ dest ) < 0 ) {
2006-03-20 17:12:09 +00:00
if ( abs ( delta ) < F1_0 / 8 ) {
2014-12-22 04:35:49 +00:00
dest = delta / 4 ;
2006-03-20 17:12:09 +00:00
} else
2014-12-22 04:35:49 +00:00
dest = delta ;
2006-03-20 17:12:09 +00:00
} else {
2014-12-22 04:35:49 +00:00
dest = delta ;
2006-03-20 17:12:09 +00:00
}
}
2014-11-02 03:42:02 +00:00
static inline vms_angvec vm_extract_angles_vector ( const vms_vector & v )
{
vms_angvec a ;
return vm_extract_angles_vector ( a , v ) , a ;
}
2006-03-20 17:12:09 +00:00
// ------------------------------------------------------------------------------------------------------
// Note: This is the old ai_turn_towards_vector code.
// phys_apply_rot used to call ai_turn_towards_vector until I fixed it, which broke phys_apply_rot.
2016-04-06 03:34:14 +00:00
void physics_turn_towards_vector ( const vms_vector & goal_vector , object_base & obj , fix rate )
2006-03-20 17:12:09 +00:00
{
fix delta_p , delta_h ;
// Make this object turn towards the goal_vector. Changes orientation, doesn't change direction of movement.
// If no one moves, will be facing goal_vector in 1 second.
// Detect null vector.
2014-10-02 03:02:36 +00:00
if ( ( goal_vector . x = = 0 ) & & ( goal_vector . y = = 0 ) & & ( goal_vector . z = = 0 ) )
2006-03-20 17:12:09 +00:00
return ;
// Make morph objects turn more slowly.
2016-04-06 03:34:14 +00:00
if ( obj . control_type = = CT_MORPH )
2006-03-20 17:12:09 +00:00
rate * = 2 ;
2014-11-02 03:42:02 +00:00
const auto dest_angles = vm_extract_angles_vector ( goal_vector ) ;
2016-04-06 03:34:14 +00:00
const auto cur_angles = vm_extract_angles_vector ( obj . orient . fvec ) ;
2006-03-20 17:12:09 +00:00
delta_p = ( dest_angles . p - cur_angles . p ) ;
delta_h = ( dest_angles . h - cur_angles . h ) ;
if ( delta_p > F1_0 / 2 ) delta_p = dest_angles . p - cur_angles . p - F1_0 ;
if ( delta_p < - F1_0 / 2 ) delta_p = dest_angles . p - cur_angles . p + F1_0 ;
if ( delta_h > F1_0 / 2 ) delta_h = dest_angles . h - cur_angles . h - F1_0 ;
if ( delta_h < - F1_0 / 2 ) delta_h = dest_angles . h - cur_angles . h + F1_0 ;
delta_p = fixdiv ( delta_p , rate ) ;
delta_h = fixdiv ( delta_h , rate ) ;
if ( abs ( delta_p ) < F1_0 / 16 ) delta_p * = 4 ;
if ( abs ( delta_h ) < F1_0 / 16 ) delta_h * = 4 ;
2016-04-06 03:34:14 +00:00
auto & rotvel_ptr = obj . mtype . phys_info . rotvel ;
2014-12-22 04:35:49 +00:00
physics_set_rotvel_and_saturate ( rotvel_ptr . x , delta_p ) ;
physics_set_rotvel_and_saturate ( rotvel_ptr . y , delta_h ) ;
2014-11-02 03:43:04 +00:00
rotvel_ptr . z = 0 ;
2006-03-20 17:12:09 +00:00
}
2016-04-06 03:34:14 +00:00
}
2016-04-06 03:34:14 +00:00
namespace dsx {
2006-03-20 17:12:09 +00:00
// -----------------------------------------------------------------------------
// Applies an instantaneous whack on an object, resulting in an instantaneous
// change in orientation.
2016-04-06 03:34:14 +00:00
void phys_apply_rot ( object & obj , const vms_vector & force_vec )
2006-03-20 17:12:09 +00:00
{
2015-02-14 22:48:28 +00:00
fix rate ;
2006-03-20 17:12:09 +00:00
2016-04-06 03:34:14 +00:00
if ( obj . movement_type ! = MT_PHYSICS )
2006-03-20 17:12:09 +00:00
return ;
2015-02-14 22:48:28 +00:00
auto vecmag = vm_vec_mag ( force_vec ) ;
if ( vecmag < F1_0 / 32 )
2006-03-20 17:12:09 +00:00
rate = 4 * F1_0 ;
2016-04-06 03:34:14 +00:00
else if ( vecmag < obj . mtype . phys_info . mass > > 11 )
2006-03-20 17:12:09 +00:00
rate = 4 * F1_0 ;
else {
2016-04-06 03:34:14 +00:00
rate = fixdiv ( obj . mtype . phys_info . mass , vecmag / 8 ) ;
if ( obj . type = = OBJ_ROBOT ) {
2006-03-20 17:12:09 +00:00
if ( rate < F1_0 / 4 )
rate = F1_0 / 4 ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-04-06 03:34:14 +00:00
obj . ctype . ai_info . SKIP_AI_COUNT = 2 ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
// Changed by mk, 10/24/95, claw guys should not slow down when attacking!
2013-10-07 23:52:33 +00:00
if ( ! Robot_info [ get_robot_id ( obj ) ] . thief & & ! Robot_info [ get_robot_id ( obj ) ] . attack_type ) {
2016-04-06 03:34:14 +00:00
if ( obj . ctype . ai_info . SKIP_AI_COUNT * FrameTime < 3 * F1_0 / 4 ) {
2006-03-20 17:12:09 +00:00
fix tval = fixdiv ( F1_0 , 8 * FrameTime ) ;
int addval ;
addval = f2i ( tval ) ;
if ( ( d_rand ( ) * 2 ) < ( tval & 0xffff ) )
addval + + ;
2016-04-06 03:34:14 +00:00
obj . ctype . ai_info . SKIP_AI_COUNT + = addval ;
2006-03-20 17:12:09 +00:00
}
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
} else {
if ( rate < F1_0 / 2 )
rate = F1_0 / 2 ;
}
}
// Turn amount inversely proportional to mass. Third parameter is seconds to do 360 turn.
2014-10-26 21:37:34 +00:00
physics_turn_towards_vector ( force_vec , obj , rate ) ;
2016-04-06 03:34:14 +00:00
}
2006-03-20 17:12:09 +00:00
}
2016-07-15 03:43:01 +00:00
namespace dcx {
2006-03-20 17:12:09 +00:00
//this routine will set the thrust for an object to a value that will
//(hopefully) maintain the object's current velocity
2016-07-15 03:43:01 +00:00
void set_thrust_from_velocity ( object_base & obj )
2006-03-20 17:12:09 +00:00
{
2016-07-15 03:43:01 +00:00
Assert ( obj . movement_type = = MT_PHYSICS ) ;
auto & phys_info = obj . mtype . phys_info ;
vm_vec_copy_scale ( phys_info . thrust , phys_info . velocity ,
fixmuldiv ( phys_info . mass , phys_info . drag , F1_0 - phys_info . drag )
) ;
}
2006-03-20 17:12:09 +00:00
}