@ -263,9 +263,17 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// Damage particles
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					if ( m_fHealth  < =  460.0f  & &  GetStatus ( )  ! =  STATUS_WRECKED  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					   Abs ( GetPosition ( ) . x  -  TheCamera . GetPosition ( ) . x )  <  200.0f  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					   Abs ( GetPosition ( ) . y  -  TheCamera . GetPosition ( ) . y )  <  200.0f  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					   CTimer : : GetLogicalFramesPassed ( )  )  // Fix high-FPS particle spam
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					if ( m_fHealth  < =  460.0f  & &  GetStatus ( )  ! =  STATUS_WRECKED  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					   Abs ( GetPosition ( ) . x  -  TheCamera . GetPosition ( ) . x )  <  200.0f  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					   Abs ( GetPosition ( ) . y  -  TheCamera . GetPosition ( ) . y )  <  200.0f ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						float  speedSq  =  m_vecMoveSpeed . MagnitudeSqr ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						CVector  smokeDir  =  0.8f * m_vecMoveSpeed ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						CVector  smokePos ; 
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -335,6 +343,7 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							bIsDrowning  =  false ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						// Apply buoyancy impulse the first time (why twice?)
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_fVolumeUnderWater  =  mod_Buoyancy . m_volumeUnderWater ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_vecBuoyancePoint  =  buoyancePoint ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( GetModelIndex ( )  = =  MI_SKIMMER  & &  GetUp ( ) . z  <  - 0.5f  & &  Abs ( m_vecMoveSpeed . x )  <  0.2f  & &  Abs ( m_vecMoveSpeed . y )  <  0.2f ) 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -344,13 +353,17 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( bSeparateTurnForce ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							ApplyTurnForce ( 0.4f * buoyanceImpulse ,  buoyancePoint ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						// TODO: what is this?
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( GetModelIndex ( )  = =  MI_SKIMMER ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							if ( m_skimmerThingTimer  ! =  0.0f  | | 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							   GetForward ( ) . z  <  - 0.5f  & &  GetUp ( ) . z  >  - 0.5f  & &  m_vecMoveSpeed . z  <  - 0.15f  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							   buoyanceImpulse . z  >  0.01f * m_fMass  *  GRAVITY * CTimer : : GetTimeStep ( )  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							   buoyanceImpulse . z  <  0.4f * m_fMass  *  GRAVITY * CTimer : : GetTimeStep ( ) ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								// buoyanceImpulse already has a factor of timestep in it
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								float  turnImpulse  =  - 0.00017f * GetForward ( ) . z * buoyanceImpulse . z  *  m_fMass * CTimer : : GetDefaultTimeStep ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								float  turnImpulse  =  - 0.00017f * GetForward ( ) . z * buoyanceImpulse . z  *  m_fMass * CTimer : : GetTimeStep ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								ApplyTurnForce ( turnImpulse * GetForward ( ) ,  GetUp ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								bBoatInWater  =  false ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								//BUG? aren't we forgetting the timestep here?
 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -362,15 +375,21 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									m_skimmerThingTimer  =  0.0f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						// Apply buoyancy impulse the second time (why twice?)
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( ! onLand  & &  bBoatInWater  & &  GetUp ( ) . z  >  0.0f ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							// buoyanceImpulse already has a factor of timestep in it
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  impulse  =  m_vecMoveSpeed . MagnitudeSqr ( ) * pBoatHandling - > fAqPlaneForce * buoyanceImpulse . z * CTimer : : GetDefaultTimeStep ( ) * 0.5f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  impulse  =  m_vecMoveSpeed . MagnitudeSqr ( ) * pBoatHandling - > fAqPlaneForce * buoyanceImpulse . z * CTimer : : GetTimeStep ( ) * 0.5f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							if ( GetModelIndex ( )  = =  MI_SKIMMER ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								impulse  * =  1.0f  +  m_fGasPedal ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							else  if ( m_fGasPedal  >  0.05f ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								impulse  * =  m_fGasPedal ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								impulse  =  0.0f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							impulse  =  Min ( impulse ,  GRAVITY * pBoatHandling - > fAqPlaneLimit * m_fMass * CTimer : : GetTimeStep ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							impulse  =  Min ( impulse ,  GRAVITY * pBoatHandling - > fAqPlaneLimit * m_fMass * CTimer : : GetTimeStep ( ) ) ;   // Both sides have a factor of TimeStep, therefore this Min() is not a problem at high FPS
  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							ApplyMoveForce ( impulse * GetUp ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							ApplyTurnForce ( impulse * GetUp ( ) ,  buoyancePoint  -  pBoatHandling - > fAqPlaneOffset * GetForward ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						} 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -378,7 +397,11 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						// Handle boat moving forward
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						float  fwdSpeed  =  1.0f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( Abs ( m_fGasPedal )  >  0.05f  | |  ( fwdSpeed  =  m_vecMoveSpeed . Magnitude2D ( ) )  >  0.01f ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							if ( bBoatInWater  & &  fwdSpeed  >  0.05f  & &  CTimer : : GetLogicalFramesPassed ( ) )  // Fix super-short wake trail at high FPS
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							if ( bBoatInWater  & &  fwdSpeed  >  0.05f ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								AddWakePoint ( GetPosition ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  steerFactor  =  1.0f ; 
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -433,7 +456,11 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									// Spray some particles
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									CVector  jetDir  =  - 0.04f  *  force ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									if ( m_fGasPedal  >  0.0f  & &  CTimer : : GetLogicalFramesPassed ( ) ) {   // Fix high-FPS particle spam
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									if ( m_fGasPedal  >  0.0f ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
										if ( GetStatus ( )  = =  STATUS_PLAYER ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
											CVector  sternPos  =  GetColModel ( ) - > boundingBox . min ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
											sternPos . x  =  0.0f ; 
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -475,7 +502,11 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									CVector  propellerForce  =  propellerDepth  *  Multiply3x3 ( GetMatrix ( ) ,  force * CVector ( - steerSin ,  0.0f ,  0.0f ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									ApplyMoveForce ( propellerForce  *  CTimer : : GetTimeStep ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									ApplyTurnForce ( propellerForce  *  CTimer : : GetTimeStep ( ) ,  propeller ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									float  rightForce  =  - steerSin  *  force  *  0.75f / steerFactor  *  CTimer : : GetTimeStep ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									float  rightForce  =  - steerSin  *  force  *  0.75f / steerFactor  *  Max ( CTimer : : GetTimeStep ( ) ,  0.01f ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									ApplyTurnForce ( GetRight ( )  *  rightForce ,  GetUp ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							} else 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -485,7 +516,12 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								CVector  right  =  CrossProduct ( GetForward ( ) ,  CVector ( 0.0f ,  0.0f ,  1.0f ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								float  rightSpeed  =  DotProduct ( m_vecMoveSpeed ,  right ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								float  impulse  =  0.1f * pHandling - > fSuspensionBias  *  m_fMass  *  m_fVolumeUnderWater  *  rightSpeed  *  CTimer : : GetTimeStep ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								ApplyMoveForce ( right  -  impulse  *  0.3f  *  CVector ( - right . y ,  right . x ,  0.0f ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								// Fix boat perf at high FPS: ensure both terms have a (correct) factor of timestep before doing subtraction
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								ApplyMoveForce ( right  *  CTimer : : GetTimeStepFix ( )  -  impulse  *  0.3f  *  CVector ( - right . y ,  right . x ,  0.0f ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								ApplyMoveForce ( right                             -  impulse  *  0.3f  *  CVector ( - right . y ,  right . x ,  0.0f ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							if ( GetStatus ( )  = =  STATUS_PLAYER  & &  CPad : : GetPad ( 0 ) - > GetHandBrake ( ) ) { 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -503,25 +539,45 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_vecMoveSpeed . y  =  Min ( m_vecMoveSpeed . y ,  - ( GetPosition ( ) . y  -  ( WORLD_MAX_Y - 100.0f ) ) * 0.01f ) ; 	// north
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_vecMoveSpeed . y  =  Max ( m_vecMoveSpeed . y ,  - ( GetPosition ( ) . y  -  ( WORLD_MIN_Y + 100.0f ) ) * 0.01f ) ; 	// south
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						// Apply water resistance to linear movement
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( ! onLand  & &  bBoatInWater  & &  ! bSeparateTurnForce ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							ApplyWaterResistance ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						// Apply water resistance to rotation
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( ( GetModelIndex ( )  ! =  MI_SKIMMER  | |  m_skimmerThingTimer  = =  0.0f )  & &  ! bSeparateTurnForce ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							// No idea what exactly is going on here besides drag in YZ
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							// Rockstar's attempts to make this framerate independent are totally wrong.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							// Rules of thumb: 
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							//   - use Pow(x,time) if you multiply the result into the velocity
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							//   - use x*time if you add the result into the velocity
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							// We have to disable one of these Pow() methods and then add our own correction at the end.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  fxfake  =  Pow ( pBoatHandling - > vecTurnRes . x ,  CTimer : : GetDefaultTimeStep ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  fy      =  Pow ( pBoatHandling - > vecTurnRes . y ,  CTimer : : GetTimeStep ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  fz      =  Pow ( pBoatHandling - > vecTurnRes . z ,  CTimer : : GetTimeStep ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							m_vecTurnSpeed  =  Multiply3x3 ( m_vecTurnSpeed ,  GetMatrix ( ) ) ; 	// invert - to local space
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  drag  =  1.0f / ( 1000.0f  *  SQR ( m_vecTurnSpeed . x )  +  1.0f )  *  fxfake ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							m_vecTurnSpeed . y  * =  fy ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							m_vecTurnSpeed . z  * =  fz ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  forceUp  =  - ( 1.0f  -  drag )  *  m_vecTurnSpeed . x  *  m_fTurnMass ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							m_vecTurnSpeed  =  Multiply3x3 ( GetMatrix ( ) ,  m_vecTurnSpeed ) ; 	// back to world
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							CVector  com  =  Multiply3x3 ( GetMatrix ( ) ,  m_vecCentreOfMass ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							ApplyTurnForce ( forceUp * GetUp ( )  *  CTimer : : GetTimeStepFix ( ) ,  com  +  GetForward ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  fx  =  Pow ( pBoatHandling - > vecTurnRes . x ,  CTimer : : GetTimeStep ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  fy  =  Pow ( pBoatHandling - > vecTurnRes . y ,  CTimer : : GetTimeStep ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  fz  =  Pow ( pBoatHandling - > vecTurnRes . z ,  CTimer : : GetTimeStep ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							m_vecTurnSpeed  =  Multiply3x3 ( m_vecTurnSpeed ,  GetMatrix ( ) ) ; 	// invert - to local space
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							// TODO: figure this out
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  magic  =  1.0f / ( 1000.0f  *  SQR ( m_vecTurnSpeed . x )  +  1.0f )  *  fx ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  drag  =  1.0f / ( 1000.0f  *  SQR ( m_vecTurnSpeed . x )  +  1.0f )  *  fx ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							m_vecTurnSpeed . y  * =  fy ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							m_vecTurnSpeed . z  * =  fz ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  forceUp  =  ( magic  -  1.0f )  *  m_vecTurnSpeed . x  *  m_fTurnMass ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  forceUp  =  ( drag  -  1.0f )  *  m_vecTurnSpeed . x  *  m_fTurnMass ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							m_vecTurnSpeed  =  Multiply3x3 ( GetMatrix ( ) ,  m_vecTurnSpeed ) ; 	// back to world
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							CVector  com  =  Multiply3x3 ( GetMatrix ( ) ,  m_vecCentreOfMass ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							ApplyTurnForce ( forceUp * GetUp ( ) ,  com  +  GetForward ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_nDeltaVolumeUnderWater  =  ( m_fVolumeUnderWater - m_fPrevVolumeUnderWater ) * 10000 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						// Falling into water
 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -539,6 +595,9 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								speedFwd  * =  - m_nDeltaVolumeUnderWater  *  0.01f  *  pHandling - > fBrakeBias ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								CVector  speed  =  speedFwd * GetForward ( )  +  CVector ( 0.0f ,  0.0f ,  speedUp ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								CVector  splashImpulse  =  speed  *  m_fMass ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								splashImpulse  * =  CTimer : : GetTimeStepFix ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								ApplyMoveForce ( splashImpulse ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								ApplyTurnForce ( splashImpulse ,  buoyancePoint ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							} 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -546,8 +605,15 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						// Splashes
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						float  speed  =  m_vecMoveSpeed . Magnitude ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( speed  >  0.05f  & &  GetUp ( ) . x  >  0.0f  & &  ! TheCamera . GetLookingForwardFirstPerson ( )  & &  IsVisible ( )  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						   ( AutoPilot . m_nCarMission  ! =  MISSION_CRUISE  | |  ( CTimer : : GetFrameCounter ( ) & 2 )  = =  0 ) ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						   ( AutoPilot . m_nCarMission  ! =  MISSION_CRUISE  | |  ( CTimer : : GetFrameCounter ( ) & 2 )  = =  0 )  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						   CTimer : : GetLogicalFramesPassed ( )  )  // Fix particle spam at high FPS
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( speed  >  0.05f  & &  GetUp ( ) . x  >  0.0f  & &  ! TheCamera . GetLookingForwardFirstPerson ( )  & &  IsVisible ( )  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						   ( AutoPilot . m_nCarMission  ! =  MISSION_CRUISE  | |  ( CTimer : : GetFrameCounter ( ) & 2 )  = =  0 ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							CVector  splashPos ,  splashDir ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  splashSize ,  front ,  waterLevel ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -682,8 +748,14 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						// Spray waterdrops on screen
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( TheCamera . GetLookingForwardFirstPerson ( )  & &  FindPlayerVehicle ( )  & &  FindPlayerVehicle ( ) - > IsBoat ( )  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						   m_nDeltaVolumeUnderWater  >  0  & &  numWaterDropOnScreen  <  20  & &  CTimer : : GetLogicalFramesPassed ( ) )  // Fix particle spam at high FPS
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( TheCamera . GetLookingForwardFirstPerson ( )  & &  FindPlayerVehicle ( )  & &  FindPlayerVehicle ( ) - > IsBoat ( )  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						   m_nDeltaVolumeUnderWater  >  0  & &  numWaterDropOnScreen  <  20 ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						   m_nDeltaVolumeUnderWater  >  0  & &  numWaterDropOnScreen  <  20 ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							CVector  dropPos ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							CVector  dropDir ( CGeneral : : GetRandomNumberInRange ( - 0.25f ,  0.25f ) ,  CGeneral : : GetRandomNumberInRange ( 1.0f ,  0.75f ) ,  0.0f ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -714,7 +786,13 @@ CBoat::ProcessControl(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								numWaterDropOnScreen + + ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( m_fPrevVolumeUnderWater  = =  0.0f  & &  m_fVolumeUnderWater  >  0.0f  & &  GetModelIndex ( )  = =  MI_SKIMMER ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( m_fPrevVolumeUnderWater  = =  0.0f  & &  m_fVolumeUnderWater  >  0.0f  & &  GetModelIndex ( )  = =  MI_SKIMMER  & & 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						CTimer : : GetLogicalFramesPassed ( ) )  // Fix particle spam at high FPS
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if ( m_fPrevVolumeUnderWater  = =  0.0f  & &  m_fVolumeUnderWater  >  0.0f  & &  GetModelIndex ( )  = =  MI_SKIMMER ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							CVector  splashDir ( 0.0f ,  0.0f ,  0.25f * speed ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							CVector  splashPos  =  GetPosition ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							float  level ; 
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -773,6 +851,18 @@ CBoat::ProcessControlInputs(uint8 pad)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_fBrake  + =  ( CPad : : GetPad ( pad ) - > GetBrake ( ) / 255.0f  -  m_fBrake ) * 0.1f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_fBrake  =  Clamp ( m_fBrake ,  0.0f ,  1.0f ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// Fix accelerator control and steering control ramp rates at high FPS
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					if ( m_fBrake  <  0.05f ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_fBrake  =  0.0f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_fAccelerate  + =  ( CPad : : GetPad ( pad ) - > GetAccelerate ( ) / 255.0f  -  m_fAccelerate ) * 0.1f * CTimer : : GetTimeStepFix ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_fAccelerate  =  Clamp ( m_fAccelerate ,  0.0f ,  1.0f ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					} else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_fAccelerate  =  - m_fBrake * 0.3f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_fSteeringLeftRight  + =  ( - CPad : : GetPad ( pad ) - > GetSteeringLeftRight ( ) / 128.0f  -  m_fSteeringLeftRight ) * 0.2f * CTimer : : GetTimeStepFix ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_fSteeringLeftRight  =  Clamp ( m_fSteeringLeftRight ,  - 1.0f ,  1.0f ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					if ( m_fBrake  <  0.05f ) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_fBrake  =  0.0f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_fAccelerate  + =  ( CPad : : GetPad ( pad ) - > GetAccelerate ( ) / 255.0f  -  m_fAccelerate ) * 0.1f ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -782,6 +872,7 @@ CBoat::ProcessControlInputs(uint8 pad)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_fSteeringLeftRight  + =  ( - CPad : : GetPad ( pad ) - > GetSteeringLeftRight ( ) / 128.0f  -  m_fSteeringLeftRight ) * 0.2f ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_fSteeringLeftRight  =  Clamp ( m_fSteeringLeftRight ,  - 1.0f ,  1.0f ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  steeringSq  =  m_fSteeringLeftRight  <  0.0f  ?  - SQR ( m_fSteeringLeftRight )  :  SQR ( m_fSteeringLeftRight ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_fSteerAngle  =  pHandling - > fSteeringLock  *  DEGTORAD ( steeringSq ) ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -793,6 +884,82 @@ float fSeaPlaneWaterResistance = 30.0f;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				CBoat : : ApplyWaterResistance ( void ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifdef FIX_BUGS 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// TODO: confirm if the explanation below makes sense
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  depthResistance  =  0.001f  *  pHandling - > fSuspensionForceLevel  *  SQR ( m_fVolumeUnderWater )  *  m_fMass ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					if ( GetModelIndex ( )  = =  MI_SKIMMER ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						depthResistance  * =  fSeaPlaneWaterResistance ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  fwdSpeed  =  DotProduct ( GetMoveSpeed ( ) ,  GetForward ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// Water resistances goes up with the square of boat speed (in real life it goes up by the
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// cube? close enough!).  An extra 0.05f fudge factor was probably put in to make sure the
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// boat still has resistance at low speeds (ie auto-brakes to standstill).
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  waterResistance  =  ( SQR ( fwdSpeed )  +  0.05f )  *  Abs ( depthResistance ) ;   // Abs() used defensively, negative numbers stuff things up later
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// waterResistance will now be a small number like 0.002 or 0.015
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// An odd use of Abs() was in the original binary.  It's possible that the developers did not
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// put this in intentionally, instead the compiler may have silently added it to avoid
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// Pow() having to deal	with negative numbers to a fractional power (undefined) later.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// Regardless it was done badly, making assumptions like vecMoveRes never accidentally
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// being negative, so the use of Abs() has changed a little bit in this FIX_BUGS.  In
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// real gameplay these corner cases should rarely (never?) be encountered anyway.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// Our boat has different water resistances when travelling forwards (y axis) versus
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// sideways (x axis).  Boats tend to find it hard to move sideways.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  rx  =  Abs ( pBoatHandling - > vecMoveRes . x / ( waterResistance  +  1.0f ) ) ;  // Abs() used defensively, negative numbers stuff things up later
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  ry  =  Abs ( pBoatHandling - > vecMoveRes . y / ( waterResistance  +  1.0f ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  rz  =  Abs ( pBoatHandling - > vecMoveRes . z / ( waterResistance  +  1.0f ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// These rx, ry, rz resistance numbers will each be something like 0.8 or 0.9 or so
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// Fun fact: the above equations are _approximately_ the same as:
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//         pBoatHandling->vecMoveRes.x * (1.0f - waterResistance)
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// If you change the equations to this then boating feels about the same in-game.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// Which version makes more sense compared to physics in real life?  Probably neither :P
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// This second version of the equation is a little more efficient however (no division).
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// Now how do we apply these rx ry rz resistance numbers to the boat speed?
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// It's not simple:
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//  - We can't multiply them into the speed once per frame, because then players with
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//    higher framerates will get a lot more friction when boating (lower top speed).
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//  - We can't linearly modify each r number based off frametime, as higher FPS players
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//    will still end up with more friction.  This is for the same reason why linearly
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//    reducing your bank account's yearly interest into monthly amounts but then
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//    compounding it monthly will yield you more money than just compounding it yearly.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//  - We could try compounding each r number based off how many fixed units of time have
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//    passed (eg multiply itself by itself for every 1ms elapsed this frame).  This will
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//    work fairly regardless of framerate.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// We don't actually have to limit ourselves to a fixed time unit (like 1ms chunks),
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// instead we can raise the resistance to some power of time using Pow().
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  rrx      =  Pow ( rx ,  0.5f * CTimer : : GetTimeStep ( ) ) ;   // Why 0.5f?  Taste?
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  rry      =  Pow ( ry ,  0.5f * CTimer : : GetTimeStep ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  rrz      =  Pow ( rz ,  0.5f * CTimer : : GetTimeStep ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  rryfake  =  Pow ( ry ,  0.5f * CTimer : : GetDefaultTimeStep ( ) ) ;   // Fudge factor needed for other equations to make sense at high FPS
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_vecMoveSpeed  =  Multiply3x3 ( m_vecMoveSpeed ,  GetMatrix ( ) ) ; 	// convert velocities to boat-local space (y = boat forwards, x = sideways, z = up/down)
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_vecMoveSpeed . x  * =  rrx ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_vecMoveSpeed . y  * =  rry ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_vecMoveSpeed . z  * =  rrz ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  force  =  ( rryfake  -  1.0f )  *  m_vecMoveSpeed . y  *  m_fMass ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					m_vecMoveSpeed  =  Multiply3x3 ( GetMatrix ( ) ,  m_vecMoveSpeed ) ; 	// back to world space
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// WTH is this for?
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					ApplyTurnForce ( force * GetForward ( ) * CTimer : : GetTimeStepFix ( ) ,  - GetUp ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// What the hell?  Why arbitrarily compound in one more factor of rrz?
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// This is framerate dependent!  Bah!  I suspect it has very little effect.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					/*
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					if ( m_vecMoveSpeed . z  >  0.0f ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_vecMoveSpeed . z  * =  rrz ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_vecMoveSpeed . z  * =  ( 1.0f  -  rrz ) * 0.5f  +  rrz ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					*/ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					// TODO: figure out how this works
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					float  resistance  =  0.001f  *  pHandling - > fSuspensionForceLevel  *  SQR ( m_fVolumeUnderWater )  *  m_fMass ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					if ( GetModelIndex ( )  = =  MI_SKIMMER ) 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -817,6 +984,7 @@ CBoat::ApplyWaterResistance(void)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_vecMoveSpeed . z  * =  fz ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						m_vecMoveSpeed . z  * =  ( 1.0f  -  fz ) * 0.5f  +  fz ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				RwObject *