2014-10-14 13:11:37 +00:00
/*
* This file is part of the Colobot : Gold Edition source code
2020-07-07 08:19:36 +00:00
* Copyright ( C ) 2001 - 2020 , Daniel Roux , EPSITEC SA & TerranovaTeam
2015-08-22 14:40:02 +00:00
* http : //epsitec.ch; http://colobot.info; http://github.com/colobot
2014-10-14 13:11:37 +00:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
* See the GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see http : //gnu.org/licenses
*/
2012-06-26 20:23:05 +00:00
2012-10-17 19:55:45 +00:00
# include "physics/physics.h"
2012-06-26 20:23:05 +00:00
2013-02-16 21:37:43 +00:00
# include "app/app.h"
2012-06-26 20:23:05 +00:00
# include "common/event.h"
2012-10-17 19:55:45 +00:00
# include "common/global.h"
2015-07-17 18:36:01 +00:00
# include "common/make_unique.h"
2012-10-17 19:55:45 +00:00
# include "graphics/engine/camera.h"
# include "graphics/engine/engine.h"
2012-09-10 21:29:38 +00:00
# include "graphics/engine/lightman.h"
2015-06-22 19:58:58 +00:00
# include "graphics/engine/pyro_manager.h"
2012-09-10 21:29:38 +00:00
# include "graphics/engine/terrain.h"
# include "graphics/engine/water.h"
2012-10-17 19:55:45 +00:00
2015-08-13 09:47:32 +00:00
# include "level/robotmain.h"
# include "level/parser/parserline.h"
# include "level/parser/parserparam.h"
2012-10-17 19:55:45 +00:00
# include "math/geometry.h"
2015-06-20 18:02:40 +00:00
# include "object/object_manager.h"
2015-07-12 11:32:50 +00:00
# include "object/old_object.h"
2015-08-02 11:09:48 +00:00
2015-07-10 20:13:39 +00:00
# include "object/interface/carrier_object.h"
2015-07-10 20:11:22 +00:00
# include "object/interface/jostleable_object.h"
2015-07-10 21:47:59 +00:00
# include "object/interface/powered_object.h"
2015-07-10 17:03:27 +00:00
# include "object/interface/transportable_object.h"
2012-06-26 20:23:05 +00:00
2015-08-02 11:09:48 +00:00
# include "object/motion/motion.h"
# include "object/motion/motionhuman.h"
# include "object/motion/motionvehicle.h"
2015-08-17 11:19:21 +00:00
# include "object/subclass/base_alien.h"
2015-08-02 11:09:48 +00:00
# include "object/task/task.h"
2015-08-31 19:47:55 +00:00
# include "sound/sound.h"
2012-10-17 19:55:45 +00:00
2012-06-26 20:23:05 +00:00
const float LANDING_SPEED = 3.0f ;
const float LANDING_ACCEL = 5.0f ;
const float LANDING_ACCELh = 1.5f ;
// Object's constructor.
2015-07-12 11:32:50 +00:00
CPhysics : : CPhysics ( COldObject * object )
2012-06-26 20:23:05 +00:00
{
m_object = object ;
2013-02-16 21:37:43 +00:00
m_engine = Gfx : : CEngine : : GetInstancePointer ( ) ;
m_lightMan = m_engine - > GetLightManager ( ) ;
m_particle = m_engine - > GetParticle ( ) ;
m_water = m_engine - > GetWater ( ) ;
m_terrain = CRobotMain : : GetInstancePointer ( ) - > GetTerrain ( ) ;
m_camera = CRobotMain : : GetInstancePointer ( ) - > GetCamera ( ) ;
m_sound = CApplication : : GetInstancePointer ( ) - > GetSound ( ) ;
m_motion = nullptr ;
2012-06-26 20:23:05 +00:00
m_gravity = 9.81f ; // default gravity
m_time = 0.0f ;
m_timeUnderWater = 0.0f ;
m_motorSpeed = Math : : Vector ( 0.0f , 0.0f , 0.0f ) ;
m_bMotor = false ;
m_bLand = true ; // ground
m_bSwim = false ; // in air
m_bCollision = false ;
m_bObstacle = false ;
m_repeatCollision = 0 ;
m_linVibrationFactor = 1.0f ;
m_cirVibrationFactor = 1.0f ;
m_inclinaisonFactor = 1.0f ;
2012-09-10 21:29:38 +00:00
m_lastPowerParticle = 0.0f ;
m_lastSlideParticle = 0.0f ;
m_lastMotorParticle = 0.0f ;
m_lastWaterParticle = 0.0f ;
m_lastUnderParticle = 0.0f ;
m_lastPloufParticle = 0.0f ;
m_lastFlameParticle = 0.0f ;
m_bWheelParticleBrake = false ;
2012-06-26 20:23:05 +00:00
m_absorbWater = 0.0f ;
m_reactorTemperature = 0.0f ;
m_timeReactorFail = 0.0f ;
m_lastEnergy = 0.0f ;
m_lastSoundWater = 0.0f ;
m_lastSoundInsect = 0.0f ;
2012-09-10 21:29:38 +00:00
m_restBreakParticle = 0.0f ;
2012-06-26 20:23:05 +00:00
m_floorHeight = 0.0f ;
m_soundChannel = - 1 ;
m_soundChannelSlide = - 1 ;
m_soundTimePshhh = 0.0f ;
m_soundTimeJostle = 0.0f ;
m_soundTimeBoum = 0.0f ;
m_bSoundSlow = true ;
m_bFreeze = false ;
m_bForceUpdate = true ;
m_bLowLevel = false ;
2014-03-08 21:36:35 +00:00
m_fallingHeight = 0.0f ;
2014-03-09 13:36:39 +00:00
m_minFallingHeight = 20.0f ;
m_fallDamageFraction = 0.007f ;
2015-08-14 21:11:24 +00:00
m_floorLevel = 0.0f ;
2012-06-26 20:23:05 +00:00
}
// Object's destructor.
CPhysics : : ~ CPhysics ( )
{
2015-07-12 11:32:50 +00:00
}
2012-06-26 20:23:05 +00:00
// Destroys the object.
void CPhysics : : DeleteObject ( bool bAll )
{
if ( m_soundChannel ! = - 1 )
{
m_sound - > FlushEnvelope ( m_soundChannel ) ;
m_sound - > AddEnvelope ( m_soundChannel , 0.0f , 1.0f , 0.3f , SOPER_STOP ) ;
m_soundChannel = - 1 ;
}
if ( m_soundChannelSlide ! = - 1 )
{
m_sound - > FlushEnvelope ( m_soundChannelSlide ) ;
m_sound - > AddEnvelope ( m_soundChannelSlide , 0.0f , 1.0f , 0.3f , SOPER_STOP ) ;
m_soundChannelSlide = - 1 ;
}
}
void CPhysics : : SetMotion ( CMotion * motion )
{
m_motion = motion ;
}
// Saves all parameters of the object.
2014-11-10 13:16:32 +00:00
bool CPhysics : : Write ( CLevelParserLine * line )
2012-06-26 20:23:05 +00:00
{
2015-07-17 18:36:01 +00:00
line - > AddParam ( " motor " , MakeUnique < CLevelParserParam > ( m_motorSpeed ) ) ;
2012-06-26 20:23:05 +00:00
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : JetFlying ) )
{
2015-08-13 08:49:26 +00:00
line - > AddParam ( " reactorRange " , MakeUnique < CLevelParserParam > ( m_object - > GetReactorRange ( ) ) ) ;
2015-08-12 17:09:35 +00:00
}
2015-07-17 18:36:01 +00:00
line - > AddParam ( " land " , MakeUnique < CLevelParserParam > ( GetLand ( ) ) ) ;
2012-06-26 20:23:05 +00:00
}
return true ;
}
// Restores all parameters of the object.
2014-11-10 16:15:34 +00:00
bool CPhysics : : Read ( CLevelParserLine * line )
2012-06-26 20:23:05 +00:00
{
2015-08-14 16:19:58 +00:00
m_motorSpeed = line - > GetParam ( " motor " ) - > AsPoint ( Math : : Vector ( 0.0f , 0.0f , 0.0f ) ) ;
2012-06-26 20:23:05 +00:00
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : JetFlying ) )
{
2015-08-14 16:19:58 +00:00
m_object - > SetReactorRange ( line - > GetParam ( " reactorRange " ) - > AsFloat ( 1.0f ) ) ;
2015-08-12 17:09:35 +00:00
}
2015-08-14 16:19:58 +00:00
SetLand ( line - > GetParam ( " land " ) - > AsBool ( true ) ) ;
2012-06-26 20:23:05 +00:00
}
return true ;
}
// Management of the force of gravity.
void CPhysics : : SetGravity ( float value )
{
m_gravity = value ;
}
2012-09-10 21:29:38 +00:00
float CPhysics : : GetGravity ( )
2012-06-26 20:23:05 +00:00
{
return m_gravity ;
}
// Returns the height above the ground.
2012-09-10 21:29:38 +00:00
float CPhysics : : GetFloorHeight ( )
2012-06-26 20:23:05 +00:00
{
return m_floorHeight ;
}
// Managing the state of the engine.
void CPhysics : : SetMotor ( bool bState )
{
int light ;
m_bMotor = bState ;
2012-09-10 21:29:38 +00:00
light = m_object - > GetShadowLight ( ) ;
2012-06-26 20:23:05 +00:00
if ( light ! = - 1 )
{
2012-09-10 21:29:38 +00:00
m_lightMan - > SetLightIntensity ( light , m_bMotor ? 1.0f : 0.0f ) ;
m_lightMan - > SetLightIntensitySpeed ( light , 3.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
2012-09-10 21:29:38 +00:00
bool CPhysics : : GetMotor ( )
2012-06-26 20:23:05 +00:00
{
return m_bMotor ;
}
// Management of the state in flight/ground.
void CPhysics : : SetLand ( bool bState )
{
m_bLand = bState ;
SetMotor ( ! bState ) ; // lights if you leave the reactor in flight
}
2012-09-10 21:29:38 +00:00
bool CPhysics : : GetLand ( )
2012-06-26 20:23:05 +00:00
{
return m_bLand ;
}
// Management of the state in air/water.
void CPhysics : : SetSwim ( bool bState )
{
if ( ! m_bSwim & & bState ) // enters the water?
{
m_timeUnderWater = 0.0f ;
}
m_bSwim = bState ;
}
2012-09-10 21:29:38 +00:00
bool CPhysics : : GetSwim ( )
2012-06-26 20:23:05 +00:00
{
return m_bSwim ;
}
// Indicates whether a collision occurred.
void CPhysics : : SetCollision ( bool bCollision )
{
m_bCollision = bCollision ;
}
2012-09-10 21:29:38 +00:00
bool CPhysics : : GetCollision ( )
2012-06-26 20:23:05 +00:00
{
return m_bCollision ;
}
// Indicates whether the influence of soil is activated or not.
void CPhysics : : SetFreeze ( bool bFreeze )
{
m_bFreeze = bFreeze ;
}
2012-09-10 21:29:38 +00:00
bool CPhysics : : GetFreeze ( )
2012-06-26 20:23:05 +00:00
{
return m_bFreeze ;
}
// Specifies the engine speed.
// x = forward/backward
// y = up/down
// z = turn
void CPhysics : : SetMotorSpeed ( Math : : Vector speed )
{
m_motorSpeed = speed ;
}
// Specifies the engine speed for forward/backward.
// +1 = forward
// -1 = backward
void CPhysics : : SetMotorSpeedX ( float speed )
{
m_motorSpeed . x = speed ;
}
// Specifies the motor speed for up/down.
// +1 = up
// -1 = down
void CPhysics : : SetMotorSpeedY ( float speed )
{
m_motorSpeed . y = speed ;
}
// Specifies the speed of the motor to turn.
// +1 = turn right(CW)
// -1 = turn left(CCW)
void CPhysics : : SetMotorSpeedZ ( float speed )
{
m_motorSpeed . z = speed ;
}
2012-09-10 21:29:38 +00:00
Math : : Vector CPhysics : : GetMotorSpeed ( )
2012-06-26 20:23:05 +00:00
{
return m_motorSpeed ;
}
2012-09-10 21:29:38 +00:00
float CPhysics : : GetMotorSpeedX ( )
2012-06-26 20:23:05 +00:00
{
return m_motorSpeed . x ;
}
2012-09-10 21:29:38 +00:00
float CPhysics : : GetMotorSpeedY ( )
2012-06-26 20:23:05 +00:00
{
return m_motorSpeed . y ;
}
2012-09-10 21:29:38 +00:00
float CPhysics : : GetMotorSpeedZ ( )
2012-06-26 20:23:05 +00:00
{
return m_motorSpeed . z ;
}
// Management of linear and angular velocities.
// Specifies the speed parallel to the direction of travel.
void CPhysics : : SetLinMotion ( PhysicsMode mode , Math : : Vector value )
{
if ( mode = = MO_ADVACCEL ) m_linMotion . advanceAccel = value ;
if ( mode = = MO_RECACCEL ) m_linMotion . recedeAccel = value ;
if ( mode = = MO_STOACCEL ) m_linMotion . stopAccel = value ;
if ( mode = = MO_TERSPEED ) m_linMotion . terrainSpeed = value ;
if ( mode = = MO_TERSLIDE ) m_linMotion . terrainSlide = value ;
if ( mode = = MO_MOTACCEL ) m_linMotion . motorAccel = value ;
if ( mode = = MO_TERFORCE ) m_linMotion . terrainForce = value ;
if ( mode = = MO_ADVSPEED ) m_linMotion . advanceSpeed = value ;
if ( mode = = MO_RECSPEED ) m_linMotion . recedeSpeed = value ;
if ( mode = = MO_MOTSPEED ) m_linMotion . motorSpeed = value ;
if ( mode = = MO_CURSPEED ) m_linMotion . currentSpeed = value ;
if ( mode = = MO_REASPEED ) m_linMotion . realSpeed = value ;
}
2012-09-10 21:29:38 +00:00
Math : : Vector CPhysics : : GetLinMotion ( PhysicsMode mode )
2012-06-26 20:23:05 +00:00
{
if ( mode = = MO_ADVACCEL ) return m_linMotion . advanceAccel ;
if ( mode = = MO_RECACCEL ) return m_linMotion . recedeAccel ;
if ( mode = = MO_STOACCEL ) return m_linMotion . stopAccel ;
if ( mode = = MO_TERSPEED ) return m_linMotion . terrainSpeed ;
if ( mode = = MO_TERSLIDE ) return m_linMotion . terrainSlide ;
if ( mode = = MO_MOTACCEL ) return m_linMotion . motorAccel ;
if ( mode = = MO_TERFORCE ) return m_linMotion . terrainForce ;
if ( mode = = MO_ADVSPEED ) return m_linMotion . advanceSpeed ;
if ( mode = = MO_RECSPEED ) return m_linMotion . recedeSpeed ;
if ( mode = = MO_MOTSPEED ) return m_linMotion . motorSpeed ;
if ( mode = = MO_CURSPEED ) return m_linMotion . currentSpeed ;
if ( mode = = MO_REASPEED ) return m_linMotion . realSpeed ;
return Math : : Vector ( 0.0f , 0.0f , 0.0f ) ;
}
void CPhysics : : SetLinMotionX ( PhysicsMode mode , float value )
{
if ( mode = = MO_ADVACCEL ) m_linMotion . advanceAccel . x = value ;
if ( mode = = MO_RECACCEL ) m_linMotion . recedeAccel . x = value ;
if ( mode = = MO_STOACCEL ) m_linMotion . stopAccel . x = value ;
if ( mode = = MO_TERSPEED ) m_linMotion . terrainSpeed . x = value ;
if ( mode = = MO_TERSLIDE ) m_linMotion . terrainSlide . x = value ;
if ( mode = = MO_MOTACCEL ) m_linMotion . motorAccel . x = value ;
if ( mode = = MO_TERFORCE ) m_linMotion . terrainForce . x = value ;
if ( mode = = MO_ADVSPEED ) m_linMotion . advanceSpeed . x = value ;
if ( mode = = MO_RECSPEED ) m_linMotion . recedeSpeed . x = value ;
if ( mode = = MO_MOTSPEED ) m_linMotion . motorSpeed . x = value ;
if ( mode = = MO_CURSPEED ) m_linMotion . currentSpeed . x = value ;
if ( mode = = MO_REASPEED ) m_linMotion . realSpeed . x = value ;
}
2012-09-10 21:29:38 +00:00
float CPhysics : : GetLinMotionX ( PhysicsMode mode )
2012-06-26 20:23:05 +00:00
{
if ( mode = = MO_ADVACCEL ) return m_linMotion . advanceAccel . x ;
if ( mode = = MO_RECACCEL ) return m_linMotion . recedeAccel . x ;
if ( mode = = MO_STOACCEL ) return m_linMotion . stopAccel . x ;
if ( mode = = MO_TERSPEED ) return m_linMotion . terrainSpeed . x ;
if ( mode = = MO_TERSLIDE ) return m_linMotion . terrainSlide . x ;
if ( mode = = MO_MOTACCEL ) return m_linMotion . motorAccel . x ;
if ( mode = = MO_TERFORCE ) return m_linMotion . terrainForce . x ;
if ( mode = = MO_ADVSPEED ) return m_linMotion . advanceSpeed . x ;
if ( mode = = MO_RECSPEED ) return m_linMotion . recedeSpeed . x ;
if ( mode = = MO_MOTSPEED ) return m_linMotion . motorSpeed . x ;
if ( mode = = MO_CURSPEED ) return m_linMotion . currentSpeed . x ;
if ( mode = = MO_REASPEED ) return m_linMotion . realSpeed . x ;
return 0.0f ;
}
// Specifies the speed of elevation.
void CPhysics : : SetLinMotionY ( PhysicsMode mode , float value )
{
if ( mode = = MO_ADVACCEL ) m_linMotion . advanceAccel . y = value ;
if ( mode = = MO_RECACCEL ) m_linMotion . recedeAccel . y = value ;
if ( mode = = MO_STOACCEL ) m_linMotion . stopAccel . y = value ;
if ( mode = = MO_TERSPEED ) m_linMotion . terrainSpeed . y = value ;
if ( mode = = MO_TERSLIDE ) m_linMotion . terrainSlide . y = value ;
if ( mode = = MO_MOTACCEL ) m_linMotion . motorAccel . y = value ;
if ( mode = = MO_TERFORCE ) m_linMotion . terrainForce . y = value ;
if ( mode = = MO_ADVSPEED ) m_linMotion . advanceSpeed . y = value ;
if ( mode = = MO_RECSPEED ) m_linMotion . recedeSpeed . y = value ;
if ( mode = = MO_MOTSPEED ) m_linMotion . motorSpeed . y = value ;
if ( mode = = MO_CURSPEED ) m_linMotion . currentSpeed . y = value ;
if ( mode = = MO_REASPEED ) m_linMotion . realSpeed . y = value ;
}
2012-09-10 21:29:38 +00:00
float CPhysics : : GetLinMotionY ( PhysicsMode mode )
2012-06-26 20:23:05 +00:00
{
if ( mode = = MO_ADVACCEL ) return m_linMotion . advanceAccel . y ;
if ( mode = = MO_RECACCEL ) return m_linMotion . recedeAccel . y ;
if ( mode = = MO_STOACCEL ) return m_linMotion . stopAccel . y ;
if ( mode = = MO_TERSPEED ) return m_linMotion . terrainSpeed . y ;
if ( mode = = MO_TERSLIDE ) return m_linMotion . terrainSlide . y ;
if ( mode = = MO_MOTACCEL ) return m_linMotion . motorAccel . y ;
if ( mode = = MO_TERFORCE ) return m_linMotion . terrainForce . y ;
if ( mode = = MO_ADVSPEED ) return m_linMotion . advanceSpeed . y ;
if ( mode = = MO_RECSPEED ) return m_linMotion . recedeSpeed . y ;
if ( mode = = MO_MOTSPEED ) return m_linMotion . motorSpeed . y ;
if ( mode = = MO_CURSPEED ) return m_linMotion . currentSpeed . y ;
if ( mode = = MO_REASPEED ) return m_linMotion . realSpeed . y ;
return 0.0f ;
}
// Specifies the velocity perpendicular to the direction of travel.
void CPhysics : : SetLinMotionZ ( PhysicsMode mode , float value )
{
if ( mode = = MO_ADVACCEL ) m_linMotion . advanceAccel . z = value ;
if ( mode = = MO_RECACCEL ) m_linMotion . recedeAccel . z = value ;
if ( mode = = MO_STOACCEL ) m_linMotion . stopAccel . z = value ;
if ( mode = = MO_TERSPEED ) m_linMotion . terrainSpeed . z = value ;
if ( mode = = MO_TERSLIDE ) m_linMotion . terrainSlide . z = value ;
if ( mode = = MO_MOTACCEL ) m_linMotion . motorAccel . z = value ;
if ( mode = = MO_TERFORCE ) m_linMotion . terrainForce . z = value ;
if ( mode = = MO_ADVSPEED ) m_linMotion . advanceSpeed . z = value ;
if ( mode = = MO_RECSPEED ) m_linMotion . recedeSpeed . z = value ;
if ( mode = = MO_MOTSPEED ) m_linMotion . motorSpeed . z = value ;
if ( mode = = MO_CURSPEED ) m_linMotion . currentSpeed . z = value ;
if ( mode = = MO_REASPEED ) m_linMotion . realSpeed . z = value ;
}
2012-09-10 21:29:38 +00:00
float CPhysics : : GetLinMotionZ ( PhysicsMode mode )
2012-06-26 20:23:05 +00:00
{
if ( mode = = MO_ADVACCEL ) return m_linMotion . advanceAccel . z ;
if ( mode = = MO_RECACCEL ) return m_linMotion . recedeAccel . z ;
if ( mode = = MO_STOACCEL ) return m_linMotion . stopAccel . z ;
if ( mode = = MO_TERSPEED ) return m_linMotion . terrainSpeed . z ;
if ( mode = = MO_TERSLIDE ) return m_linMotion . terrainSlide . z ;
if ( mode = = MO_MOTACCEL ) return m_linMotion . motorAccel . z ;
if ( mode = = MO_TERFORCE ) return m_linMotion . terrainForce . z ;
if ( mode = = MO_ADVSPEED ) return m_linMotion . advanceSpeed . z ;
if ( mode = = MO_RECSPEED ) return m_linMotion . recedeSpeed . z ;
if ( mode = = MO_MOTSPEED ) return m_linMotion . motorSpeed . z ;
if ( mode = = MO_CURSPEED ) return m_linMotion . currentSpeed . z ;
if ( mode = = MO_REASPEED ) return m_linMotion . realSpeed . z ;
return 0.0f ;
}
// Specifies the rotation around the axis of walk.
void CPhysics : : SetCirMotion ( PhysicsMode mode , Math : : Vector value )
{
if ( mode = = MO_ADVACCEL ) m_cirMotion . advanceAccel = value ;
if ( mode = = MO_RECACCEL ) m_cirMotion . recedeAccel = value ;
if ( mode = = MO_STOACCEL ) m_cirMotion . stopAccel = value ;
if ( mode = = MO_TERSPEED ) m_cirMotion . terrainSpeed = value ;
if ( mode = = MO_TERSLIDE ) m_cirMotion . terrainSlide = value ;
if ( mode = = MO_MOTACCEL ) m_cirMotion . motorAccel = value ;
if ( mode = = MO_TERFORCE ) m_cirMotion . terrainForce = value ;
if ( mode = = MO_ADVSPEED ) m_cirMotion . advanceSpeed = value ;
if ( mode = = MO_RECSPEED ) m_cirMotion . recedeSpeed = value ;
if ( mode = = MO_MOTSPEED ) m_cirMotion . motorSpeed = value ;
if ( mode = = MO_CURSPEED ) m_cirMotion . currentSpeed = value ;
if ( mode = = MO_REASPEED ) m_cirMotion . realSpeed = value ;
}
2012-09-10 21:29:38 +00:00
Math : : Vector CPhysics : : GetCirMotion ( PhysicsMode mode )
2012-06-26 20:23:05 +00:00
{
if ( mode = = MO_ADVACCEL ) return m_cirMotion . advanceAccel ;
if ( mode = = MO_RECACCEL ) return m_cirMotion . recedeAccel ;
if ( mode = = MO_STOACCEL ) return m_cirMotion . stopAccel ;
if ( mode = = MO_TERSPEED ) return m_cirMotion . terrainSpeed ;
if ( mode = = MO_TERSLIDE ) return m_cirMotion . terrainSlide ;
if ( mode = = MO_MOTACCEL ) return m_cirMotion . motorAccel ;
if ( mode = = MO_TERFORCE ) return m_cirMotion . terrainForce ;
if ( mode = = MO_ADVSPEED ) return m_cirMotion . advanceSpeed ;
if ( mode = = MO_RECSPEED ) return m_cirMotion . recedeSpeed ;
if ( mode = = MO_MOTSPEED ) return m_cirMotion . motorSpeed ;
if ( mode = = MO_CURSPEED ) return m_cirMotion . currentSpeed ;
if ( mode = = MO_REASPEED ) return m_cirMotion . realSpeed ;
return Math : : Vector ( 0.0f , 0.0f , 0.0f ) ;
}
void CPhysics : : SetCirMotionX ( PhysicsMode mode , float value )
{
if ( mode = = MO_ADVACCEL ) m_cirMotion . advanceAccel . x = value ;
if ( mode = = MO_RECACCEL ) m_cirMotion . recedeAccel . x = value ;
if ( mode = = MO_STOACCEL ) m_cirMotion . stopAccel . x = value ;
if ( mode = = MO_TERSPEED ) m_cirMotion . terrainSpeed . x = value ;
if ( mode = = MO_TERSLIDE ) m_cirMotion . terrainSlide . x = value ;
if ( mode = = MO_MOTACCEL ) m_cirMotion . motorAccel . x = value ;
if ( mode = = MO_TERFORCE ) m_cirMotion . terrainForce . x = value ;
if ( mode = = MO_ADVSPEED ) m_cirMotion . advanceSpeed . x = value ;
if ( mode = = MO_RECSPEED ) m_cirMotion . recedeSpeed . x = value ;
if ( mode = = MO_MOTSPEED ) m_cirMotion . motorSpeed . x = value ;
if ( mode = = MO_CURSPEED ) m_cirMotion . currentSpeed . x = value ;
if ( mode = = MO_REASPEED ) m_cirMotion . realSpeed . x = value ;
}
2012-09-10 21:29:38 +00:00
float CPhysics : : GetCirMotionX ( PhysicsMode mode )
2012-06-26 20:23:05 +00:00
{
if ( mode = = MO_ADVACCEL ) return m_cirMotion . advanceAccel . x ;
if ( mode = = MO_RECACCEL ) return m_cirMotion . recedeAccel . x ;
if ( mode = = MO_STOACCEL ) return m_cirMotion . stopAccel . x ;
if ( mode = = MO_TERSPEED ) return m_cirMotion . terrainSpeed . x ;
if ( mode = = MO_TERSLIDE ) return m_cirMotion . terrainSlide . x ;
if ( mode = = MO_MOTACCEL ) return m_cirMotion . motorAccel . x ;
if ( mode = = MO_TERFORCE ) return m_cirMotion . terrainForce . x ;
if ( mode = = MO_ADVSPEED ) return m_cirMotion . advanceSpeed . x ;
if ( mode = = MO_RECSPEED ) return m_cirMotion . recedeSpeed . x ;
if ( mode = = MO_MOTSPEED ) return m_cirMotion . motorSpeed . x ;
if ( mode = = MO_CURSPEED ) return m_cirMotion . currentSpeed . x ;
if ( mode = = MO_REASPEED ) return m_cirMotion . realSpeed . x ;
return 0.0f ;
}
// Specifies the rotation direction.
void CPhysics : : SetCirMotionY ( PhysicsMode mode , float value )
{
if ( mode = = MO_ADVACCEL ) m_cirMotion . advanceAccel . y = value ;
if ( mode = = MO_RECACCEL ) m_cirMotion . recedeAccel . y = value ;
if ( mode = = MO_STOACCEL ) m_cirMotion . stopAccel . y = value ;
if ( mode = = MO_TERSPEED ) m_cirMotion . terrainSpeed . y = value ;
if ( mode = = MO_TERSLIDE ) m_cirMotion . terrainSlide . y = value ;
if ( mode = = MO_MOTACCEL ) m_cirMotion . motorAccel . y = value ;
if ( mode = = MO_TERFORCE ) m_cirMotion . terrainForce . y = value ;
if ( mode = = MO_ADVSPEED ) m_cirMotion . advanceSpeed . y = value ;
if ( mode = = MO_RECSPEED ) m_cirMotion . recedeSpeed . y = value ;
if ( mode = = MO_MOTSPEED ) m_cirMotion . motorSpeed . y = value ;
if ( mode = = MO_CURSPEED ) m_cirMotion . currentSpeed . y = value ;
if ( mode = = MO_REASPEED ) m_cirMotion . realSpeed . y = value ;
}
2012-09-10 21:29:38 +00:00
float CPhysics : : GetCirMotionY ( PhysicsMode mode )
2012-06-26 20:23:05 +00:00
{
if ( mode = = MO_ADVACCEL ) return m_cirMotion . advanceAccel . y ;
if ( mode = = MO_RECACCEL ) return m_cirMotion . recedeAccel . y ;
if ( mode = = MO_STOACCEL ) return m_cirMotion . stopAccel . y ;
if ( mode = = MO_TERSPEED ) return m_cirMotion . terrainSpeed . y ;
if ( mode = = MO_TERSLIDE ) return m_cirMotion . terrainSlide . y ;
if ( mode = = MO_MOTACCEL ) return m_cirMotion . motorAccel . y ;
if ( mode = = MO_TERFORCE ) return m_cirMotion . terrainForce . y ;
if ( mode = = MO_ADVSPEED ) return m_cirMotion . advanceSpeed . y ;
if ( mode = = MO_RECSPEED ) return m_cirMotion . recedeSpeed . y ;
if ( mode = = MO_MOTSPEED ) return m_cirMotion . motorSpeed . y ;
if ( mode = = MO_CURSPEED ) return m_cirMotion . currentSpeed . y ;
if ( mode = = MO_REASPEED ) return m_cirMotion . realSpeed . y ;
return 0.0f ;
}
// Specifies the rotation up/down.
void CPhysics : : SetCirMotionZ ( PhysicsMode mode , float value )
{
if ( mode = = MO_ADVACCEL ) m_cirMotion . advanceAccel . z = value ;
if ( mode = = MO_RECACCEL ) m_cirMotion . recedeAccel . z = value ;
if ( mode = = MO_STOACCEL ) m_cirMotion . stopAccel . z = value ;
if ( mode = = MO_TERSPEED ) m_cirMotion . terrainSpeed . z = value ;
if ( mode = = MO_TERSLIDE ) m_cirMotion . terrainSlide . z = value ;
if ( mode = = MO_MOTACCEL ) m_cirMotion . motorAccel . z = value ;
if ( mode = = MO_TERFORCE ) m_cirMotion . terrainForce . z = value ;
if ( mode = = MO_ADVSPEED ) m_cirMotion . advanceSpeed . z = value ;
if ( mode = = MO_RECSPEED ) m_cirMotion . recedeSpeed . z = value ;
if ( mode = = MO_MOTSPEED ) m_cirMotion . motorSpeed . z = value ;
if ( mode = = MO_CURSPEED ) m_cirMotion . currentSpeed . z = value ;
if ( mode = = MO_REASPEED ) m_cirMotion . realSpeed . z = value ;
}
2012-09-10 21:29:38 +00:00
float CPhysics : : GetCirMotionZ ( PhysicsMode mode )
2012-06-26 20:23:05 +00:00
{
if ( mode = = MO_ADVACCEL ) return m_cirMotion . advanceAccel . z ;
if ( mode = = MO_RECACCEL ) return m_cirMotion . recedeAccel . z ;
if ( mode = = MO_STOACCEL ) return m_cirMotion . stopAccel . z ;
if ( mode = = MO_TERSPEED ) return m_cirMotion . terrainSpeed . z ;
if ( mode = = MO_TERSLIDE ) return m_cirMotion . terrainSlide . z ;
if ( mode = = MO_MOTACCEL ) return m_cirMotion . motorAccel . z ;
if ( mode = = MO_TERFORCE ) return m_cirMotion . terrainForce . z ;
if ( mode = = MO_ADVSPEED ) return m_cirMotion . advanceSpeed . z ;
if ( mode = = MO_RECSPEED ) return m_cirMotion . recedeSpeed . z ;
if ( mode = = MO_MOTSPEED ) return m_cirMotion . motorSpeed . z ;
if ( mode = = MO_CURSPEED ) return m_cirMotion . currentSpeed . z ;
if ( mode = = MO_REASPEED ) return m_cirMotion . realSpeed . z ;
return 0.0f ;
}
// Returns the linear distance braking.
//
// v*v
// d = -----
// 2a
2012-09-10 21:29:38 +00:00
float CPhysics : : GetLinStopLength ( PhysicsMode sMode , PhysicsMode aMode )
2012-06-26 20:23:05 +00:00
{
float speed , accel ;
2012-09-10 21:29:38 +00:00
speed = GetLinMotionX ( sMode ) ; // MO_ADVSPEED/MO_RECSPEED
accel = GetLinMotionX ( aMode ) ; // MO_ADVACCEL/MO_RECACCEL/MO_STOACCEL
2012-06-26 20:23:05 +00:00
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) & & m_bLand ) // flying on the ground?
2012-06-26 20:23:05 +00:00
{
speed / = LANDING_SPEED ;
accel * = LANDING_ACCEL ;
}
return ( speed * speed ) / ( accel * 2.0f ) ;
}
// Returns the angle of circular braking.
2012-09-10 21:29:38 +00:00
float CPhysics : : GetCirStopLength ( )
2012-06-26 20:23:05 +00:00
{
2012-06-26 21:01:17 +00:00
return m_cirMotion . advanceSpeed . y * m_cirMotion . advanceSpeed . y /
2012-06-26 20:23:05 +00:00
m_cirMotion . stopAccel . y / 2.0f ;
}
// Returns the length advanced into a second, on the ground, maximum speed.
2012-09-10 21:29:38 +00:00
float CPhysics : : GetLinMaxLength ( float dir )
2012-06-26 20:23:05 +00:00
{
float dist ;
if ( dir > 0.0f ) dist = m_linMotion . advanceSpeed . x ;
else dist = m_linMotion . recedeSpeed . x ;
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
dist / = 5.0f ;
}
return dist ;
}
// Returns the time needed to travel some distance.
2012-09-10 21:29:38 +00:00
float CPhysics : : GetLinTimeLength ( float dist , float dir )
2012-06-26 20:23:05 +00:00
{
float accel , decel , dps ;
if ( dir > 0.0f )
{
2012-09-10 21:29:38 +00:00
accel = GetLinStopLength ( MO_ADVSPEED , MO_ADVACCEL ) ;
decel = GetLinStopLength ( MO_ADVSPEED , MO_STOACCEL ) ;
2012-06-26 20:23:05 +00:00
}
else
{
2012-09-10 21:29:38 +00:00
accel = GetLinStopLength ( MO_RECSPEED , MO_RECACCEL ) ;
decel = GetLinStopLength ( MO_RECSPEED , MO_STOACCEL ) ;
2012-06-26 20:23:05 +00:00
}
2012-09-10 21:29:38 +00:00
dps = GetLinMaxLength ( dir ) ;
2012-06-26 20:23:05 +00:00
return ( dist + accel + decel ) / dps ;
}
// Returns the length for a forward travel some distance, taking into account the accelerations / decelerations.
2012-09-10 21:29:38 +00:00
float CPhysics : : GetLinLength ( float dist )
2012-06-26 20:23:05 +00:00
{
float accDist , desDist ;
if ( dist > 0.0f )
{
2012-09-10 21:29:38 +00:00
accDist = GetLinStopLength ( MO_ADVSPEED , MO_ADVACCEL ) ;
desDist = GetLinStopLength ( MO_ADVSPEED , MO_STOACCEL ) ;
2012-06-26 20:23:05 +00:00
if ( dist > accDist + desDist )
{
return dist - desDist ;
}
return dist * m_linMotion . stopAccel . x /
( m_linMotion . advanceAccel . x + m_linMotion . stopAccel . x ) ;
}
else
{
dist = - dist ;
2012-09-10 21:29:38 +00:00
accDist = GetLinStopLength ( MO_RECSPEED , MO_RECACCEL ) ;
desDist = GetLinStopLength ( MO_RECSPEED , MO_STOACCEL ) ;
2012-06-26 20:23:05 +00:00
if ( dist > accDist + desDist )
{
return dist - desDist ;
}
return dist * m_linMotion . stopAccel . x /
( m_linMotion . recedeAccel . x + m_linMotion . stopAccel . x ) ;
}
}
// Management of an event.
// Returns false if the object is destroyed.
bool CPhysics : : EventProcess ( const Event & event )
{
2012-09-10 21:29:38 +00:00
if ( event . type = = EVENT_FRAME )
2012-06-26 20:23:05 +00:00
{
return EventFrame ( event ) ;
}
return true ;
}
// Updates instructions for the motor speed.
void CPhysics : : MotorUpdate ( float aTime , float rTime )
{
ObjectType type ;
2015-08-11 20:51:09 +00:00
CPowerContainerObject * power = nullptr ;
2012-06-26 20:23:05 +00:00
Math : : Vector pos , motorSpeed ;
float energy , speed , factor , h ;
2012-09-10 21:29:38 +00:00
type = m_object - > GetType ( ) ;
2012-06-26 20:23:05 +00:00
2013-12-26 20:14:36 +00:00
if ( std : : isnan ( m_motorSpeed . x ) ) m_motorSpeed . x = 0.f ;
if ( std : : isnan ( m_motorSpeed . y ) ) m_motorSpeed . y = 0.f ;
if ( std : : isnan ( m_motorSpeed . z ) ) m_motorSpeed . z = 0.f ;
2013-12-26 19:37:39 +00:00
2012-06-26 20:23:05 +00:00
motorSpeed = m_motorSpeed ;
2015-08-12 17:09:35 +00:00
if ( type = = OBJECT_HUMAN | |
type = = OBJECT_TECH )
2012-06-26 20:23:05 +00:00
{
2015-08-11 20:51:09 +00:00
if ( IsObjectCarryingCargo ( m_object ) & & // carries something?
2015-07-12 13:09:32 +00:00
! m_bFreeze )
2012-06-26 20:23:05 +00:00
{
motorSpeed . x * = 0.7f ; // forward more slowly
motorSpeed . z * = 0.5f ;
motorSpeed . y = - 1.0f ; // grave
}
if ( m_bSwim )
{
if ( m_bLand ) // deep in the water?
{
motorSpeed . x * = 0.4f ; // forward more slowly
motorSpeed . z * = 0.5f ;
motorSpeed . y * = 0.5f ;
2015-07-10 20:13:39 +00:00
if ( IsObjectCarryingCargo ( m_object ) ) // carries something?
2012-06-26 20:23:05 +00:00
{
motorSpeed . x * = 0.2f ;
motorSpeed . z * = 0.9f ;
motorSpeed . y * = 0.2f ;
}
}
else // swimming?
{
motorSpeed . x * = 0.2f ; // forward more slowly
motorSpeed . z * = 0.5f ;
motorSpeed . y * = 0.2f ;
}
}
}
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Powered ) )
2012-06-26 20:23:05 +00:00
{
2020-09-14 19:19:16 +00:00
power = dynamic_cast < CPowerContainerObject * > ( dynamic_cast < CPoweredObject & > ( * m_object ) . GetPower ( ) ) ; // searches for the object battery uses
2015-08-12 17:09:35 +00:00
if ( GetObjectEnergy ( m_object ) = = 0.0f ) // no battery or flat?
2012-06-26 20:23:05 +00:00
{
2015-08-12 17:09:35 +00:00
motorSpeed . x = 0.0f ;
motorSpeed . z = 0.0f ;
if ( m_bFreeze | | m_bLand )
2012-06-26 20:23:05 +00:00
{
2015-08-12 17:09:35 +00:00
motorSpeed . y = 0.0f ; // immobile
2012-06-26 20:23:05 +00:00
}
2015-08-12 17:09:35 +00:00
else
{
motorSpeed . y = - 1.0f ; // grave
SetFalling ( ) ;
}
SetMotor ( false ) ;
2012-06-26 20:23:05 +00:00
}
}
2020-09-14 19:19:16 +00:00
if ( m_object - > GetType ( ) = = OBJECT_HUMAN & & dynamic_cast < CDestroyableObject & > ( * m_object ) . GetDying ( ) = = DeathType : : Dead ) // dead man?
2012-06-26 20:23:05 +00:00
{
motorSpeed . x = 0.0f ;
motorSpeed . z = 0.0f ;
2012-09-10 21:29:38 +00:00
if ( m_motion - > GetAction ( ) = = MHS_DEADw ) // drowned?
2012-06-26 20:23:05 +00:00
{
motorSpeed . y = 0.0f ; // this is MHS_DEADw going back
}
else
{
motorSpeed . y = - 1.0f ; // grave
}
SetMotor ( false ) ;
}
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) & & ! m_bLand & & motorSpeed . y > 0.0f )
2012-06-26 20:23:05 +00:00
{
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-09-10 21:29:38 +00:00
h = m_terrain - > GetFlyingLimit ( pos , type = = OBJECT_BEE ) ;
h + = m_object - > GetCharacter ( ) - > height ;
2012-06-26 20:23:05 +00:00
if ( pos . y > h - 40.0f ) // almost at the top?
{
factor = 1.0f - ( pos . y - ( h - 40.0f ) ) / 40.0f ;
if ( factor < - 1.0f ) factor = - 1.0f ;
if ( factor > 1.0f ) factor = 1.0f ;
motorSpeed . y * = factor ; // limit the rate of rise
}
}
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : JetFlying ) & &
2020-09-14 19:19:16 +00:00
dynamic_cast < CJetFlyingObject & > ( * m_object ) . GetRange ( ) > 0.0f ) // limited flight range?
2012-06-26 20:23:05 +00:00
{
2015-08-13 08:49:26 +00:00
CJetFlyingObject * jetFlying = dynamic_cast < CJetFlyingObject * > ( m_object ) ;
2012-06-26 20:23:05 +00:00
if ( m_bLand | | m_bSwim | | m_bObstacle ) // on the ground or in the water?
{
factor = 1.0f ;
if ( m_bObstacle ) factor = 3.0f ; // in order to leave!
if ( m_bSwim ) factor = 3.0f ; // cools faster in water
2015-08-13 08:49:26 +00:00
jetFlying - > SetReactorRange ( jetFlying - > GetReactorRange ( ) + rTime * ( 1.0f / 5.0f ) * factor ) ;
if ( jetFlying - > GetReactorRange ( ) = = 1.0f )
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
if ( m_bLowLevel & & m_object - > GetSelect ( ) ) // beep cool?
2012-06-26 20:23:05 +00:00
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_INFO , m_object - > GetPosition ( ) , 1.0f , 2.0f ) ;
2012-06-26 20:23:05 +00:00
m_bLowLevel = false ;
}
}
m_bObstacle = false ;
}
else // in flight?
{
2015-08-13 08:49:26 +00:00
jetFlying - > SetReactorRange ( jetFlying - > GetReactorRange ( ) - rTime * ( 1.0f / jetFlying - > GetRange ( ) ) ) ;
if ( jetFlying - > GetReactorRange ( ) < 0.5f ) m_bLowLevel = true ;
2012-06-26 20:23:05 +00:00
}
2015-08-13 08:49:26 +00:00
if ( jetFlying - > GetReactorRange ( ) = = 0.0f ) // reactor tilt?
2012-06-26 20:23:05 +00:00
{
motorSpeed . y = - 1.0f ; // grave
2014-03-09 13:36:39 +00:00
SetFalling ( ) ;
2012-06-26 20:23:05 +00:00
}
}
2012-09-10 21:29:38 +00:00
//? MotorParticle(aTime);
2012-06-26 20:23:05 +00:00
// Forward/backward.
if ( motorSpeed . x > 0.0f )
{
m_linMotion . motorAccel . x = m_linMotion . advanceAccel . x ;
m_linMotion . motorSpeed . x = m_linMotion . advanceSpeed . x * motorSpeed . x ;
}
if ( motorSpeed . x < 0.0f )
{
m_linMotion . motorAccel . x = m_linMotion . recedeAccel . x ;
m_linMotion . motorSpeed . x = m_linMotion . recedeSpeed . x * motorSpeed . x ;
}
if ( motorSpeed . x = = 0.0f )
{
m_linMotion . motorAccel . x = m_linMotion . stopAccel . x ;
m_linMotion . motorSpeed . x = 0.0f ;
}
// Up/down.
if ( motorSpeed . y > 0.0f )
{
m_linMotion . motorAccel . y = m_linMotion . advanceAccel . y ;
m_linMotion . motorSpeed . y = m_linMotion . advanceSpeed . y * motorSpeed . y ;
}
if ( motorSpeed . y < 0.0f )
{
m_linMotion . motorAccel . y = m_linMotion . recedeAccel . y ;
m_linMotion . motorSpeed . y = m_linMotion . recedeSpeed . y * motorSpeed . y ;
}
if ( motorSpeed . y = = 0.0f )
{
m_linMotion . motorAccel . y = m_linMotion . stopAccel . y ;
m_linMotion . motorSpeed . y = 0.0f ;
}
// Turn left/right.
speed = motorSpeed . z ;
//? if ( motorSpeed.x < 0.0f ) speed = -speed; // reverse if running back
if ( motorSpeed . z > 0.0f )
{
m_cirMotion . motorAccel . y = m_cirMotion . advanceAccel . y ;
m_cirMotion . motorSpeed . y = m_cirMotion . advanceSpeed . y * speed ;
}
if ( motorSpeed . z < 0.0f )
{
m_cirMotion . motorAccel . y = m_cirMotion . recedeAccel . y ;
m_cirMotion . motorSpeed . y = m_cirMotion . recedeSpeed . y * speed ;
}
if ( motorSpeed . z = = 0.0f )
{
m_cirMotion . motorAccel . y = m_cirMotion . stopAccel . y ;
m_cirMotion . motorSpeed . y = 0.0f ;
}
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) & & m_bLand ) // flying on the ground?
2012-06-26 20:23:05 +00:00
{
if ( type = = OBJECT_HUMAN | |
type = = OBJECT_TECH )
{
factor = LANDING_ACCELh ;
}
else
{
factor = LANDING_ACCEL ;
}
m_linMotion . motorAccel . x = m_linMotion . stopAccel . x * factor ;
m_cirMotion . motorAccel . y = m_cirMotion . stopAccel . y * factor ;
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-09-10 21:29:38 +00:00
h = m_terrain - > GetFlyingLimit ( pos , type = = OBJECT_BEE ) ;
h + = m_object - > GetCharacter ( ) - > height ;
2015-08-13 08:49:26 +00:00
bool reactorCool = true ;
if ( m_object - > Implements ( ObjectInterfaceType : : JetFlying ) )
{
2020-09-14 19:19:16 +00:00
reactorCool = dynamic_cast < CJetFlyingObject & > ( * m_object ) . GetReactorRange ( ) > 0.1f ;
2015-08-13 08:49:26 +00:00
}
if ( motorSpeed . y > 0.0f & & reactorCool & & pos . y < h )
2012-06-26 20:23:05 +00:00
{
m_bLand = false ; // take off
SetMotor ( true ) ;
pos . y + = 0.05f ; // small initial height (startup)
2015-07-13 21:19:46 +00:00
m_object - > SetPosition ( pos ) ;
2012-06-26 20:23:05 +00:00
}
}
2015-08-12 17:09:35 +00:00
if ( ! m_object - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
if ( motorSpeed . x = = 0.0f & &
motorSpeed . z = = 0.0f )
{
SetMotor ( false ) ;
}
else
{
SetMotor ( true ) ;
}
}
2015-07-10 21:47:59 +00:00
if ( power ! = nullptr ) // battery transported?
2012-06-26 20:23:05 +00:00
{
factor = 1.0f ;
if ( type = = OBJECT_MOBILEia | |
2017-11-16 17:43:45 +00:00
type = = OBJECT_MOBILEib | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEis | |
type = = OBJECT_MOBILEic | |
2017-12-21 00:49:56 +00:00
type = = OBJECT_MOBILEii | |
type = = OBJECT_MOBILEit ) factor = 0.5f ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
energy = power - > GetEnergy ( ) ;
2012-06-26 20:23:05 +00:00
energy - = fabs ( motorSpeed . x ) * rTime * factor * 0.005f ;
energy - = fabs ( motorSpeed . z ) * rTime * factor * 0.005f ;
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) & & motorSpeed . y > 0.0f )
2012-06-26 20:23:05 +00:00
{
energy - = motorSpeed . y * rTime * factor * 0.01f ;
}
if ( energy < 0.0f ) energy = 0.0f ;
power - > SetEnergy ( energy ) ;
}
}
// Updates the effects of vibration and tilt.
void CPhysics : : EffectUpdate ( float aTime , float rTime )
{
Character * character ;
Math : : Vector vibLin , vibCir , incl ;
float speedLin , speedCir , accel ;
ObjectType type ;
bool bOnBoard ;
2015-07-12 09:01:16 +00:00
if ( ! m_engine - > IsVisiblePoint ( m_object - > GetPosition ( ) ) ) return ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
type = m_object - > GetType ( ) ;
character = m_object - > GetCharacter ( ) ;
2012-06-26 20:23:05 +00:00
bOnBoard = false ;
2012-09-10 21:29:38 +00:00
if ( m_object - > GetSelect ( ) & &
m_camera - > GetType ( ) = = Gfx : : CAM_TYPE_ONBOARD )
2012-06-26 20:23:05 +00:00
{
bOnBoard = true ;
}
2012-09-10 21:29:38 +00:00
vibLin = m_motion - > GetLinVibration ( ) ;
vibCir = m_motion - > GetCirVibration ( ) ;
2015-06-25 17:05:56 +00:00
incl = m_motion - > GetTilt ( ) ;
2012-06-26 20:23:05 +00:00
if ( type = = OBJECT_HUMAN | | // human?
type = = OBJECT_TECH )
{
if ( ! m_bLand & & ! m_bSwim ) // in flight?
{
vibLin . y = sinf ( aTime * 2.00f ) * 0.5f +
sinf ( aTime * 2.11f ) * 0.3f ;
vibCir . z = sinf ( aTime * Math : : PI * 2.01f ) * ( Math : : PI / 150.0f ) +
sinf ( aTime * Math : : PI * 2.51f ) * ( Math : : PI / 200.0f ) +
sinf ( aTime * Math : : PI * 19.01f ) * ( Math : : PI / 400.0f ) ;
vibCir . x = sinf ( aTime * Math : : PI * 2.03f ) * ( Math : : PI / 150.0f ) +
sinf ( aTime * Math : : PI * 2.52f ) * ( Math : : PI / 200.0f ) +
sinf ( aTime * Math : : PI * 19.53f ) * ( Math : : PI / 400.0f ) ;
speedLin = m_linMotion . realSpeed . x / m_linMotion . advanceSpeed . x ;
speedCir = m_cirMotion . realSpeed . y / m_cirMotion . advanceSpeed . y ;
incl . x = - speedLin * speedCir * 0.5f ; // looks if turn
//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
speedLin = m_linMotion . currentSpeed . x - m_linMotion . motorSpeed . x * 1.2f ;
speedLin / = m_linMotion . advanceSpeed . x ;
m_linMotion . finalInclin . z = speedLin * 1.4f ;
if ( incl . z < m_linMotion . finalInclin . z )
{
incl . z + = rTime * 0.4f ;
if ( incl . z > m_linMotion . finalInclin . z )
{
incl . z = m_linMotion . finalInclin . z ;
}
}
else if ( incl . z > m_linMotion . finalInclin . z )
{
incl . z - = rTime * 0.4f ;
if ( incl . z < m_linMotion . finalInclin . z )
{
incl . z = m_linMotion . finalInclin . z ;
}
}
vibLin * = m_linVibrationFactor ;
vibCir * = m_cirVibrationFactor ;
incl * = m_inclinaisonFactor ;
m_motion - > SetLinVibration ( vibLin ) ;
m_motion - > SetCirVibration ( vibCir ) ;
2015-06-25 17:05:56 +00:00
m_motion - > SetTilt ( incl ) ;
2012-06-26 20:23:05 +00:00
}
else if ( m_bSwim ) // swimming?
{
vibLin . y = sinf ( aTime * 2.00f ) * 0.5f +
sinf ( aTime * 2.11f ) * 0.3f ;
vibCir . z = sinf ( aTime * Math : : PI * 2.01f ) * ( Math : : PI / 150.0f ) +
sinf ( aTime * Math : : PI * 2.51f ) * ( Math : : PI / 200.0f ) +
//? sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f)-Math::PI/2.0f;
sinf ( aTime * Math : : PI * 19.01f ) * ( Math : : PI / 400.0f ) ;
vibCir . x = sinf ( aTime * Math : : PI * 2.03f ) * ( Math : : PI / 150.0f ) +
sinf ( aTime * Math : : PI * 2.52f ) * ( Math : : PI / 200.0f ) +
sinf ( aTime * Math : : PI * 19.53f ) * ( Math : : PI / 400.0f ) ;
speedLin = m_linMotion . realSpeed . x / m_linMotion . advanceSpeed . x ;
speedCir = m_cirMotion . realSpeed . y / m_cirMotion . advanceSpeed . y ;
incl . x = - speedLin * speedCir * 5.0f ; // looks if turn
//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
speedLin = m_linMotion . currentSpeed . x - m_linMotion . motorSpeed . x * 1.2f ;
speedLin / = m_linMotion . advanceSpeed . x ;
m_linMotion . finalInclin . z = speedLin * 1.4f ;
if ( incl . z < m_linMotion . finalInclin . z )
{
incl . z + = rTime * 0.4f ;
if ( incl . z > m_linMotion . finalInclin . z )
{
incl . z = m_linMotion . finalInclin . z ;
}
}
else if ( incl . z > m_linMotion . finalInclin . z )
{
incl . z - = rTime * 0.4f ;
if ( incl . z < m_linMotion . finalInclin . z )
{
incl . z = m_linMotion . finalInclin . z ;
}
}
if ( m_linMotion . realSpeed . y > 0.0f ) // up?
{
vibCir . z + = m_linMotion . realSpeed . y * 0.05f ;
}
else // down?
{
vibCir . z + = m_linMotion . realSpeed . y * 0.12f ;
}
vibCir . z - = Math : : PI * 0.4f ;
vibLin * = m_linVibrationFactor ;
vibCir * = m_cirVibrationFactor ;
incl * = m_inclinaisonFactor ;
m_motion - > SetLinVibration ( vibLin ) ;
m_motion - > SetCirVibration ( vibCir ) ;
2015-06-25 17:05:56 +00:00
m_motion - > SetTilt ( incl ) ;
2012-06-26 20:23:05 +00:00
}
else
{
m_motion - > SetLinVibration ( Math : : Vector ( 0.0f , 0.0f , 0.0f ) ) ;
2012-09-10 21:29:38 +00:00
2012-06-26 20:23:05 +00:00
//? m_motion->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
2015-06-25 17:05:56 +00:00
//? m_motion->SetTilt(Math::Vector(0.0f, 0.0f, 0.0f));
2012-06-26 20:23:05 +00:00
}
}
if ( type = = OBJECT_MOBILEwa | |
2017-11-16 17:43:45 +00:00
type = = OBJECT_MOBILEwb | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEwc | |
type = = OBJECT_MOBILEwi | |
type = = OBJECT_MOBILEws | |
type = = OBJECT_MOBILEwt | |
type = = OBJECT_MOBILEtg | |
type = = OBJECT_APOLLO2 ) // wheels?
{
speedLin = m_linMotion . realSpeed . x / m_linMotion . advanceSpeed . x ;
speedCir = m_cirMotion . realSpeed . y / m_cirMotion . advanceSpeed . y ;
incl . x = speedLin * speedCir * 0.20f ; // looks if turn
if ( type = = OBJECT_APOLLO2 ) incl . x * = 0.25f ;
speedLin = m_linMotion . currentSpeed . x - m_linMotion . motorSpeed . x ;
speedLin / = m_linMotion . advanceSpeed . x ;
if ( speedLin > 1.0f ) speedLin = 1.0f ;
m_linMotion . finalInclin . z = - speedLin * 0.30f ;
accel = ( 0.40f - fabs ( incl . z ) ) * 4.0f ;
if ( incl . z < m_linMotion . finalInclin . z )
{
incl . z + = rTime * accel ;
if ( incl . z > m_linMotion . finalInclin . z )
{
incl . z = m_linMotion . finalInclin . z ;
}
}
else if ( incl . z > m_linMotion . finalInclin . z )
{
incl . z - = rTime * accel ;
if ( incl . z < m_linMotion . finalInclin . z )
{
incl . z = m_linMotion . finalInclin . z ;
}
}
if ( bOnBoard ) incl . z * = 0.1f ;
if ( type = = OBJECT_APOLLO2 ) incl . z * = 0.25f ;
2015-06-25 17:05:56 +00:00
m_object - > SetTilt ( incl ) ;
2012-06-26 20:23:05 +00:00
vibLin . x = 0.0f ;
vibLin . z = 0.0f ;
vibLin . y = fabs ( character - > wheelFront * sinf ( incl . z ) ) * 0.8f +
fabs ( character - > wheelRight * sinf ( incl . x ) ) * 0.5f ;
m_motion - > SetLinVibration ( vibLin ) ;
}
if ( type = = OBJECT_MOBILEfa | |
2017-11-16 17:43:45 +00:00
type = = OBJECT_MOBILEfb | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEfc | |
type = = OBJECT_MOBILEfi | |
type = = OBJECT_MOBILEfs | |
2019-03-08 11:45:41 +00:00
type = = OBJECT_MOBILEft ) // flying?
2012-06-26 20:23:05 +00:00
{
if ( m_bLand ) // on the ground?
{
m_motion - > SetLinVibration ( Math : : Vector ( 0.0f , 0.0f , 0.0f ) ) ;
m_motion - > SetCirVibration ( Math : : Vector ( 0.0f , 0.0f , 0.0f ) ) ;
2015-06-25 17:05:56 +00:00
m_motion - > SetTilt ( Math : : Vector ( 0.0f , 0.0f , 0.0f ) ) ;
2012-06-26 20:23:05 +00:00
}
else // in flight?
{
vibLin . y = sinf ( aTime * 2.00f ) * 0.5f +
sinf ( aTime * 2.11f ) * 0.3f ;
vibCir . z = sinf ( aTime * Math : : PI * 2.01f ) * ( Math : : PI / 150.0f ) +
sinf ( aTime * Math : : PI * 2.51f ) * ( Math : : PI / 200.0f ) +
sinf ( aTime * Math : : PI * 19.01f ) * ( Math : : PI / 400.0f ) ;
vibCir . x = sinf ( aTime * Math : : PI * 2.03f ) * ( Math : : PI / 150.0f ) +
sinf ( aTime * Math : : PI * 2.52f ) * ( Math : : PI / 200.0f ) +
sinf ( aTime * Math : : PI * 19.53f ) * ( Math : : PI / 400.0f ) ;
if ( bOnBoard ) vibCir * = 0.4f ;
speedLin = m_linMotion . realSpeed . x / m_linMotion . advanceSpeed . x ;
speedCir = m_cirMotion . realSpeed . y / m_cirMotion . advanceSpeed . y ;
incl . x = - speedLin * speedCir * 0.5f ; // looks if turn
//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
speedLin = m_linMotion . currentSpeed . x - m_linMotion . motorSpeed . x * 1.2f ;
speedLin / = m_linMotion . advanceSpeed . x ;
m_linMotion . finalInclin . z = speedLin * 0.8f ;
if ( incl . z < m_linMotion . finalInclin . z )
{
incl . z + = rTime * 0.4f ;
if ( incl . z > m_linMotion . finalInclin . z )
{
incl . z = m_linMotion . finalInclin . z ;
}
}
else if ( incl . z > m_linMotion . finalInclin . z )
{
incl . z - = rTime * 0.4f ;
if ( incl . z < m_linMotion . finalInclin . z )
{
incl . z = m_linMotion . finalInclin . z ;
}
}
//? if ( bOnBoard ) incl.z *= 0.5f;
vibLin * = m_linVibrationFactor ;
vibCir * = m_cirVibrationFactor ;
incl * = m_inclinaisonFactor ;
m_motion - > SetLinVibration ( vibLin ) ;
m_motion - > SetCirVibration ( vibCir ) ;
2015-06-25 17:05:56 +00:00
m_motion - > SetTilt ( incl ) ;
2012-06-26 20:23:05 +00:00
}
}
if ( type = = OBJECT_BEE ) // bee?
{
if ( ! m_bLand ) // in flight?
{
vibLin . y = sinf ( aTime * 2.00f ) * 0.5f +
sinf ( aTime * 2.11f ) * 0.3f ;
vibCir . z = ( Math : : Rand ( ) - 0.5f ) * 0.1f +
sinf ( aTime * Math : : PI * 2.01f ) * ( Math : : PI / 150.0f ) +
sinf ( aTime * Math : : PI * 2.51f ) * ( Math : : PI / 200.0f ) +
sinf ( aTime * Math : : PI * 19.01f ) * ( Math : : PI / 400.0f ) ;
vibCir . x = ( Math : : Rand ( ) - 0.5f ) * 0.1f +
sinf ( aTime * Math : : PI * 2.03f ) * ( Math : : PI / 150.0f ) +
sinf ( aTime * Math : : PI * 2.52f ) * ( Math : : PI / 200.0f ) +
sinf ( aTime * Math : : PI * 19.53f ) * ( Math : : PI / 400.0f ) ;
speedLin = m_linMotion . realSpeed . x / m_linMotion . advanceSpeed . x ;
speedCir = m_cirMotion . realSpeed . y / m_cirMotion . advanceSpeed . y ;
incl . x = - speedLin * speedCir * 1.5f ; // looks if turn
//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
speedLin = m_linMotion . currentSpeed . x - m_linMotion . motorSpeed . x * 1.2f ;
speedLin / = m_linMotion . advanceSpeed . x ;
m_linMotion . finalInclin . z = speedLin * 1.4f ;
if ( incl . z < m_linMotion . finalInclin . z )
{
incl . z + = rTime * 1.6f ;
if ( incl . z > m_linMotion . finalInclin . z )
{
incl . z = m_linMotion . finalInclin . z ;
}
}
else if ( incl . z > m_linMotion . finalInclin . z )
{
incl . z - = rTime * 1.6f ;
if ( incl . z < m_linMotion . finalInclin . z )
{
incl . z = m_linMotion . finalInclin . z ;
}
}
vibLin * = m_linVibrationFactor ;
vibCir * = m_cirVibrationFactor ;
incl * = m_inclinaisonFactor ;
m_motion - > SetLinVibration ( vibLin ) ;
m_motion - > SetCirVibration ( vibCir ) ;
2015-06-25 17:05:56 +00:00
m_motion - > SetTilt ( incl ) ;
2012-06-26 20:23:05 +00:00
}
}
}
// Updates structure Motion.
void CPhysics : : UpdateMotionStruct ( float rTime , Motion & motion )
{
float speed , motor ;
// Management for the coordinate x.
speed = motion . currentSpeed . x ;
motor = motion . motorSpeed . x * m_inclinaisonFactor ;
if ( speed < motor )
{
speed + = rTime * motion . motorAccel . x ; // accelerates
if ( speed > motor )
{
speed = motor ; // does not exceed the speed
}
}
if ( speed > motor )
{
speed - = rTime * motion . motorAccel . x ; // decelerates
if ( speed < motor )
{
speed = motor ; // does not exceed the speed
}
}
motion . currentSpeed . x = speed ;
motion . realSpeed . x = speed ;
if ( fabs ( motion . terrainSpeed . x ) > motion . terrainSlide . x )
{
if ( motion . terrainSpeed . x > 0 )
{
speed = motion . terrainSpeed . x - motion . terrainSlide . x ;
}
else
{
speed = motion . terrainSpeed . x + motion . terrainSlide . x ;
}
motion . realSpeed . x + = speed ;
}
// Management for the coordinate y.
speed = motion . currentSpeed . y ;
motor = motion . motorSpeed . y ; // unlimited speed!
if ( speed < motor )
{
speed + = rTime * motion . motorAccel . y ; // accelerates
if ( speed > motor )
{
speed = motor ; // does not exceed the speed
}
}
if ( speed > motor )
{
speed - = rTime * motion . motorAccel . y ; // decelerates
if ( speed < motor )
{
speed = motor ; // does not exceed the speed
}
}
motion . currentSpeed . y = speed ;
motion . realSpeed . y = speed ;
if ( fabs ( motion . terrainSpeed . y ) > motion . terrainSlide . y )
{
if ( motion . terrainSpeed . y > 0 )
{
speed = motion . terrainSpeed . y - motion . terrainSlide . y ;
}
else
{
speed = motion . terrainSpeed . y + motion . terrainSlide . y ;
}
motion . realSpeed . y + = speed ;
}
// Management for the coordinate z.
speed = motion . currentSpeed . z ;
motor = motion . motorSpeed . z * m_inclinaisonFactor ;
if ( speed < motor )
{
speed + = rTime * motion . motorAccel . z ; // accelerates
if ( speed > motor )
{
speed = motor ; // does not exceed the speed
}
}
if ( speed > motor )
{
speed - = rTime * motion . motorAccel . z ; // decelerates
if ( speed < motor )
{
speed = motor ; // does not exceed the speed
}
}
motion . currentSpeed . z = speed ;
motion . realSpeed . z = speed ;
if ( fabs ( motion . terrainSpeed . z ) > motion . terrainSlide . z )
{
if ( motion . terrainSpeed . z > 0 )
{
speed = motion . terrainSpeed . z - motion . terrainSlide . z ;
}
else
{
speed = motion . terrainSpeed . z + motion . terrainSlide . z ;
}
motion . realSpeed . z + = speed ;
}
}
// Makes physics evolve as time elapsed.
// Returns false if the object is destroyed.
//
// a: acceleration
// v1: velocity at time t1
// v2: velocity at time t2
// dt: time elapsed since t1, then: dt = t2-t1
// dd: difference in distance (advance)
//
// v2 = v1 + a*dt
// dd = v2*dt
bool CPhysics : : EventFrame ( const Event & event )
{
ObjectType type ;
Math : : Matrix objRotate , matRotate ;
Math : : Vector iPos , iAngle , tAngle , pos , newpos , angle , newangle , n ;
float h , w ;
int i ;
2012-09-10 21:29:38 +00:00
if ( m_engine - > GetPause ( ) ) return true ;
2012-06-26 20:23:05 +00:00
m_time + = event . rTime ;
m_timeUnderWater + = event . rTime ;
m_soundTimeJostle + = event . rTime ;
2012-09-10 21:29:38 +00:00
type = m_object - > GetType ( ) ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
FrameParticle ( m_time , event . rTime ) ;
2012-06-26 20:23:05 +00:00
MotorUpdate ( m_time , event . rTime ) ;
EffectUpdate ( m_time , event . rTime ) ;
WaterFrame ( m_time , event . rTime ) ;
2015-07-12 09:01:16 +00:00
iPos = pos = m_object - > GetPosition ( ) ;
iAngle = angle = m_object - > GetRotation ( ) ;
2012-06-26 20:23:05 +00:00
// Accelerate is the descent, brake is the ascent.
2020-09-14 19:19:16 +00:00
if ( m_bFreeze | | ( m_object - > Implements ( ObjectInterfaceType : : Destroyable ) & & dynamic_cast < CDestroyableObject & > ( * m_object ) . IsDying ( ) ) )
2012-06-26 20:23:05 +00:00
{
m_linMotion . terrainSpeed . x = 0.0f ;
m_linMotion . terrainSpeed . z = 0.0f ;
m_linMotion . terrainSpeed . y = 0.0f ;
}
else
{
tAngle = angle ;
2012-09-10 21:29:38 +00:00
h = m_terrain - > GetBuildingFactor ( pos ) ;
2012-06-26 20:23:05 +00:00
if ( type = = OBJECT_HUMAN | |
type = = OBJECT_TECH )
{
if ( m_linMotion . currentSpeed . x = = 0.0f )
{
h * = 0.5f ; // immobile man -> slippage
}
FloorAngle ( pos , tAngle ) ; // calculates the angle with the ground
}
2015-08-12 15:25:41 +00:00
2012-09-10 21:29:38 +00:00
if ( pos . y < m_water - > GetLevel ( m_object ) ) // underwater?
2012-06-26 20:23:05 +00:00
{
h * = 0.5f ;
2014-03-09 13:36:39 +00:00
m_fallingHeight = 0.0f ; // can't fall underwater
2012-06-26 20:23:05 +00:00
}
2015-08-12 15:25:41 +00:00
2012-06-26 20:23:05 +00:00
//? m_linMotion.terrainSpeed.x = -tAngle.z*m_linMotion.terrainForce.x*h;
//? m_linMotion.terrainSpeed.z = tAngle.x*m_linMotion.terrainForce.z*h;
//? m_linMotion.terrainSpeed.x = -sinf(tAngle.z)*Math::PI*0.5f*m_linMotion.terrainForce.x*h;
//? m_linMotion.terrainSpeed.z = sinf(tAngle.x)*Math::PI*0.5f*m_linMotion.terrainForce.z*h;
m_linMotion . terrainSpeed . x = - tanf ( tAngle . z ) * 0.9f * m_linMotion . terrainForce . x * h ;
m_linMotion . terrainSpeed . z = tanf ( tAngle . x ) * 0.9f * m_linMotion . terrainForce . z * h ;
m_linMotion . terrainSpeed . y = 0.0f ;
// If the terrain is very steep, do not exaggerate!
if ( m_linMotion . terrainSpeed . x > 50.0f ) m_linMotion . terrainSpeed . x = 20.0f ;
if ( m_linMotion . terrainSpeed . x < - 50.0f ) m_linMotion . terrainSpeed . x = - 20.0f ;
if ( m_linMotion . terrainSpeed . z > 50.0f ) m_linMotion . terrainSpeed . z = 20.0f ;
if ( m_linMotion . terrainSpeed . z < - 50.0f ) m_linMotion . terrainSpeed . z = - 20.0f ;
}
if ( type = = OBJECT_BEE & & ! m_bLand )
{
h = m_floorLevel ; // ground level
2012-09-10 21:29:38 +00:00
w = m_water - > GetLevel ( m_object ) ;
2012-06-26 20:23:05 +00:00
if ( h < w ) h = w ;
h = pos . y - h - 10.0f ; // maximum height (*)
if ( h < 0.0f ) h = 0.0f ;
m_linMotion . terrainSpeed . y = - h * 2.5f ; // is not above
}
// (*) High enough to pass over the tower defense (OBJECT_TOWER),
// but not too much to pass under the cover of the ship (OBJECT_BASE)!
UpdateMotionStruct ( event . rTime , m_linMotion ) ;
UpdateMotionStruct ( event . rTime , m_cirMotion ) ;
newangle = angle + event . rTime * m_cirMotion . realSpeed ;
Math : : LoadRotationZXYMatrix ( matRotate , newangle ) ;
newpos = event . rTime * m_linMotion . realSpeed ;
newpos = Transform ( matRotate , newpos ) ;
newpos + = pos ;
2012-09-10 21:29:38 +00:00
m_terrain - > AdjustToStandardBounds ( newpos ) ;
2012-06-26 20:23:05 +00:00
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) & & ! m_bLand )
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
h = m_terrain - > GetFlyingLimit ( newpos , type = = OBJECT_BEE ) ;
h + = m_object - > GetCharacter ( ) - > height ;
2012-06-26 20:23:05 +00:00
if ( newpos . y > h ) newpos . y = h ;
}
if ( m_bForceUpdate | |
newpos . x ! = pos . x | |
newpos . y ! = pos . y | |
newpos . z ! = pos . z | |
newangle . x ! = angle . x | |
newangle . y ! = angle . y | |
newangle . z ! = angle . z )
{
FloorAdapt ( m_time , event . rTime , newpos , newangle ) ;
}
if ( m_bForceUpdate | |
newpos . x ! = pos . x | |
newpos . y ! = pos . y | |
newpos . z ! = pos . z )
{
i = ObjectAdapt ( newpos , newangle ) ;
if ( i = = 2 ) // object destroyed?
{
return false ;
}
if ( i = = 1 ) // immobile object?
{
newpos = iPos ; // keeps the initial position, but accepts the rotation
}
}
if ( newangle . x ! = angle . x | |
newangle . y ! = angle . y | |
newangle . z ! = angle . z )
{
2015-07-14 19:29:13 +00:00
m_object - > SetRotation ( newangle ) ;
2012-06-26 20:23:05 +00:00
}
if ( newpos . x ! = pos . x | |
newpos . y ! = pos . y | |
newpos . z ! = pos . z )
{
2015-07-13 21:19:46 +00:00
m_object - > SetPosition ( newpos ) ;
2012-06-26 20:23:05 +00:00
}
2012-09-10 21:29:38 +00:00
MotorParticle ( m_time , event . rTime ) ;
2012-06-26 20:23:05 +00:00
SoundMotor ( event . rTime ) ;
2014-03-08 22:20:39 +00:00
if ( m_bLand & & m_fallingHeight ! = 0.0f ) // if fell
{
2016-04-07 18:21:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Damageable ) )
2015-09-13 18:43:11 +00:00
{
2016-04-07 18:21:35 +00:00
float force = ( m_fallingHeight - m_object - > GetPosition ( ) . y ) * m_fallDamageFraction ;
if ( m_object - > DamageObject ( DamageType : : Fall , force ) )
{
return false ; // ugly hack, but works for 0.1.6 release :/
}
2015-09-13 18:43:11 +00:00
}
2014-03-08 22:20:39 +00:00
m_fallingHeight = 0.0f ;
}
2012-06-26 20:23:05 +00:00
m_bForceUpdate = false ;
return true ;
}
// Starts or stops the engine sounds.
void CPhysics : : SoundMotor ( float rTime )
{
ObjectType type ;
m_lastSoundInsect - = rTime ;
2012-09-10 21:29:38 +00:00
type = m_object - > GetType ( ) ;
2012-06-26 20:23:05 +00:00
if ( type = = OBJECT_MOTHER )
{
2015-08-16 18:24:48 +00:00
if ( m_lastSoundInsect < = 0.0f & & m_object - > GetDetectable ( ) )
2012-06-26 20:23:05 +00:00
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_INSECTm , m_object - > GetPosition ( ) ) ;
2012-06-26 20:23:05 +00:00
if ( m_bMotor ) m_lastSoundInsect = 0.4f + Math : : Rand ( ) * 2.5f ;
else m_lastSoundInsect = 1.5f + Math : : Rand ( ) * 4.0f ;
}
}
else if ( type = = OBJECT_ANT )
{
2015-08-16 18:24:48 +00:00
assert ( m_object - > Implements ( ObjectInterfaceType : : Destroyable ) ) ;
2020-09-14 19:19:16 +00:00
if ( dynamic_cast < CDestroyableObject & > ( * m_object ) . GetDying ( ) = = DeathType : : Burning | |
dynamic_cast < CBaseAlien & > ( * m_object ) . GetFixed ( ) )
2012-06-26 20:23:05 +00:00
{
if ( m_lastSoundInsect < = 0.0f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_INSECTa , m_object - > GetPosition ( ) , 1.0f , 1.5f + Math : : Rand ( ) * 0.5f ) ;
2012-06-26 20:23:05 +00:00
m_lastSoundInsect = 0.4f + Math : : Rand ( ) * 0.6f ;
}
}
2015-08-16 18:24:48 +00:00
else if ( m_object - > GetDetectable ( ) )
2012-06-26 20:23:05 +00:00
{
if ( m_lastSoundInsect < = 0.0f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_INSECTa , m_object - > GetPosition ( ) ) ;
2012-06-26 20:23:05 +00:00
if ( m_bMotor ) m_lastSoundInsect = 0.4f + Math : : Rand ( ) * 2.5f ;
else m_lastSoundInsect = 1.5f + Math : : Rand ( ) * 4.0f ;
}
}
}
else if ( type = = OBJECT_BEE )
{
2015-08-16 18:24:48 +00:00
assert ( m_object - > Implements ( ObjectInterfaceType : : Destroyable ) ) ;
if ( m_object - > GetDetectable ( ) )
2012-06-26 20:23:05 +00:00
{
if ( m_lastSoundInsect < = 0.0f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_INSECTb , m_object - > GetPosition ( ) ) ;
2012-06-26 20:23:05 +00:00
if ( m_bMotor ) m_lastSoundInsect = 0.4f + Math : : Rand ( ) * 2.5f ;
else m_lastSoundInsect = 1.5f + Math : : Rand ( ) * 4.0f ;
}
}
2020-09-14 19:19:16 +00:00
else if ( dynamic_cast < CDestroyableObject & > ( * m_object ) . GetDying ( ) = = DeathType : : Burning )
2012-06-26 20:23:05 +00:00
{
if ( m_lastSoundInsect < = 0.0f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_INSECTb , m_object - > GetPosition ( ) , 1.0f , 1.5f + Math : : Rand ( ) * 0.5f ) ;
2012-06-26 20:23:05 +00:00
m_lastSoundInsect = 0.3f + Math : : Rand ( ) * 0.5f ;
}
}
}
else if ( type = = OBJECT_WORM )
{
2015-08-16 18:24:48 +00:00
assert ( m_object - > Implements ( ObjectInterfaceType : : Destroyable ) ) ;
if ( m_object - > GetDetectable ( ) )
2012-06-26 20:23:05 +00:00
{
if ( m_lastSoundInsect < = 0.0f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_INSECTw , m_object - > GetPosition ( ) ) ;
2012-06-26 20:23:05 +00:00
if ( m_bMotor ) m_lastSoundInsect = 0.4f + Math : : Rand ( ) * 2.5f ;
else m_lastSoundInsect = 1.5f + Math : : Rand ( ) * 4.0f ;
}
}
2020-09-14 19:19:16 +00:00
else if ( dynamic_cast < CDestroyableObject & > ( * m_object ) . GetDying ( ) = = DeathType : : Burning )
2012-06-26 20:23:05 +00:00
{
if ( m_lastSoundInsect < = 0.0f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_INSECTw , m_object - > GetPosition ( ) , 1.0f , 1.5f + Math : : Rand ( ) * 0.5f ) ;
2012-06-26 20:23:05 +00:00
m_lastSoundInsect = 0.2f + Math : : Rand ( ) * 0.2f ;
}
}
}
else if ( type = = OBJECT_SPIDER )
{
2015-08-16 18:24:48 +00:00
assert ( m_object - > Implements ( ObjectInterfaceType : : Destroyable ) ) ;
2020-09-14 19:19:16 +00:00
if ( dynamic_cast < CDestroyableObject & > ( * m_object ) . GetDying ( ) = = DeathType : : Burning | |
dynamic_cast < CBaseAlien & > ( * m_object ) . GetFixed ( ) )
2012-06-26 20:23:05 +00:00
{
if ( m_lastSoundInsect < = 0.0f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_INSECTs , m_object - > GetPosition ( ) , 1.0f , 1.5f + Math : : Rand ( ) * 0.5f ) ;
2012-06-26 20:23:05 +00:00
m_lastSoundInsect = 0.4f + Math : : Rand ( ) * 0.6f ;
}
}
2015-08-16 18:24:48 +00:00
else if ( m_object - > GetDetectable ( ) )
2012-06-26 20:23:05 +00:00
{
if ( m_lastSoundInsect < = 0.0f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_INSECTs , m_object - > GetPosition ( ) ) ;
2012-06-26 20:23:05 +00:00
if ( m_bMotor ) m_lastSoundInsect = 0.4f + Math : : Rand ( ) * 2.5f ;
else m_lastSoundInsect = 1.5f + Math : : Rand ( ) * 4.0f ;
}
}
}
else // vehicle?
{
2015-08-12 17:09:35 +00:00
if ( ! m_object - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
2015-08-16 18:24:48 +00:00
if ( m_bMotor & & m_object - > GetDetectable ( ) )
2012-06-26 20:23:05 +00:00
{
SoundMotorFull ( rTime , type ) ; // full diet
}
else
{
2015-07-10 21:47:59 +00:00
float energy = GetObjectEnergy ( m_object ) ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
if ( m_object - > GetSelect ( ) & &
2012-06-26 20:23:05 +00:00
energy ! = 0.0f )
{
SoundMotorSlow ( rTime , type ) ; // in slow motion
}
else
{
SoundMotorStop ( rTime , type ) ; // to the stop
}
}
}
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
if ( m_bMotor & & ! m_bSwim & &
2015-08-16 18:24:48 +00:00
m_object - > GetDetectable ( ) )
2012-06-26 20:23:05 +00:00
{
SoundReactorFull ( rTime , type ) ; // full diet
}
else
{
SoundReactorStop ( rTime , type ) ; // to the stop
}
}
}
}
// Detonates the object if it is underwater.
void CPhysics : : WaterFrame ( float aTime , float rTime )
{
ObjectType type ;
Math : : Vector pos , speed ;
Math : : Point dim ;
float level ;
2012-09-10 21:29:38 +00:00
level = m_water - > GetLevel ( ) ;
2012-06-26 20:23:05 +00:00
if ( level = = 0.0f ) return ; // no water?
2015-07-10 17:03:27 +00:00
if ( IsObjectBeingTransported ( m_object ) ) return ;
2012-06-26 20:23:05 +00:00
// Management of flames into the lava.
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-09-10 21:29:38 +00:00
if ( m_water - > GetLava ( ) & &
pos . y - m_object - > GetCharacter ( ) - > height < = level )
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
if ( m_lastFlameParticle + m_engine - > ParticleAdapt ( 0.05f ) < = aTime )
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
m_lastFlameParticle = aTime ;
2012-06-26 20:23:05 +00:00
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-06-26 20:23:05 +00:00
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 3.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 3.0f ;
speed . x = 0.0f ;
speed . z = 0.0f ;
speed . y = Math : : Rand ( ) * 5.0f + 3.0f ;
dim . x = Math : : Rand ( ) * 2.0f + 1.0f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIFLAME , 2.0f , 0.0f , 0.2f ) ;
2012-06-26 20:23:05 +00:00
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-06-26 20:23:05 +00:00
pos . y - = 2.0f ;
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 5.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 5.0f ;
speed . x = 0.0f ;
speed . z = 0.0f ;
speed . y = 6.0f + Math : : Rand ( ) * 6.0f + 6.0f ;
dim . x = Math : : Rand ( ) * 1.5f + 1.0f + 3.0f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTISMOKE3 , 4.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
2012-06-26 21:01:17 +00:00
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-09-10 21:29:38 +00:00
if ( pos . y > = m_water - > GetLevel ( m_object ) ) return ; // out of water?
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
type = m_object - > GetType ( ) ;
2012-06-26 20:23:05 +00:00
if ( type = = OBJECT_TOTO ) return ;
if ( type = = OBJECT_NULL ) return ;
2015-08-16 18:24:48 +00:00
if ( ! m_object - > GetDetectable ( ) ) return ;
2012-06-26 20:23:05 +00:00
2015-08-13 16:54:44 +00:00
if ( type = = OBJECT_HUMAN & & m_object - > GetOption ( ) ! = 0 ) // human without a helmet?)
{
assert ( m_object - > Implements ( ObjectInterfaceType : : Destroyable ) ) ;
dynamic_cast < CDestroyableObject * > ( m_object ) - > DestroyObject ( DestructionType : : Drowned ) ;
}
else if ( m_water - > GetLava ( ) | |
type = = OBJECT_MOBILEfa | | // TODO: A function in CObject to check if object is waterproof or not
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEta | |
type = = OBJECT_MOBILEwa | |
type = = OBJECT_MOBILEia | |
2017-11-16 17:43:45 +00:00
type = = OBJECT_MOBILEfb | |
type = = OBJECT_MOBILEtb | |
type = = OBJECT_MOBILEwb | |
type = = OBJECT_MOBILEib | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEfc | |
type = = OBJECT_MOBILEtc | |
type = = OBJECT_MOBILEwc | |
type = = OBJECT_MOBILEic | |
type = = OBJECT_MOBILEfi | |
type = = OBJECT_MOBILEti | |
type = = OBJECT_MOBILEwi | |
type = = OBJECT_MOBILEii | |
type = = OBJECT_MOBILEfs | |
type = = OBJECT_MOBILEts | |
type = = OBJECT_MOBILEws | |
type = = OBJECT_MOBILEis | |
type = = OBJECT_MOBILErt | |
type = = OBJECT_MOBILErc | |
type = = OBJECT_MOBILErr | |
type = = OBJECT_MOBILErs | |
type = = OBJECT_MOBILEft | |
type = = OBJECT_MOBILEtt | |
type = = OBJECT_MOBILEwt | |
type = = OBJECT_MOBILEit | |
2018-12-23 06:04:06 +00:00
type = = OBJECT_MOBILErp | |
2019-07-05 14:03:29 +00:00
type = = OBJECT_MOBILEtg | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEdr | |
2015-08-13 16:54:44 +00:00
type = = OBJECT_APOLLO2 )
2012-06-26 20:23:05 +00:00
{
2015-08-13 16:54:44 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Destroyable ) )
{
dynamic_cast < CDestroyableObject * > ( m_object ) - > DestroyObject ( DestructionType : : ExplosionWater ) ;
}
2012-06-26 20:23:05 +00:00
}
}
// Sounds the engine at full power.
void CPhysics : : SoundMotorFull ( float rTime , ObjectType type )
{
2015-07-05 11:00:48 +00:00
SoundType sound ;
2012-06-26 20:23:05 +00:00
float amplitude , time , freq ;
if ( type = = OBJECT_MOBILEia | |
2017-11-16 17:43:45 +00:00
type = = OBJECT_MOBILEib | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEic | |
type = = OBJECT_MOBILEii | |
2017-12-21 00:49:56 +00:00
type = = OBJECT_MOBILEis | |
type = = OBJECT_MOBILEit )
2012-06-26 20:23:05 +00:00
{
if ( m_soundChannel = = - 1 )
{
2015-07-12 09:01:16 +00:00
m_soundChannel = m_sound - > Play ( SOUND_MOTORi , m_object - > GetPosition ( ) , 0.0f , 1.0f , true ) ;
2012-06-26 20:23:05 +00:00
m_sound - > AddEnvelope ( m_soundChannel , 1.0f , 1.0f , 0.2f , SOPER_CONTINUE ) ;
m_sound - > AddEnvelope ( m_soundChannel , 1.0f , 1.0f , 1.0f , SOPER_LOOP ) ;
}
else
{
2015-07-12 09:01:16 +00:00
m_sound - > Position ( m_soundChannel , m_object - > GetPosition ( ) ) ;
2012-06-26 20:23:05 +00:00
}
freq = 1.0f + m_linMotion . terrainSpeed . x / 50.0f ;
if ( m_linMotion . realSpeed . x = = 0.0f )
{
freq - = fabs ( m_cirMotion . realSpeed . y / 3.0f ) ;
}
else
{
freq - = fabs ( m_cirMotion . realSpeed . y / 4.0f ) ;
}
m_sound - > Frequency ( m_soundChannel , freq ) ;
return ;
}
2018-12-23 06:04:06 +00:00
if ( type = = OBJECT_MOBILEsa | |
type = = OBJECT_MOBILEst )
2012-06-26 20:23:05 +00:00
{
sound = SOUND_MOTORs ;
amplitude = 0.6f ;
time = 0.5f ;
}
else if ( type = = OBJECT_MOBILErt | |
type = = OBJECT_MOBILErc | |
type = = OBJECT_MOBILErr | |
2018-12-23 06:04:06 +00:00
type = = OBJECT_MOBILErs | |
type = = OBJECT_MOBILErp )
2012-06-26 20:23:05 +00:00
{
sound = SOUND_MOTORr ;
amplitude = 1.0f ;
time = 0.7f ;
}
else if ( type = = OBJECT_MOBILEta | |
type = = OBJECT_MOBILEtc | |
type = = OBJECT_MOBILEti | |
2017-12-21 00:49:56 +00:00
type = = OBJECT_MOBILEts | |
type = = OBJECT_MOBILEtt )
2012-06-26 20:23:05 +00:00
{
sound = SOUND_MOTORt ;
amplitude = 1.0f ;
time = 0.5f ;
}
else if ( type = = OBJECT_APOLLO2 )
{
sound = SOUND_MANIP ;
amplitude = 1.0f ;
time = 0.5f ;
}
else
{
sound = SOUND_MOTORw ;
amplitude = 0.7f ;
time = 0.3f ;
}
2012-09-10 21:29:38 +00:00
if ( m_object - > GetToy ( ) )
2012-06-26 20:23:05 +00:00
{
2015-10-04 16:13:13 +00:00
sound = SOUND_MOTORd ;
2012-06-26 20:23:05 +00:00
amplitude = 1.0f ;
time = 0.1f ;
}
freq = 0.75f + ( fabs ( m_motorSpeed . x ) + fabs ( m_motorSpeed . z ) ) * 0.25f ;
if ( freq > 1.0f ) freq = 1.0f ;
2012-09-10 21:29:38 +00:00
if ( m_object - > GetToy ( ) ) freq = 1.0f ;
2012-06-26 20:23:05 +00:00
if ( m_soundChannel = = - 1 )
{
2015-07-12 09:01:16 +00:00
m_soundChannel = m_sound - > Play ( sound , m_object - > GetPosition ( ) , 0.0f , 0.5f , true ) ;
2012-06-26 20:23:05 +00:00
m_sound - > AddEnvelope ( m_soundChannel , amplitude , freq , time , SOPER_CONTINUE ) ;
m_sound - > AddEnvelope ( m_soundChannel , amplitude , freq , 1.0f , SOPER_LOOP ) ;
}
else
{
2015-07-12 09:01:16 +00:00
m_sound - > Position ( m_soundChannel , m_object - > GetPosition ( ) ) ;
2012-06-26 20:23:05 +00:00
if ( m_bSoundSlow ) // in slow motion?
{
m_sound - > FlushEnvelope ( m_soundChannel ) ;
m_sound - > AddEnvelope ( m_soundChannel , amplitude , freq , time , SOPER_CONTINUE ) ;
m_sound - > AddEnvelope ( m_soundChannel , amplitude , freq , 1.0f , SOPER_LOOP ) ;
m_bSoundSlow = false ;
}
}
freq * = 1.0f + m_linMotion . terrainSpeed . x / 100.0f ;
freq * = 1.0f + fabs ( m_cirMotion . realSpeed . y / 20.0f ) ;
m_sound - > Frequency ( m_soundChannel , freq ) ;
m_soundTimePshhh - = rTime * 2.0f ;
}
// Sounds the engine idling.
void CPhysics : : SoundMotorSlow ( float rTime , ObjectType type )
{
Math : : Matrix * mat ;
Math : : Vector pos , speed ;
Math : : Point dim ;
2015-07-05 11:00:48 +00:00
SoundType sound ;
2012-06-26 20:23:05 +00:00
float amplitude ;
int i , max ;
if ( type = = OBJECT_MOBILEia | |
2017-11-16 17:43:45 +00:00
type = = OBJECT_MOBILEib | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEic | |
type = = OBJECT_MOBILEii | |
2017-12-21 00:49:56 +00:00
type = = OBJECT_MOBILEis | |
type = = OBJECT_MOBILEit )
2012-06-26 20:23:05 +00:00
{
if ( m_soundChannel ! = - 1 ) // engine is running?
{
m_sound - > FlushEnvelope ( m_soundChannel ) ;
m_sound - > AddEnvelope ( m_soundChannel , 0.0f , 1.0f , 0.3f , SOPER_STOP ) ;
m_soundChannel = - 1 ;
}
return ;
}
2018-12-23 06:04:06 +00:00
if ( type = = OBJECT_MOBILEsa | |
type = = OBJECT_MOBILEst )
2012-06-26 20:23:05 +00:00
{
sound = SOUND_MOTORs ;
amplitude = 0.4f ;
}
else if ( type = = OBJECT_MOBILErt | |
type = = OBJECT_MOBILErc | |
type = = OBJECT_MOBILErr | |
2018-12-23 06:04:06 +00:00
type = = OBJECT_MOBILErs | |
type = = OBJECT_MOBILErp )
2012-06-26 20:23:05 +00:00
{
sound = SOUND_MOTORr ;
amplitude = 0.9f ;
}
else if ( type = = OBJECT_MOBILEta | |
2017-11-16 17:43:45 +00:00
type = = OBJECT_MOBILEtb | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEtc | |
type = = OBJECT_MOBILEti | |
2017-12-21 00:49:56 +00:00
type = = OBJECT_MOBILEts | |
type = = OBJECT_MOBILEtt )
2012-06-26 20:23:05 +00:00
{
sound = SOUND_MOTORt ;
amplitude = 0.7f ;
}
else if ( type = = OBJECT_APOLLO2 )
{
if ( m_soundChannel ! = - 1 ) // engine is running?
{
m_sound - > FlushEnvelope ( m_soundChannel ) ;
m_sound - > AddEnvelope ( m_soundChannel , 0.0f , 0.5f , 0.3f , SOPER_STOP ) ;
m_soundChannel = - 1 ;
}
return ;
}
else
{
sound = SOUND_MOTORw ;
amplitude = 0.3f ;
}
2012-09-10 21:29:38 +00:00
if ( m_object - > GetToy ( ) )
2012-06-26 20:23:05 +00:00
{
2015-10-04 16:13:13 +00:00
sound = SOUND_MOTORd ;
2012-06-26 20:23:05 +00:00
amplitude = 0.0f ;
}
if ( m_soundChannel = = - 1 )
{
2015-07-12 09:01:16 +00:00
m_soundChannel = m_sound - > Play ( sound , m_object - > GetPosition ( ) , 0.0f , 0.25f , true ) ;
2012-06-26 20:23:05 +00:00
m_sound - > AddEnvelope ( m_soundChannel , amplitude , 0.5f , 0.2f , SOPER_CONTINUE ) ;
m_sound - > AddEnvelope ( m_soundChannel , amplitude , 0.5f , 1.0f , SOPER_LOOP ) ;
}
else
{
2015-07-12 09:01:16 +00:00
m_sound - > Position ( m_soundChannel , m_object - > GetPosition ( ) ) ;
2012-06-26 20:23:05 +00:00
if ( ! m_bSoundSlow ) // full power?
{
m_sound - > FlushEnvelope ( m_soundChannel ) ;
m_sound - > AddEnvelope ( m_soundChannel , amplitude , 0.5f , 0.3f , SOPER_CONTINUE ) ;
m_sound - > AddEnvelope ( m_soundChannel , amplitude , 0.5f , 1.0f , SOPER_LOOP ) ;
m_bSoundSlow = true ;
}
}
if ( type = = OBJECT_MOBILErt | |
type = = OBJECT_MOBILErc | |
type = = OBJECT_MOBILErr | |
2018-12-23 06:04:06 +00:00
type = = OBJECT_MOBILErs | |
type = = OBJECT_MOBILErp )
2012-06-26 20:23:05 +00:00
{
m_soundTimePshhh - = rTime ;
if ( m_soundTimePshhh < = 0.0f )
{
amplitude = 0.5f - m_soundTimePshhh * 0.08f ;
if ( amplitude > 1.0f ) amplitude = 1.0f ;
2015-07-12 09:01:16 +00:00
//? m_sound->Play(SOUND_PSHHH, m_object->GetPosition(), amplitude);
m_sound - > Play ( SOUND_PSHHH , m_object - > GetPosition ( ) , 1.0f ) ;
2012-06-26 20:23:05 +00:00
m_soundTimePshhh = 4.0f + 4.0f * Math : : Rand ( ) ;
2012-09-10 21:29:38 +00:00
max = static_cast < int > ( 10.0f * m_engine - > GetParticleDensity ( ) ) ;
2012-06-26 20:23:05 +00:00
for ( i = 0 ; i < max ; i + + )
{
pos = Math : : Vector ( - 5.0f , 2.0f , 0.0f ) ;
pos . x + = Math : : Rand ( ) * 4.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
speed = pos ;
speed . x - = Math : : Rand ( ) * 4.0f ;
speed . y - = Math : : Rand ( ) * 3.0f ;
speed . z + = ( Math : : Rand ( ) - 0.5f ) * 6.0f ;
2012-06-26 21:01:17 +00:00
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
speed = Transform ( * mat , speed ) - pos ;
dim . x = Math : : Rand ( ) * 1.0f + 1.0f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIMOTOR , 2.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
}
}
// Sounds the engine not running.
void CPhysics : : SoundMotorStop ( float rTime , ObjectType type )
{
if ( type = = OBJECT_MOBILEia | |
2017-11-16 17:43:45 +00:00
type = = OBJECT_MOBILEib | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEic | |
type = = OBJECT_MOBILEii | |
2017-12-21 00:49:56 +00:00
type = = OBJECT_MOBILEis | |
type = = OBJECT_MOBILEit )
2012-06-26 20:23:05 +00:00
{
if ( m_soundChannel ! = - 1 ) // engine is running?
{
m_sound - > FlushEnvelope ( m_soundChannel ) ;
m_sound - > AddEnvelope ( m_soundChannel , 0.0f , 1.0f , 0.3f , SOPER_STOP ) ;
m_soundChannel = - 1 ;
}
return ;
}
if ( m_soundChannel ! = - 1 ) // engine is running?
{
m_sound - > FlushEnvelope ( m_soundChannel ) ;
m_sound - > AddEnvelope ( m_soundChannel , 0.0f , 0.5f , 0.3f , SOPER_STOP ) ;
m_soundChannel = - 1 ;
}
m_soundTimePshhh - = rTime * 2.0f ;
}
// Sounds the reactor at full power.
void CPhysics : : SoundReactorFull ( float rTime , ObjectType type )
{
2015-07-05 11:00:48 +00:00
SoundType sound ;
2012-06-26 20:23:05 +00:00
Math : : Matrix * mat ;
Math : : Vector pos , speed ;
Math : : Point dim ;
float freq ;
int i ;
if ( m_soundChannelSlide ! = - 1 ) // slides?
{
m_sound - > FlushEnvelope ( m_soundChannelSlide ) ;
m_sound - > AddEnvelope ( m_soundChannelSlide , 0.0f , 1.0f , 0.3f , SOPER_STOP ) ;
m_soundChannelSlide = - 1 ;
}
2015-08-13 08:49:26 +00:00
if ( ! m_object - > Implements ( ObjectInterfaceType : : JetFlying ) | | dynamic_cast < CJetFlyingObject * > ( m_object ) - > GetReactorRange ( ) > 0.0f )
2012-06-26 20:23:05 +00:00
{
if ( m_soundChannel = = - 1 )
{
if ( type = = OBJECT_HUMAN | |
type = = OBJECT_TECH )
{
sound = SOUND_FLYh ;
}
else
{
sound = SOUND_FLY ;
}
2015-07-12 09:01:16 +00:00
m_soundChannel = m_sound - > Play ( sound , m_object - > GetPosition ( ) , 0.0f , 1.0f , true ) ;
2012-06-26 20:23:05 +00:00
m_sound - > AddEnvelope ( m_soundChannel , 1.0f , 1.0f , 0.6f , SOPER_CONTINUE ) ;
m_sound - > AddEnvelope ( m_soundChannel , 1.0f , 1.0f , 1.0f , SOPER_LOOP ) ;
}
else
{
2015-07-12 09:01:16 +00:00
m_sound - > Position ( m_soundChannel , m_object - > GetPosition ( ) ) ;
2012-06-26 20:23:05 +00:00
}
freq = 1.0f + m_linMotion . realSpeed . y / 100.0f ;
freq * = 1.0f + fabs ( m_cirMotion . realSpeed . y / 5.0f ) ;
m_sound - > Frequency ( m_soundChannel , freq ) ;
}
else
{
if ( m_soundChannel ! = - 1 ) // engine is running?
{
m_sound - > FlushEnvelope ( m_soundChannel ) ;
m_sound - > AddEnvelope ( m_soundChannel , 0.0f , 1.0f , 1.0f , SOPER_STOP ) ;
m_soundChannel = - 1 ;
}
if ( m_timeReactorFail < = m_time )
{
freq = 1.0f + Math : : Rand ( ) * 0.5f ;
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_FLYf , m_object - > GetPosition ( ) , 1.0f , freq ) ;
m_camera - > StartEffect ( Gfx : : CAM_EFFECT_PET , m_object - > GetPosition ( ) , 1.0f ) ;
2012-06-26 20:23:05 +00:00
for ( i = 0 ; i < 5 ; i + + )
{
2012-09-10 21:29:38 +00:00
if ( m_object - > GetType ( ) = = OBJECT_HUMAN | |
m_object - > GetType ( ) = = OBJECT_TECH )
2012-06-26 20:23:05 +00:00
{
pos = Math : : Vector ( - 1.6f , - 0.5f , 0.0f ) ;
}
else
{
pos = Math : : Vector ( 0.0f , - 1.0f , 0.0f ) ;
}
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 5.0f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 5.0f ;
speed . y = - ( 4.0f + Math : : Rand ( ) * 4.0f ) ;
dim . x = ( 2.0f + Math : : Rand ( ) * 1.0f ) ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTISMOKE1 , 2.0f , 0.0f , 0.1f ) ;
2012-06-26 20:23:05 +00:00
}
m_timeReactorFail = m_time + 0.10f + Math : : Rand ( ) * 0.30f ;
}
else
{
2012-09-10 21:29:38 +00:00
if ( m_object - > GetType ( ) = = OBJECT_HUMAN | |
m_object - > GetType ( ) = = OBJECT_TECH )
2012-06-26 20:23:05 +00:00
{
pos = Math : : Vector ( - 1.6f , - 0.5f , 0.0f ) ;
}
else
{
pos = Math : : Vector ( 0.0f , - 1.0f , 0.0f ) ;
}
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
speed . y = - ( 4.0f + Math : : Rand ( ) * 4.0f ) ;
dim . x = ( 0.7f + Math : : Rand ( ) * 0.4f ) ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTISMOKE1 , 2.0f , 0.0f , 0.1f ) ;
2012-06-26 20:23:05 +00:00
}
}
}
// Sounds the reactor stopped.
void CPhysics : : SoundReactorStop ( float rTime , ObjectType type )
{
2015-07-10 21:47:59 +00:00
float energy = GetObjectEnergy ( m_object ) ;
2012-06-26 20:23:05 +00:00
if ( m_soundChannel ! = - 1 ) // engine is running?
{
m_sound - > FlushEnvelope ( m_soundChannel ) ;
m_sound - > AddEnvelope ( m_soundChannel , 0.0f , 1.0f , 1.0f , SOPER_STOP ) ;
m_soundChannel = - 1 ;
}
if ( type = = OBJECT_HUMAN | |
type = = OBJECT_TECH )
{
if ( m_soundChannelSlide ! = - 1 ) // slides?
{
m_sound - > FlushEnvelope ( m_soundChannelSlide ) ;
m_sound - > AddEnvelope ( m_soundChannelSlide , 0.0f , 1.0f , 0.3f , SOPER_STOP ) ;
m_soundChannelSlide = - 1 ;
}
}
else
{
if ( energy ! = 0.0f & &
( m_motorSpeed . x ! = 0.0f | | // slides with small reactors in skates?
m_cirMotion . realSpeed . y ! = 0.0f ) )
{
if ( m_soundChannelSlide = = - 1 )
{
2015-07-12 09:01:16 +00:00
m_soundChannelSlide = m_sound - > Play ( SOUND_SLIDE , m_object - > GetPosition ( ) , 0.0f , 1.0f , true ) ;
2012-06-26 20:23:05 +00:00
m_sound - > AddEnvelope ( m_soundChannelSlide , 0.5f , 1.0f , 0.3f , SOPER_CONTINUE ) ;
m_sound - > AddEnvelope ( m_soundChannelSlide , 0.5f , 1.0f , 1.0f , SOPER_LOOP ) ;
}
2015-07-12 09:01:16 +00:00
m_sound - > Position ( m_soundChannelSlide , m_object - > GetPosition ( ) ) ;
2012-06-26 20:23:05 +00:00
}
else
{
if ( m_soundChannelSlide ! = - 1 ) // slides?
{
m_sound - > FlushEnvelope ( m_soundChannelSlide ) ;
m_sound - > AddEnvelope ( m_soundChannelSlide , 0.0f , 1.0f , 0.3f , SOPER_STOP ) ;
m_soundChannelSlide = - 1 ;
}
}
}
}
// Adapts the physics of the object based on the ground.
void CPhysics : : FloorAdapt ( float aTime , float rTime ,
Math : : Vector & pos , Math : : Vector & angle )
{
Character * character ;
ObjectType type ;
Math : : Vector norm ;
Math : : Matrix matRotate ;
float level , h , f , a1 , volume , freq , force ;
2012-09-10 21:29:38 +00:00
bool bSlopingTerrain ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
type = m_object - > GetType ( ) ;
character = m_object - > GetCharacter ( ) ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
level = m_water - > GetLevel ( m_object ) ;
2012-06-26 20:23:05 +00:00
SetSwim ( pos . y < level ) ;
2012-09-10 21:29:38 +00:00
m_floorLevel = m_terrain - > GetFloorLevel ( pos ) ; // height above the ground
2012-06-26 20:23:05 +00:00
h = pos . y - m_floorLevel ;
h - = character - > height ;
m_floorHeight = h ;
2012-09-10 21:29:38 +00:00
WaterParticle ( aTime , pos , type , m_floorLevel ,
2012-06-26 20:23:05 +00:00
fabs ( m_linMotion . realSpeed . x ) ,
fabs ( m_cirMotion . realSpeed . y * 15.0f ) ) ;
2015-08-12 17:09:35 +00:00
if ( ! m_object - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
pos . y - = h ; // plate to the ground immediately
pos . y + = character - > height ;
m_floorHeight = 0.0f ;
}
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
bSlopingTerrain = false ; // ground as possible to land
if ( ! m_bLand ) // in flight?
{
m_terrain - > GetNormal ( norm , pos ) ;
a1 = fabs ( Math : : RotateAngle ( Math : : Point ( norm . x , norm . z ) . Length ( ) , norm . y ) ) ;
if ( a1 < ( 90.0f - 55.0f ) * Math : : PI / 180.0f ) // slope exceeds 55 degrees?
{
bSlopingTerrain = true ; // very sloped ground
if ( h < 4.0f ) // collision with the ground?
{
force = 5.0f + fabs ( m_linMotion . realSpeed . x * 0.3f ) +
fabs ( m_linMotion . realSpeed . y * 0.3f ) ;
m_linMotion . currentSpeed = norm * force ;
Math : : LoadRotationXZYMatrix ( matRotate , - angle ) ;
m_linMotion . currentSpeed = Transform ( matRotate , m_linMotion . currentSpeed ) ;
if ( aTime - m_soundTimeBoum > 0.5f )
{
volume = fabs ( m_linMotion . realSpeed . x * 0.02f ) +
fabs ( m_linMotion . realSpeed . y * 0.02f ) ;
2012-09-10 21:29:38 +00:00
freq = 0.5f + m_terrain - > GetHardness ( pos ) * 2.5f ;
2012-06-26 20:23:05 +00:00
m_sound - > Play ( SOUND_BOUM , pos , volume , freq ) ;
m_soundTimeBoum = aTime ;
}
2015-07-12 09:01:16 +00:00
//? pos = m_object->GetPosition(); // gives position before collision
2012-06-26 20:23:05 +00:00
}
}
}
if ( ( h < = 0.0f | | m_bLand ) & & ! bSlopingTerrain ) // on the ground?
{
if ( ! m_bLand ) // in flight?
{
volume = fabs ( m_linMotion . realSpeed . y * 0.02f ) ;
2012-09-10 21:29:38 +00:00
freq = 0.5f + m_terrain - > GetHardness ( pos ) * 2.5f ;
2012-06-26 20:23:05 +00:00
m_sound - > Play ( SOUND_BOUM , pos , volume , freq ) ;
}
m_bLand = true ; // on the ground?
SetMotor ( false ) ;
pos . y - = h ; // plate to the ground immediately
m_floorHeight = 0.0f ;
if ( h < 0.0f )
{
f = fabs ( m_linMotion . currentSpeed . y / m_linMotion . advanceSpeed . y ) ;
2012-09-10 21:29:38 +00:00
CrashParticle ( f ) ;
2012-06-26 20:23:05 +00:00
}
m_linMotion . currentSpeed . y = 0.0f ;
m_inclinaisonFactor = 1.0f / LANDING_SPEED ; // slips a little to the ground
m_linVibrationFactor = 0.0f ;
m_cirVibrationFactor = 0.0f ;
if ( type = = OBJECT_HUMAN | |
type = = OBJECT_TECH ) return ; // always right
}
if ( h > 4.0f | | bSlopingTerrain ) // meters above the ground?
{
if ( m_bSwim )
{
m_linVibrationFactor = 1.0f ; // vibrates a max
m_cirVibrationFactor = 1.0f ;
}
else
{
m_linVibrationFactor = 2.0f ; // vibrates a large max
m_cirVibrationFactor = 2.0f ;
}
m_inclinaisonFactor = 1.0f ;
// Gives gently the horizontal.
if ( angle . x > 0.0f )
{
angle . x - = rTime * 0.5f ;
if ( angle . x < 0.0f ) angle . x = 0.0f ;
}
if ( angle . x < 0.0f )
{
angle . x + = rTime * 0.5f ;
if ( angle . x > 0.0f ) angle . x = 0.0f ;
}
if ( angle . z > 0.0f )
{
angle . z - = rTime * 0.5f ;
if ( angle . z < 0.0f ) angle . z = 0.0f ;
}
if ( angle . z < 0.0f )
{
angle . z + = rTime * 0.5f ;
if ( angle . z > 0.0f ) angle . z = 0.0f ;
}
return ;
}
}
if ( m_floorHeight = = 0.0f ) // ground plate?
{
2015-08-13 08:49:26 +00:00
CTraceDrawingObject * traceDrawing = nullptr ;
if ( m_object - > Implements ( ObjectInterfaceType : : TraceDrawing ) )
traceDrawing = dynamic_cast < CTraceDrawingObject * > ( m_object ) ;
if ( traceDrawing ! = nullptr & & traceDrawing - > GetTraceDown ( ) )
2012-06-26 20:23:05 +00:00
{
2015-08-13 08:49:26 +00:00
WheelParticle ( traceDrawing - > GetTraceColor ( ) , traceDrawing - > GetTraceWidth ( ) * g_unit ) ;
2012-06-26 20:23:05 +00:00
}
else
{
2015-07-14 11:42:47 +00:00
WheelParticle ( TraceColor : : Default , 0.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
if ( type = = OBJECT_HUMAN | |
type = = OBJECT_TECH | |
type = = OBJECT_WORM ) return ; // always right
FloorAngle ( pos , angle ) ; // adjusts the angle at the ground
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) & & ! m_bLand ) // flying in the air?
2012-06-26 20:23:05 +00:00
{
f = h / 1.0f ;
if ( f < 0.0f ) f = 0.0f ;
if ( f > 1.0f ) f = 1.0f ;
m_linVibrationFactor = f ;
m_cirVibrationFactor = f ;
angle . z * = 1.0f - f ;
angle . x * = 1.0f - f ;
f = h / 1.0f ;
if ( f < 0.0f ) f = 0.0f ;
if ( f > 1.0f ) f = 1.0f ;
m_inclinaisonFactor = f ;
}
}
// Calculates the angle of an object with the field.
void CPhysics : : FloorAngle ( const Math : : Vector & pos , Math : : Vector & angle )
{
Character * character ;
Math : : Vector pw , norm ;
float a1 , a2 ;
2012-09-10 21:29:38 +00:00
character = m_object - > GetCharacter ( ) ;
2012-06-26 20:23:05 +00:00
pw . x = pos . x + character - > wheelFront * cosf ( angle . y + Math : : PI * 0.0f ) ;
pw . y = pos . y ;
pw . z = pos . z - character - > wheelFront * sinf ( angle . y + Math : : PI * 0.0f ) ;
2012-09-10 21:29:38 +00:00
a1 = atanf ( m_terrain - > GetHeightToFloor ( pw ) / character - > wheelFront ) ;
2012-06-26 20:23:05 +00:00
pw . x = pos . x + character - > wheelBack * cosf ( angle . y + Math : : PI * 1.0f ) ;
pw . y = pos . y ;
pw . z = pos . z - character - > wheelBack * sinf ( angle . y + Math : : PI * 1.0f ) ;
2012-09-10 21:29:38 +00:00
a2 = atanf ( m_terrain - > GetHeightToFloor ( pw ) / character - > wheelBack ) ;
2012-06-26 20:23:05 +00:00
angle . z = ( a2 - a1 ) / 2.0f ;
pw . x = pos . x + character - > wheelLeft * cosf ( angle . y + Math : : PI * 0.5f ) * cosf ( angle . z ) ;
pw . y = pos . y ;
pw . z = pos . z - character - > wheelLeft * sinf ( angle . y + Math : : PI * 0.5f ) * cosf ( angle . z ) ;
2012-09-10 21:29:38 +00:00
a1 = atanf ( m_terrain - > GetHeightToFloor ( pw ) / character - > wheelLeft ) ;
2012-06-26 20:23:05 +00:00
pw . x = pos . x + character - > wheelRight * cosf ( angle . y + Math : : PI * 1.5f ) * cosf ( angle . z ) ;
pw . y = pos . y ;
pw . z = pos . z - character - > wheelRight * sinf ( angle . y + Math : : PI * 1.5f ) * cosf ( angle . z ) ;
2012-09-10 21:29:38 +00:00
a2 = atanf ( m_terrain - > GetHeightToFloor ( pw ) / character - > wheelRight ) ;
2012-06-26 20:23:05 +00:00
angle . x = ( a2 - a1 ) / 2.0f ;
}
// Adapts the physics of the object in relation to other objects.
// Returns 0 -> mobile object
// Returns 1 -> immobile object (because collision)
// Returns 2 -> destroyed object
int CPhysics : : ObjectAdapt ( const Math : : Vector & pos , const Math : : Vector & angle )
{
Math : : Matrix matRotate ;
2015-07-10 07:26:38 +00:00
Math : : Vector iPos , oAngle , oSpeed ;
float distance , force , volume ;
int colType ;
2012-09-10 21:29:38 +00:00
ObjectType iType , oType ;
2012-06-26 20:23:05 +00:00
2020-09-14 19:19:16 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Destroyable ) & & dynamic_cast < CDestroyableObject & > ( * m_object ) . IsDying ( ) ) return 0 ; // is burning or exploding?
2015-08-11 15:51:39 +00:00
if ( ! m_object - > GetCollisions ( ) ) return 0 ;
2012-06-26 20:23:05 +00:00
// iiPos = sphere center is the old position.
// iPos = sphere center has the new position.
2015-07-10 21:57:06 +00:00
if ( m_object - > GetCrashSphereCount ( ) < 1 )
return 0 ;
2015-07-10 07:26:38 +00:00
auto firstCrashSphere = m_object - > GetFirstCrashSphere ( ) ;
Math : : Vector iiPos = firstCrashSphere . sphere . pos ;
float iRad = firstCrashSphere . sphere . radius ;
2015-07-12 09:01:16 +00:00
iPos = iiPos + ( pos - m_object - > GetPosition ( ) ) ;
2012-09-10 21:29:38 +00:00
iType = m_object - > GetType ( ) ;
2012-06-26 20:23:05 +00:00
2015-06-21 14:22:09 +00:00
for ( CObject * pObj : CObjectManager : : GetInstancePointer ( ) - > GetAllObjects ( ) )
2012-06-26 20:23:05 +00:00
{
if ( pObj = = m_object ) continue ; // yourself?
2015-07-10 17:03:27 +00:00
if ( IsObjectBeingTransported ( pObj ) ) continue ;
2020-09-14 19:19:16 +00:00
if ( pObj - > Implements ( ObjectInterfaceType : : Destroyable ) & & dynamic_cast < CDestroyableObject & > ( * pObj ) . GetDying ( ) = = DeathType : : Exploding ) continue ; // is exploding?
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
oType = pObj - > GetType ( ) ;
2015-08-18 10:29:41 +00:00
if ( oType = = OBJECT_TOTO ) continue ;
if ( ! m_object - > CanCollideWith ( pObj ) ) continue ;
2012-06-26 20:23:05 +00:00
2015-07-10 20:11:22 +00:00
if ( pObj - > Implements ( ObjectInterfaceType : : Jostleable ) )
2012-06-26 20:23:05 +00:00
{
2015-07-10 20:11:22 +00:00
JostleObject ( dynamic_cast < CJostleableObject * > ( pObj ) , iPos , iRad ) ;
2012-06-26 20:23:05 +00:00
}
if ( oType = = OBJECT_WAYPOINT & &
2015-08-11 22:12:37 +00:00
! pObj - > GetLock ( ) & &
2012-09-10 21:29:38 +00:00
m_object - > GetTrainer ( ) ) // driving vehicle?
2012-06-26 20:23:05 +00:00
{
2015-07-12 09:01:16 +00:00
Math : : Vector oPos = pObj - > GetPosition ( ) ;
2012-06-26 20:23:05 +00:00
distance = Math : : DistanceProjected ( oPos , iPos ) ;
if ( distance < 4.0f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_WAYPOINT , m_object - > GetPosition ( ) ) ;
2015-06-22 19:58:58 +00:00
m_engine - > GetPyroManager ( ) - > Create ( Gfx : : PT_WPCHECK , pObj ) ;
2012-06-26 20:23:05 +00:00
}
}
2015-08-13 20:32:49 +00:00
if ( oType = = OBJECT_TARGET2 & & ! pObj - > GetLock ( ) )
2012-06-26 20:23:05 +00:00
{
2015-07-12 09:01:16 +00:00
Math : : Vector oPos = pObj - > GetPosition ( ) ;
2012-06-26 20:23:05 +00:00
distance = Math : : Distance ( oPos , iPos ) ;
if ( distance < 10.0f * 1.5f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_WAYPOINT , m_object - > GetPosition ( ) ) ;
2015-06-22 19:58:58 +00:00
m_engine - > GetPyroManager ( ) - > Create ( Gfx : : PT_WPCHECK , pObj ) ;
2012-06-26 20:23:05 +00:00
}
}
2015-07-10 07:26:38 +00:00
for ( const auto & crashSphere : pObj - > GetAllCrashSpheres ( ) )
2012-06-26 20:23:05 +00:00
{
2015-07-10 07:26:38 +00:00
Math : : Vector oPos = crashSphere . sphere . pos ;
float oRad = crashSphere . sphere . radius ;
2015-08-18 10:29:41 +00:00
// Aliens ignore small objects
// TODO: But why? :/
2012-06-26 20:23:05 +00:00
if ( iType = = OBJECT_MOTHER & & oRad < = 1.2f ) continue ;
if ( iType = = OBJECT_ANT & & oRad < = 1.2f ) continue ;
if ( iType = = OBJECT_SPIDER & & oRad < = 1.2f ) continue ;
if ( iType = = OBJECT_BEE & & oRad < = 1.2f ) continue ;
if ( iType = = OBJECT_WORM & & oRad < = 1.2f ) continue ;
distance = Math : : Distance ( oPos , iPos ) ;
if ( distance < iRad + oRad ) // collision?
{
distance = Math : : Distance ( oPos , iiPos ) ;
if ( distance > = iRad + oRad ) // view (*)
{
m_bCollision = true ;
m_bObstacle = true ;
2016-02-19 16:12:27 +00:00
if ( crashSphere . sound ! = SOUND_NONE )
2012-06-26 20:23:05 +00:00
{
force = fabs ( m_linMotion . realSpeed . x ) ;
2015-07-10 07:26:38 +00:00
force * = crashSphere . hardness * 2.0f ;
2012-06-26 20:23:05 +00:00
if ( ExploOther ( iType , pObj , oType , force ) ) continue ;
colType = ExploHimself ( iType , oType , force ) ;
if ( colType = = 2 ) return 2 ; // destroyed?
if ( colType = = 0 ) continue ; // ignores?
}
force = m_linMotion . realSpeed . Length ( ) ;
2015-07-10 07:26:38 +00:00
force * = crashSphere . hardness ;
2012-06-26 20:23:05 +00:00
volume = fabs ( force * 0.05f ) ;
if ( volume > 1.0f ) volume = 1.0f ;
2016-02-19 16:12:27 +00:00
if ( crashSphere . sound ! = SOUND_NONE )
2012-06-26 20:23:05 +00:00
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( crashSphere . sound , m_object - > GetPosition ( ) , volume ) ;
2012-06-26 20:23:05 +00:00
}
if ( iType = = OBJECT_HUMAN & & volume > 0.5f )
{
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_AIE , m_object - > GetPosition ( ) , volume ) ;
2012-06-26 20:23:05 +00:00
}
if ( m_repeatCollision > 0 )
{
force * = 0.5f * m_repeatCollision ;
if ( force > 20.0f ) force = 20.0f ;
}
m_repeatCollision + = 2 ;
if ( m_repeatCollision > 10 )
{
m_repeatCollision = 10 ;
}
m_linMotion . currentSpeed = Normalize ( iPos - oPos ) * force ;
Math : : LoadRotationXZYMatrix ( matRotate , - angle ) ;
m_linMotion . currentSpeed = Transform ( matRotate , m_linMotion . currentSpeed ) ;
2015-08-12 17:09:35 +00:00
if ( ! m_object - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
m_linMotion . currentSpeed . y = 0.0f ;
}
2015-08-13 08:49:26 +00:00
CPhysics * ph = nullptr ;
if ( pObj - > Implements ( ObjectInterfaceType : : Movable ) )
2020-09-14 19:19:16 +00:00
ph = dynamic_cast < CMovableObject & > ( * pObj ) . GetPhysics ( ) ;
2015-08-13 08:49:26 +00:00
if ( ph ! = nullptr )
2012-06-26 20:23:05 +00:00
{
2015-07-12 09:01:16 +00:00
oAngle = pObj - > GetRotation ( ) ;
2012-06-26 20:23:05 +00:00
oSpeed = Normalize ( oPos - iPos ) * force ;
Math : : LoadRotationXZYMatrix ( matRotate , - oAngle ) ;
oSpeed = Transform ( matRotate , oSpeed ) ;
2015-08-12 17:09:35 +00:00
if ( ! pObj - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
oSpeed . y = 0.0f ;
}
ph - > SetLinMotion ( MO_CURSPEED , oSpeed ) ;
}
return 1 ;
}
}
}
}
if ( m_repeatCollision > 0 )
{
m_repeatCollision - - ;
}
return 0 ;
}
// (*) Collision has the initial position (iiPos) and the new position (iPos),
2012-06-26 21:01:17 +00:00
// the obstacle is not known. We can therefore pass through.
2012-06-26 20:23:05 +00:00
// This is necessary when barriers found "in" a vehicle, not to block it definitely!
// Shakes an object.
2015-07-10 20:11:22 +00:00
bool CPhysics : : JostleObject ( CJostleableObject * pObj , Math : : Vector iPos , float iRad )
2012-06-26 20:23:05 +00:00
{
2015-07-10 20:11:22 +00:00
Math : : Sphere jostlingSphere = pObj - > GetJostlingSphere ( ) ;
2012-06-26 20:23:05 +00:00
2015-07-10 20:11:22 +00:00
float distance = Math : : Distance ( jostlingSphere . pos , iPos ) ;
if ( distance > = iRad + jostlingSphere . radius ) return false ;
2012-06-26 20:23:05 +00:00
2015-07-10 20:11:22 +00:00
float d = ( iRad + jostlingSphere . radius ) / 2.0f ;
float f = ( distance - d ) / d ; // 0 = off, 1 = near
2012-06-26 20:23:05 +00:00
if ( f < 0.0f ) f = 0.0f ;
if ( f > 1.0f ) f = 1.0f ;
2015-07-10 20:11:22 +00:00
Math : : Vector speed = m_linMotion . realSpeed ;
2012-06-26 20:23:05 +00:00
speed . y = 0.0f ;
2015-07-10 20:11:22 +00:00
float force = speed . Length ( ) * f * 0.05f ;
2012-06-26 20:23:05 +00:00
if ( force > 1.0f ) force = 1.0f ;
if ( m_soundTimeJostle > = 0.20f )
{
m_soundTimeJostle = 0.0f ;
m_sound - > Play ( SOUND_JOSTLE , iPos , force ) ;
}
return pObj - > JostleObject ( force ) ;
}
// Shakes forcing an object.
bool CPhysics : : JostleObject ( CObject * pObj , float force )
{
2015-07-10 20:11:22 +00:00
if ( ! pObj - > Implements ( ObjectInterfaceType : : Jostleable ) )
return false ;
2012-06-26 20:23:05 +00:00
2015-07-10 20:11:22 +00:00
CJostleableObject * jostleableObject = dynamic_cast < CJostleableObject * > ( pObj ) ;
2012-06-26 20:23:05 +00:00
if ( m_soundTimeJostle > = 0.20f )
{
m_soundTimeJostle = 0.0f ;
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_JOSTLE , pObj - > GetPosition ( ) , force ) ;
2012-06-26 20:23:05 +00:00
}
2015-07-10 20:11:22 +00:00
return jostleableObject - > JostleObject ( force ) ;
2012-06-26 20:23:05 +00:00
}
// Effects of the explosion on the object buffers.
// Returns true if we ignore this obstacle.
bool CPhysics : : ExploOther ( ObjectType iType ,
CObject * pObj , ObjectType oType , float force )
{
JostleObject ( pObj , 1.0f ) ; // shakes the object
2017-05-23 20:02:00 +00:00
if ( pObj - > Implements ( ObjectInterfaceType : : Damageable ) )
2015-08-13 16:54:44 +00:00
{
// TODO: CFragileObject::GetDestructionForce (I can't do this now because you can't inherit both in COldObject ~krzys_h)
DamageType damageType = DamageType : : Collision ;
2017-05-23 20:02:00 +00:00
float destructionForce = pObj - > Implements ( ObjectInterfaceType : : Fragile ) ? 50.0f : - 1.0f ; // Titanium, PowerCell, NuclearCell, default
2015-08-13 16:54:44 +00:00
if ( pObj - > GetType ( ) = = OBJECT_STONE ) { destructionForce = 25.0f ; } // TitaniumOre
if ( pObj - > GetType ( ) = = OBJECT_URANIUM ) { destructionForce = 25.0f ; } // UraniumOre
2017-05-23 20:02:00 +00:00
if ( pObj - > GetType ( ) = = OBJECT_MOBILEtg ) { destructionForce = 10.0f ; damageType = DamageType : : Explosive ; } // TargetBot (something running into it)
2019-07-17 00:57:47 +00:00
if ( iType = = OBJECT_MOBILEtg ) { destructionForce = 0.0f ; damageType = DamageType : : Explosive ; } // TargetBot (it running into something)
2015-08-13 16:54:44 +00:00
if ( pObj - > GetType ( ) = = OBJECT_TNT ) { destructionForce = 10.0f ; damageType = DamageType : : Explosive ; } // TNT
if ( pObj - > GetType ( ) = = OBJECT_BOMB ) { destructionForce = 0.0f ; damageType = DamageType : : Explosive ; } // Mine
2017-05-23 20:02:00 +00:00
if ( force > destructionForce & & destructionForce > = 0.0f )
2015-08-13 16:54:44 +00:00
{
2017-05-17 16:22:27 +00:00
// TODO: implement "killer"?
2020-09-14 19:19:16 +00:00
dynamic_cast < CDamageableObject & > ( * pObj ) . DamageObject ( damageType ) ;
2015-08-13 16:54:44 +00:00
}
}
if ( force > 25.0f )
{
// TODO: Some function in CShieldedObject. GetCollisionResistance()?
if ( oType = = OBJECT_DERRICK | |
oType = = OBJECT_FACTORY | |
oType = = OBJECT_STATION | |
oType = = OBJECT_CONVERT | |
oType = = OBJECT_REPAIR | |
oType = = OBJECT_DESTROYER | |
oType = = OBJECT_TOWER | |
oType = = OBJECT_RESEARCH | |
oType = = OBJECT_RADAR | |
oType = = OBJECT_INFO | |
oType = = OBJECT_ENERGY | |
oType = = OBJECT_LABO | |
oType = = OBJECT_NUCLEAR | |
oType = = OBJECT_PARA | |
oType = = OBJECT_SAFE | |
oType = = OBJECT_HUSTON ) // building?
{
assert ( pObj - > Implements ( ObjectInterfaceType : : Damageable ) ) ;
2017-05-17 16:22:27 +00:00
// TODO: implement "killer"?
2020-09-14 19:19:16 +00:00
dynamic_cast < CDamageableObject & > ( * pObj ) . DamageObject ( DamageType : : Collision , force / 400.0f ) ;
2015-08-13 16:54:44 +00:00
}
if ( oType = = OBJECT_MOBILEwa | |
oType = = OBJECT_MOBILEta | |
oType = = OBJECT_MOBILEfa | |
oType = = OBJECT_MOBILEia | |
2017-11-16 17:43:45 +00:00
oType = = OBJECT_MOBILEwb | |
oType = = OBJECT_MOBILEtb | |
oType = = OBJECT_MOBILEfb | |
oType = = OBJECT_MOBILEib | |
2015-08-13 16:54:44 +00:00
oType = = OBJECT_MOBILEwc | |
oType = = OBJECT_MOBILEtc | |
oType = = OBJECT_MOBILEfc | |
oType = = OBJECT_MOBILEic | |
oType = = OBJECT_MOBILEwi | |
oType = = OBJECT_MOBILEti | |
oType = = OBJECT_MOBILEfi | |
oType = = OBJECT_MOBILEii | |
oType = = OBJECT_MOBILEws | |
oType = = OBJECT_MOBILEts | |
oType = = OBJECT_MOBILEfs | |
oType = = OBJECT_MOBILEis | |
oType = = OBJECT_MOBILErt | |
oType = = OBJECT_MOBILErc | |
oType = = OBJECT_MOBILErr | |
oType = = OBJECT_MOBILErs | |
oType = = OBJECT_MOBILEsa | |
oType = = OBJECT_MOBILEwt | |
oType = = OBJECT_MOBILEtt | |
oType = = OBJECT_MOBILEft | |
2018-12-23 06:04:06 +00:00
oType = = OBJECT_MOBILEit | |
oType = = OBJECT_MOBILErp | |
oType = = OBJECT_MOBILEst ) // vehicle?
2015-08-13 16:54:44 +00:00
{
assert ( pObj - > Implements ( ObjectInterfaceType : : Damageable ) ) ;
2017-05-17 16:22:27 +00:00
// TODO: implement "killer"?
2020-09-14 19:19:16 +00:00
dynamic_cast < CDamageableObject & > ( * pObj ) . DamageObject ( DamageType : : Collision , force / 200.0f ) ;
2015-08-13 16:54:44 +00:00
}
2012-06-26 20:23:05 +00:00
}
2020-07-13 17:44:50 +00:00
if ( ( oType = = OBJECT_PLANT0 | |
oType = = OBJECT_PLANT1 | |
oType = = OBJECT_PLANT2 | |
oType = = OBJECT_PLANT3 | |
oType = = OBJECT_PLANT4 | |
oType = = OBJECT_PLANT15 | |
oType = = OBJECT_PLANT16 | |
oType = = OBJECT_PLANT17 | |
oType = = OBJECT_PLANT18 ) & &
GetDriveFromObject ( iType ) = = DriveType : : Heavy )
{
dynamic_cast < CDestroyableObject * > ( pObj ) - > DestroyObject ( DestructionType : : Squash ) ;
}
2012-06-26 20:23:05 +00:00
return false ;
}
// Effects of the explosion on the object itself.
// Returns 0 -> mobile object
// Returns 1 -> immobile object
// Returns 2 -> object destroyed
int CPhysics : : ExploHimself ( ObjectType iType , ObjectType oType , float force )
{
2015-08-13 16:54:44 +00:00
if ( ! m_object - > Implements ( ObjectInterfaceType : : Damageable ) ) return 1 ;
2012-06-26 20:23:05 +00:00
2015-08-13 16:54:44 +00:00
// TODO: CExplosiveObject? derrives from CFragileObject
float destructionForce = - 1.0f ; // minimal force required to destroy an object using this explosive, default: not explosive
if ( oType = = OBJECT_TNT ) destructionForce = 10.0f ; // TNT
2017-05-23 20:02:00 +00:00
if ( oType = = OBJECT_MOBILEtg ) destructionForce = 10.0f ; // TargetBot (something running into it)
2019-07-17 00:57:47 +00:00
if ( iType = = OBJECT_MOBILEtg ) destructionForce = 0.0f ; // TargetBot (it running into something)
2015-08-13 16:54:44 +00:00
if ( oType = = OBJECT_BOMB ) destructionForce = 0.0f ; // Mine
2012-06-26 20:23:05 +00:00
2015-08-13 16:54:44 +00:00
if ( force > destructionForce & & destructionForce > = 0.0f )
2012-06-26 20:23:05 +00:00
{
2017-05-17 16:22:27 +00:00
// TODO: implement "killer"?
2020-09-14 19:19:16 +00:00
dynamic_cast < CDamageableObject & > ( * m_object ) . DamageObject ( DamageType : : Explosive ) ;
2012-06-26 20:23:05 +00:00
return 2 ;
}
2015-08-13 16:54:44 +00:00
if ( force > 25.0f )
{
if ( iType = = OBJECT_HUMAN | |
iType = = OBJECT_MOBILEwa | |
iType = = OBJECT_MOBILEta | |
iType = = OBJECT_MOBILEfa | |
iType = = OBJECT_MOBILEia | |
2017-11-16 17:43:45 +00:00
iType = = OBJECT_MOBILEwb | |
iType = = OBJECT_MOBILEtb | |
iType = = OBJECT_MOBILEfb | |
iType = = OBJECT_MOBILEib | |
2015-08-13 16:54:44 +00:00
iType = = OBJECT_MOBILEwc | |
iType = = OBJECT_MOBILEtc | |
iType = = OBJECT_MOBILEfc | |
iType = = OBJECT_MOBILEic | |
iType = = OBJECT_MOBILEwi | |
iType = = OBJECT_MOBILEti | |
iType = = OBJECT_MOBILEfi | |
iType = = OBJECT_MOBILEii | |
iType = = OBJECT_MOBILEws | |
iType = = OBJECT_MOBILEts | |
iType = = OBJECT_MOBILEfs | |
iType = = OBJECT_MOBILEis | |
iType = = OBJECT_MOBILErt | |
iType = = OBJECT_MOBILErc | |
iType = = OBJECT_MOBILErr | |
iType = = OBJECT_MOBILErs | |
iType = = OBJECT_MOBILEsa | |
iType = = OBJECT_MOBILEwt | |
iType = = OBJECT_MOBILEtt | |
iType = = OBJECT_MOBILEft | |
iType = = OBJECT_MOBILEit | |
2018-12-23 06:04:06 +00:00
iType = = OBJECT_MOBILErp | |
iType = = OBJECT_MOBILEst | |
2015-08-13 16:54:44 +00:00
iType = = OBJECT_MOBILEdr | |
iType = = OBJECT_APOLLO2 ) // vehicle?
{
if ( oType = = OBJECT_DERRICK | |
oType = = OBJECT_FACTORY | |
oType = = OBJECT_STATION | |
oType = = OBJECT_CONVERT | |
oType = = OBJECT_REPAIR | |
oType = = OBJECT_DESTROYER | |
oType = = OBJECT_TOWER | |
oType = = OBJECT_RESEARCH | |
oType = = OBJECT_RADAR | |
oType = = OBJECT_INFO | |
oType = = OBJECT_ENERGY | |
oType = = OBJECT_LABO | |
oType = = OBJECT_NUCLEAR | |
oType = = OBJECT_PARA | |
oType = = OBJECT_SAFE | |
oType = = OBJECT_HUSTON ) // building?
{
force / = 200.0f ;
}
else if ( oType = = OBJECT_MOTHER | |
oType = = OBJECT_ANT | |
oType = = OBJECT_SPIDER | |
oType = = OBJECT_BEE | |
oType = = OBJECT_WORM ) // insect?
{
force / = 400.0f ;
}
else
2015-08-18 09:42:55 +00:00
if ( oType = = OBJECT_STONE | |
2015-08-13 16:54:44 +00:00
oType = = OBJECT_METAL )
{
force / = 500.0f ;
}
else
if ( oType = = OBJECT_URANIUM | |
oType = = OBJECT_POWER | |
oType = = OBJECT_ATOMIC )
{
force / = 100.0f ;
}
else
{
force / = 200.0f ;
}
2012-06-26 20:23:05 +00:00
2017-05-17 16:22:27 +00:00
// TODO: implement "killer"?
2020-09-14 19:19:16 +00:00
if ( dynamic_cast < CDamageableObject & > ( * m_object ) . DamageObject ( DamageType : : Collision , force ) ) return 2 ;
2015-08-13 16:54:44 +00:00
}
2012-06-26 20:23:05 +00:00
}
return 1 ;
}
// Makes the particles evolve.
2012-09-10 21:29:38 +00:00
void CPhysics : : FrameParticle ( float aTime , float rTime )
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
m_restBreakParticle - = rTime ;
if ( aTime - m_lastPowerParticle < m_engine - > ParticleAdapt ( 0.05f ) ) return ;
m_lastPowerParticle = aTime ;
2012-06-26 20:23:05 +00:00
2015-08-24 21:19:02 +00:00
float energy = GetObjectEnergyLevel ( m_object ) ;
2012-06-26 20:23:05 +00:00
if ( energy ! = m_lastEnergy ) // change the energy level?
{
if ( energy > m_lastEnergy ) // recharge?
{
2012-09-10 21:29:38 +00:00
PowerParticle ( 1.0f , false ) ;
2012-06-26 20:23:05 +00:00
}
if ( energy = = 0.0f | | m_lastEnergy = = 0.0f )
{
2012-09-10 21:29:38 +00:00
m_restBreakParticle = 2.5f ; // particles for 2.5s
2012-06-26 20:23:05 +00:00
}
m_lastEnergy = energy ;
}
2012-09-10 21:29:38 +00:00
if ( m_restBreakParticle > 0.0f )
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
PowerParticle ( m_restBreakParticle / 2.5f , ( energy = = 0 ) ) ;
2012-06-26 20:23:05 +00:00
}
}
// Generates some particles after a recharge.
2012-09-10 21:29:38 +00:00
void CPhysics : : PowerParticle ( float factor , bool bBreak )
2012-06-26 20:23:05 +00:00
{
Math : : Matrix * mat ;
Math : : Vector pos , ppos , eye , speed ;
Math : : Point dim ;
bool bCarryPower ;
bCarryPower = false ;
2015-07-10 20:13:39 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Carrier ) )
2012-06-26 20:23:05 +00:00
{
2020-09-14 19:19:16 +00:00
CObject * cargo = dynamic_cast < CCarrierObject & > ( * m_object ) . GetCargo ( ) ;
2015-08-18 10:29:41 +00:00
if ( cargo ! = nullptr & & cargo - > Implements ( ObjectInterfaceType : : PowerContainer ) & &
2020-09-14 19:19:16 +00:00
dynamic_cast < CPowerContainerObject & > ( * cargo ) . IsRechargeable ( ) & &
2015-07-14 19:29:13 +00:00
m_object - > GetPartRotationZ ( 1 ) = = ARM_STOCK_ANGLE1 )
2015-07-10 20:13:39 +00:00
{
bCarryPower = true ; // carries a battery
}
2012-06-26 20:23:05 +00:00
}
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
2015-08-17 19:23:07 +00:00
pos = m_object - > GetPowerPosition ( ) ;
2012-06-26 20:23:05 +00:00
pos . x - = 0.3f ;
pos . y + = 1.0f ; // battery center position
pos = Transform ( * mat , pos ) ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 12.0f ;
speed . y = ( Math : : Rand ( ) - 0.5f ) * 12.0f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 12.0f ;
ppos . x = pos . x ;
ppos . y = pos . y + ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
ppos . z = pos . z ;
dim . x = 1.0f * factor ;
dim . y = 1.0f * factor ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( ppos , speed , dim , Gfx : : PARTIBLITZ , 0.5f , 0.0f , 0.0f ) ;
2012-06-26 20:23:05 +00:00
if ( bCarryPower ) // carry a battery?
{
2015-08-24 21:19:02 +00:00
pos = Math : : Vector ( 3.0f , 5.6f , 0.0f ) ; // position of battery holder // TODO: Move to CTransportableObject
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 12.0f ;
speed . y = ( Math : : Rand ( ) - 0.5f ) * 12.0f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 12.0f ;
ppos . x = pos . x ;
ppos . y = pos . y ;
ppos . z = pos . z + ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
dim . x = 1.0f * factor ;
dim . y = 1.0f * factor ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( ppos , speed , dim , Gfx : : PARTIBLITZ , 0.5f , 0.0f , 0.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
// Generates some particles after a fall.
// crash: 0=super soft, 1=big crash
2012-09-10 21:29:38 +00:00
void CPhysics : : CrashParticle ( float crash )
2012-06-26 20:23:05 +00:00
{
Math : : Vector pos , ppos , speed ;
Math : : Point dim ;
2012-09-10 21:29:38 +00:00
float len ;
int i , max ;
2012-06-26 20:23:05 +00:00
if ( crash < 0.2f ) return ;
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-09-10 21:29:38 +00:00
m_camera - > StartEffect ( Gfx : : CAM_EFFECT_CRASH , pos , crash ) ;
2012-06-26 20:23:05 +00:00
//? max = (int)(crash*50.0f);
2012-09-10 21:29:38 +00:00
max = static_cast < int > ( crash * 10.0f * m_engine - > GetParticleDensity ( ) ) ;
2012-06-26 20:23:05 +00:00
for ( i = 0 ; i < max ; i + + )
{
ppos . x = pos . x + ( Math : : Rand ( ) - 0.5f ) * 15.0f * crash ;
ppos . z = pos . z + ( Math : : Rand ( ) - 0.5f ) * 15.0f * crash ;
ppos . y = pos . y + Math : : Rand ( ) * 4.0f ;
len = 1.0f - ( Math : : Distance ( ppos , pos ) / ( 15.0f + 5.0f ) ) ;
if ( len < = 0.0f ) continue ;
speed . x = ( ppos . x - pos . x ) * 0.1f ;
speed . z = ( ppos . z - pos . z ) * 0.1f ;
speed . y = - 2.0f ;
dim . x = 2.0f + crash * 5.0f * len ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( ppos , speed , dim , Gfx : : PARTICRASH , 2.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
// Generates some exhaust gas particle.
2012-09-10 21:29:38 +00:00
void CPhysics : : MotorParticle ( float aTime , float rTime )
2012-06-26 20:23:05 +00:00
{
Math : : Matrix * mat ;
Math : : Vector pos , speed ;
Math : : Point dim ;
ObjectType type ;
Math : : Point c , p ;
float h , a , delay , level ;
int r , i , nb ;
2012-09-10 21:29:38 +00:00
if ( m_object - > GetToy ( ) ) return ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
type = m_object - > GetType ( ) ;
2012-06-26 20:23:05 +00:00
if ( type = = OBJECT_MOBILEia | |
2017-11-16 17:43:45 +00:00
type = = OBJECT_MOBILEib | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEic | |
type = = OBJECT_MOBILEii | |
2017-12-21 00:49:56 +00:00
type = = OBJECT_MOBILEis | |
type = = OBJECT_MOBILEit | | // legs?
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEdr | |
type = = OBJECT_MOTHER | |
type = = OBJECT_ANT | |
type = = OBJECT_SPIDER | |
type = = OBJECT_BEE | |
type = = OBJECT_WORM | |
type = = OBJECT_APOLLO2 ) return ;
if ( type = = OBJECT_HUMAN ) delay = 3.0f ;
else delay = 8.0f ;
if ( m_bSwim & & m_timeUnderWater < delay ) // bubbles when entering water?
{
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastUnderParticle > = m_engine - > ParticleAdapt ( 0.05f ) )
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
m_lastUnderParticle = aTime ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
nb = static_cast < int > ( 20.0f - ( 20.0f / delay ) * m_timeUnderWater ) ;
2012-06-26 20:23:05 +00:00
for ( i = 0 ; i < nb ; i + + )
{
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-06-26 20:23:05 +00:00
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 4.0f ;
pos . y + = ( Math : : Rand ( ) - 0.5f ) * 4.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 4.0f ;
speed . y = ( Math : : Rand ( ) - 0.5f ) * 8.0f + 8.0f ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 0.2f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 0.2f ;
dim . x = 0.06f + Math : : Rand ( ) * 0.10f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIBUBBLE , 3.0f , 0.0f , 0.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
}
2012-09-10 21:29:38 +00:00
level = m_water - > GetLevel ( ) ;
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-06-26 20:23:05 +00:00
if ( type = = OBJECT_HUMAN ) pos . y - = 2.0f ;
if ( pos . y < level ) // underwater?
{
m_absorbWater + = rTime * ( 1.0f / 2.0f ) ; // gets wet
if ( m_absorbWater > 1.0f ) m_absorbWater = 1.0f ;
}
else // out of water?
{
m_absorbWater - = rTime * ( 1.0f / 3.0f ) ; // to dry
if ( m_absorbWater < 0.0f ) m_absorbWater = 0.0f ;
}
if ( pos . y > = level & &
m_absorbWater > 0.0f & &
2012-09-10 21:29:38 +00:00
! m_water - > GetLava ( ) ) // drops on leaving the water?
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastUnderParticle > = m_engine - > ParticleAdapt ( 0.05f ) )
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
m_lastUnderParticle = aTime ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
nb = static_cast < int > ( 8.0f * m_absorbWater ) ;
2012-06-26 20:23:05 +00:00
for ( i = 0 ; i < nb ; i + + )
{
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-06-26 20:23:05 +00:00
if ( type = = OBJECT_HUMAN ) pos . y - = Math : : Rand ( ) * 2.0f ;
else pos . y + = Math : : Rand ( ) * 2.0f ;
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
speed . y = - ( ( Math : : Rand ( ) - 0.5f ) * 8.0f + 8.0f ) ;
speed . x = 0.0f ;
speed . z = 0.0f ;
dim . x = 0.2f ;
dim . y = 0.2f ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIWATER , 2.0f , 0.0f , 1.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
}
if ( type = = OBJECT_HUMAN | | // human?
type = = OBJECT_TECH )
{
if ( m_bLand & &
2012-09-10 21:29:38 +00:00
aTime - m_lastSlideParticle > = m_engine - > ParticleAdapt ( 0.05f ) )
2012-06-26 20:23:05 +00:00
{
h = Math : : Max ( fabs ( m_linMotion . terrainSpeed . x ) ,
fabs ( m_linMotion . terrainSpeed . z ) ) ;
if ( h > m_linMotion . terrainSlide . x + 0.5f & &
m_linMotion . motorSpeed . x = = 0.0f ) // slides a stop?
{
2012-09-10 21:29:38 +00:00
m_lastSlideParticle = aTime ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos . x = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
2012-09-10 21:29:38 +00:00
pos . y = - m_object - > GetCharacter ( ) - > height ;
2012-06-26 20:23:05 +00:00
pos . z = Math : : Rand ( ) * 0.4f + 1.0f ;
if ( rand ( ) % 2 = = 0 ) pos . z = - pos . z ;
pos = Transform ( * mat , pos ) ;
speed = Math : : Vector ( 0.0f , 1.0f , 0.0f ) ;
dim . x = Math : : Rand ( ) * ( h - 5.0f ) / 2.0f + 1.0f ;
if ( dim . x > 2.5f ) dim . x = 2.5f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTICRASH , 2.0f , 0.0f , 0.2f ) ;
2012-06-26 20:23:05 +00:00
}
}
}
if ( type = = OBJECT_MOBILEta | |
2017-11-16 17:43:45 +00:00
type = = OBJECT_MOBILEtb | |
2012-06-26 20:23:05 +00:00
type = = OBJECT_MOBILEtc | |
type = = OBJECT_MOBILEti | |
2017-12-21 00:49:56 +00:00
type = = OBJECT_MOBILEts | |
type = = OBJECT_MOBILEtt ) // caterpillars?
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastSlideParticle > = m_engine - > ParticleAdapt ( 0.05f ) )
2012-06-26 20:23:05 +00:00
{
h = fabs ( m_linMotion . motorSpeed . x - m_linMotion . realSpeed . x ) ;
if ( h > 5.0f )
{
2012-09-10 21:29:38 +00:00
m_lastSlideParticle = aTime ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos . x = ( Math : : Rand ( ) - 0.5f ) * 8.0f ;
pos . y = 0.0f ;
pos . z = Math : : Rand ( ) * 2.0f + 3.0f ;
if ( rand ( ) % 2 = = 0 ) pos . z = - pos . z ;
pos = Transform ( * mat , pos ) ;
speed = Math : : Vector ( 0.0f , 0.0f , 0.0f ) ;
dim . x = Math : : Rand ( ) * ( h - 5.0f ) / 2.0f + 1.0f ;
if ( dim . x > 3.0f ) dim . x = 3.0f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTICRASH , 2.0f , 0.0f , 0.2f ) ;
2012-06-26 20:23:05 +00:00
}
}
}
if ( type = = OBJECT_MOBILErt | |
type = = OBJECT_MOBILErc | |
type = = OBJECT_MOBILErr | |
2018-12-23 06:04:06 +00:00
type = = OBJECT_MOBILErs | |
type = = OBJECT_MOBILErp ) // large caterpillars?
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastSlideParticle > = m_engine - > ParticleAdapt ( 0.05f ) )
2012-06-26 20:23:05 +00:00
{
h = fabs ( m_linMotion . motorSpeed . x - m_linMotion . realSpeed . x ) ;
if ( h > 5.0f )
{
2012-09-10 21:29:38 +00:00
m_lastSlideParticle = aTime ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos . x = ( Math : : Rand ( ) - 0.5f ) * 9.0f ;
pos . y = 0.0f ;
pos . z = Math : : Rand ( ) * 3.0f + 3.0f ;
if ( rand ( ) % 2 = = 0 ) pos . z = - pos . z ;
pos = Transform ( * mat , pos ) ;
speed = Math : : Vector ( 0.0f , 0.0f , 0.0f ) ;
dim . x = Math : : Rand ( ) * ( h - 5.0f ) / 2.0f + 1.0f ;
if ( dim . x > 3.0f ) dim . x = 3.0f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTICRASH , 2.0f , 0.0f , 0.2f ) ;
2012-06-26 20:23:05 +00:00
}
}
}
if ( ( type = = OBJECT_HUMAN | | type = = OBJECT_TECH ) & & ! m_bSwim )
{
if ( m_bLand ) // on the ground?
{
if ( m_reactorTemperature > 0.0f )
{
m_reactorTemperature - = rTime * ( 1.0f / 10.0f ) ; // cooling
if ( m_reactorTemperature < 0.0f )
{
m_reactorTemperature = 0.0f ;
}
}
if ( m_reactorTemperature = = 0.0f | |
2012-09-10 21:29:38 +00:00
aTime - m_lastMotorParticle < m_engine - > ParticleAdapt ( 0.05f ) ) return ;
m_lastMotorParticle = aTime ;
2012-06-26 20:23:05 +00:00
pos = Math : : Vector ( - 1.6f , - 0.5f , 0.0f ) ;
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 0.6f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 0.6f ;
speed . y = - ( 0.5f + Math : : Rand ( ) * 0.3f ) * ( 1.0f - m_reactorTemperature ) ;
dim . x = ( 1.0f + Math : : Rand ( ) * 0.5f ) * ( 0.2f + m_reactorTemperature * 0.8f ) ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTISMOKE2 , 3.0f , 0.0f , 0.1f ) ;
2012-06-26 20:23:05 +00:00
}
else // in flight?
{
2020-09-14 19:19:16 +00:00
if ( ! m_bMotor | | ( m_object - > Implements ( ObjectInterfaceType : : JetFlying ) & & dynamic_cast < CJetFlyingObject & > ( * m_object ) . GetReactorRange ( ) = = 0.0f ) ) return ;
2012-06-26 20:23:05 +00:00
if ( m_reactorTemperature < 1.0f ) // not too hot?
{
m_reactorTemperature + = rTime * ( 1.0f / 4.0f ) ; // heating
if ( m_reactorTemperature > 1.0f )
{
m_reactorTemperature = 1.0f ; // but not too much
}
}
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastMotorParticle < m_engine - > ParticleAdapt ( 0.02f ) ) return ;
m_lastMotorParticle = aTime ;
2012-06-26 20:23:05 +00:00
pos = Math : : Vector ( - 1.6f , - 1.0f , 0.0f ) ;
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 3.0f ;
pos . y + = ( Math : : Rand ( ) - 0.5f ) * 1.5f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 3.0f ;
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
h = m_floorHeight ;
if ( h > 10.0f ) // high enough?
{
speed = Math : : Vector ( 0.0f , - 10.0f , 0.0f ) ; // against the bottom
}
else
{
speed . y = 10.0f - 2.0f * h - Math : : Rand ( ) * ( 10.0f - h ) ; //against the top
speed . x = ( Math : : Rand ( ) - 0.5f ) * ( 5.0f - h ) * 1.0f ; // horizontal (xz)
speed . z = ( Math : : Rand ( ) - 0.5f ) * ( 5.0f - h ) * 1.0f ;
}
dim . x = 0.12f ;
dim . y = 0.12f ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTISCRAPS , 2.0f , 10.0f ) ;
2012-06-26 20:23:05 +00:00
pos = Math : : Vector ( - 1.6f , - 0.5f , 0.0f ) ;
pos = Transform ( * mat , pos ) ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
speed . y = - ( 4.0f + Math : : Rand ( ) * 3.0f ) ;
speed . x + = m_linMotion . realSpeed . x * 0.8f ;
speed . z - = m_linMotion . realSpeed . x * m_cirMotion . realSpeed . y * 0.05f ;
if ( m_linMotion . realSpeed . y > 0.0f )
{
speed . y + = m_linMotion . realSpeed . y * 0.5f ;
}
else
{
speed . y + = m_linMotion . realSpeed . y * 1.2f ;
}
2015-07-14 19:29:13 +00:00
a = m_object - > GetRotationY ( ) ;
2012-06-26 20:23:05 +00:00
p . x = speed . x ;
p . y = speed . z ;
p = Math : : RotatePoint ( - a , p ) ;
speed . x = p . x ;
speed . z = p . y ;
dim . x = 0.4f + Math : : Rand ( ) * 0.2f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIEJECT , 0.3f , 10.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
if ( ( type = = OBJECT_HUMAN | | type = = OBJECT_TECH ) & & m_bSwim )
{
m_reactorTemperature = 0.0f ; // reactor cold
}
2015-08-12 17:09:35 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Flying ) & &
2012-06-26 20:23:05 +00:00
type ! = OBJECT_HUMAN & &
type ! = OBJECT_TECH & &
! m_bSwim )
{
if ( m_bLand ) // on the ground?
{
if ( m_motorSpeed . x = = 0.0f & & // glide slope due to ground?
m_cirMotion . realSpeed . y = = 0.0f )
{
h = Math : : Max ( fabs ( m_linMotion . realSpeed . x ) ,
fabs ( m_linMotion . realSpeed . z ) ) ;
if ( h < 3.0f ) return ;
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastMotorParticle < m_engine - > ParticleAdapt ( 0.2f ) ) return ;
m_lastMotorParticle = aTime ;
2012-06-26 20:23:05 +00:00
r = rand ( ) % 3 ;
if ( r = = 0 ) pos = Math : : Vector ( - 3.0f , 0.0f , - 4.0f ) ;
if ( r = = 1 ) pos = Math : : Vector ( - 3.0f , 0.0f , 4.0f ) ;
if ( r = = 2 ) pos = Math : : Vector ( 4.0f , 0.0f , 0.0f ) ;
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
speed = Math : : Vector ( 0.0f , 0.0f , 0.0f ) ;
dim . x = Math : : Rand ( ) * h / 5.0f + 2.0f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTICRASH , 2.0f ) ;
2012-06-26 20:23:05 +00:00
}
else // glide with small reactors in skates?
{
if ( m_linMotion . realSpeed . x = = 0.0f & &
m_cirMotion . realSpeed . y = = 0.0f ) return ;
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastMotorParticle < m_engine - > ParticleAdapt ( 0.02f ) ) return ;
m_lastMotorParticle = aTime ;
2012-06-26 20:23:05 +00:00
r = rand ( ) % 3 ;
if ( r = = 0 ) pos = Math : : Vector ( - 3.0f , 0.0f , - 4.0f ) ;
if ( r = = 1 ) pos = Math : : Vector ( - 3.0f , 0.0f , 4.0f ) ;
if ( r = = 2 ) pos = Math : : Vector ( 4.0f , 0.0f , 0.0f ) ;
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
speed = Math : : Vector ( 0.0f , 0.0f , 0.0f ) ;
dim . x = 1.0f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIEJECT ) ;
2012-06-26 20:23:05 +00:00
}
}
else // in flight?
{
2020-09-14 19:19:16 +00:00
if ( ! m_bMotor | | ( m_object - > Implements ( ObjectInterfaceType : : JetFlying ) & & dynamic_cast < CJetFlyingObject & > ( * m_object ) . GetReactorRange ( ) = = 0.0f ) ) return ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastMotorParticle < m_engine - > ParticleAdapt ( 0.02f ) ) return ;
m_lastMotorParticle = aTime ;
2012-06-26 20:23:05 +00:00
pos = Math : : Vector ( 0.0f , - 1.0f , 0.0f ) ;
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 6.0f ;
pos . y + = ( Math : : Rand ( ) - 0.5f ) * 3.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 6.0f ;
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
h = m_floorHeight ;
if ( h > 10.0f ) // high enough?
{
speed = Math : : Vector ( 0.0f , - 10.0f , 0.0f ) ; // against the bottom
}
else
{
speed . y = 10.0f - 2.0f * h - Math : : Rand ( ) * ( 10.0f - h ) ; // against the top
speed . x = ( Math : : Rand ( ) - 0.5f ) * ( 10.0f - h ) * 2.0f ; // horizontal (xz)
speed . z = ( Math : : Rand ( ) - 0.5f ) * ( 10.0f - h ) * 2.0f ;
}
dim . x = 0.2f ;
dim . y = 0.2f ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTISCRAPS , 2.0f , 10.0f ) ;
2012-06-26 20:23:05 +00:00
pos = Math : : Vector ( 0.0f , 1.0f , 0.0f ) ;
pos = Transform ( * mat , pos ) ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
speed . y = - ( 6.0f + Math : : Rand ( ) * 4.5f ) ;
speed . x + = m_linMotion . realSpeed . x * 0.8f ;
speed . z - = m_linMotion . realSpeed . x * m_cirMotion . realSpeed . y * 0.05f ;
if ( m_linMotion . realSpeed . y > 0.0f )
{
speed . y + = m_linMotion . realSpeed . y * 0.5f ;
}
else
{
speed . y + = m_linMotion . realSpeed . y * 1.2f ;
}
2015-07-14 19:29:13 +00:00
a = m_object - > GetRotationY ( ) ;
2012-06-26 20:23:05 +00:00
p . x = speed . x ;
p . y = speed . z ;
p = Math : : RotatePoint ( - a , p ) ;
speed . x = p . x ;
speed . z = p . y ;
dim . x = 0.7f + Math : : Rand ( ) * 0.6f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIEJECT , 0.5f , 10.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
if ( ( type = = OBJECT_HUMAN | | type = = OBJECT_TECH ) & & m_bSwim )
{
2020-09-14 19:19:16 +00:00
if ( ! m_object - > Implements ( ObjectInterfaceType : : Destroyable ) | | dynamic_cast < CDestroyableObject & > ( * m_object ) . GetDying ( ) ! = DeathType : : Dead )
2012-06-26 20:23:05 +00:00
{
h = Math : : Mod ( aTime , 5.0f ) ;
if ( h < 3.5f & & ( h < 1.5f | | h > 1.6f ) ) return ;
}
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastMotorParticle < m_engine - > ParticleAdapt ( 0.06f ) ) return ;
m_lastMotorParticle = aTime ;
2012-06-26 20:23:05 +00:00
pos = Math : : Vector ( 0.0f , 3.0f , 0.0f ) ;
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
speed . y = ( Math : : Rand ( ) - 0.5f ) * 8.0f + 8.0f ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 0.2f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 0.2f ;
dim . x = 0.2f ;
dim . y = 0.2f ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIBUBBLE , 3.0f , 0.0f , 0.0f ) ;
2012-06-26 20:23:05 +00:00
if ( aTime - m_lastSoundWater > 1.5f )
{
m_lastSoundWater = aTime ;
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_BLUP , m_object - > GetPosition ( ) , 0.5f + Math : : Rand ( ) * 0.5f ) ;
2012-06-26 20:23:05 +00:00
}
}
2018-12-23 06:04:06 +00:00
if ( ( type = = OBJECT_MOBILEsa | | type = = OBJECT_MOBILEst ) & & m_bSwim )
2012-06-26 20:23:05 +00:00
{
h = Math : : Mod ( aTime , 3.0f ) ;
if ( h < 1.5f & & ( h < 0.5f | | h > 0.9f ) ) return ;
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastMotorParticle < m_engine - > ParticleAdapt ( 0.06f ) ) return ;
m_lastMotorParticle = aTime ;
2012-06-26 20:23:05 +00:00
pos = Math : : Vector ( 0.0f , 3.0f , 0.0f ) ;
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
speed . y = ( Math : : Rand ( ) - 0.5f ) * 8.0f + 8.0f ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 0.2f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 0.2f ;
dim . x = 0.2f ;
dim . y = 0.2f ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIBUBBLE , 3.0f , 0.0f , 0.0f ) ;
2012-06-26 20:23:05 +00:00
if ( aTime - m_lastSoundWater > 1.5f )
{
m_lastSoundWater = aTime ;
2015-07-12 09:01:16 +00:00
m_sound - > Play ( SOUND_BLUP , m_object - > GetPosition ( ) , 0.5f + Math : : Rand ( ) * 0.5f ) ;
2012-06-26 20:23:05 +00:00
}
}
2015-08-12 17:09:35 +00:00
if ( ! m_object - > Implements ( ObjectInterfaceType : : Flying ) )
2012-06-26 20:23:05 +00:00
{
if ( type = = OBJECT_APOLLO2 ) return ; // electric motors!
2015-08-12 17:09:35 +00:00
// Create engine smoke
2012-06-26 20:23:05 +00:00
if ( type = = OBJECT_MOBILErt | |
type = = OBJECT_MOBILErc | |
type = = OBJECT_MOBILErr | |
2018-12-23 06:04:06 +00:00
type = = OBJECT_MOBILErs | |
type = = OBJECT_MOBILErp )
2012-06-26 20:23:05 +00:00
{
if ( ! m_bMotor ) return ;
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastMotorParticle < m_engine - > ParticleAdapt ( 0.1f ) ) return ;
m_lastMotorParticle = aTime ;
2012-06-26 20:23:05 +00:00
pos = Math : : Vector ( - 2.5f , 10.3f , - 1.3f ) ;
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 1.0f ;
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 2.0f ;
speed . y = 1.5f + Math : : Rand ( ) * 1.0f ;
dim . x = Math : : Rand ( ) * 0.6f + 0.4f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIMOTOR , 2.0f ) ;
2012-06-26 20:23:05 +00:00
}
else
{
if ( ! m_bMotor ) return ;
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastMotorParticle < m_engine - > ParticleAdapt ( 0.05f ) ) return ;
m_lastMotorParticle = aTime ;
2012-06-26 20:23:05 +00:00
pos = Math : : Vector ( - 3.4f , 1.8f , 0.5f ) ;
speed = pos ;
if ( m_linMotion . currentSpeed . x < 0.0f )
{
speed . x + = m_linMotion . currentSpeed . x * 1.2f ;
}
else if ( m_linMotion . currentSpeed . x > 0.0f )
{
speed . x + = 0.0f ;
}
else
{
speed . x - = 3.0f ;
}
speed . y - = 0.5f + Math : : Rand ( ) * 2.0f ;
speed . z + = ( Math : : Rand ( ) - 0.5f ) * 3.0f ;
2012-06-26 21:01:17 +00:00
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
pos = Transform ( * mat , pos ) ;
speed = Transform ( * mat , speed ) - pos ;
dim . x = Math : : Rand ( ) * 0.4f + 0.3f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIMOTOR , 2.0f ) ;
2012-06-26 20:23:05 +00:00
}
}
}
// Generates some particles after falling into the water.
2012-09-10 21:29:38 +00:00
void CPhysics : : WaterParticle ( float aTime , Math : : Vector pos , ObjectType type ,
2012-06-26 20:23:05 +00:00
float floor , float advance , float turn )
{
Math : : Vector ppos , speed ;
Math : : Point dim ;
float delay , level , min , max , force , volume , diam ;
int i , nb ;
2012-09-10 21:29:38 +00:00
level = m_water - > GetLevel ( ) ;
2012-06-26 20:23:05 +00:00
if ( floor > = level ) return ;
if ( type = = OBJECT_HUMAN | |
type = = OBJECT_TECH )
{
min = 3.0f ;
max = 3.0f ;
}
else
{
min = 0.0f ;
max = 9.0f ;
}
if ( pos . y + max < level | | pos . y - min > level ) return ;
// Management of the particle "splash".
if ( m_linMotion . realSpeed . y < - 10.0f & &
2012-09-10 21:29:38 +00:00
aTime - m_lastPloufParticle > = 1.0f )
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
m_lastPloufParticle = aTime ;
2012-06-26 20:23:05 +00:00
force = - m_linMotion . realSpeed . y / 20.0f ; // power according to speed drops
if ( type = = OBJECT_HUMAN | |
type = = OBJECT_TECH )
{
diam = 2.5f ;
}
else
{
diam = 5.0f ;
force * = 1.3f ; // a robot is heavier
}
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-09-10 21:29:38 +00:00
pos . y = m_water - > GetLevel ( ) - 1.0f ;
2012-06-26 20:23:05 +00:00
dim . x = 2.0f * force ; // height
dim . y = diam ; // diameter
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , Math : : Vector ( 0.0f , 0.0f , 0.0f ) , dim , Gfx : : PARTIPLOUF0 , 1.4f , 0.0f , 0.0f ) ;
2012-06-26 20:23:05 +00:00
force = ( 0.5f + force * 0.5f ) ;
2012-09-10 21:29:38 +00:00
nb = static_cast < int > ( force * 50.0f * m_engine - > GetParticleDensity ( ) ) ;
2012-06-26 20:23:05 +00:00
for ( i = 0 ; i < nb ; i + + )
{
ppos = pos ;
ppos . x + = ( Math : : Rand ( ) - 0.5f ) * 4.0f ;
ppos . z + = ( Math : : Rand ( ) - 0.5f ) * 4.0f ;
ppos . y + = 0.6f ;
speed . x = ( Math : : Rand ( ) - 0.5f ) * 12.0f * force ;
speed . z = ( Math : : Rand ( ) - 0.5f ) * 12.0f * force ;
speed . y = 6.0f + Math : : Rand ( ) * 6.0f * force ;
dim . x = 0.5f ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( ppos , speed , dim , Gfx : : PARTIDROP , 2.0f , 20.0f , 0.2f ) ;
2012-06-26 20:23:05 +00:00
}
volume = fabs ( m_linMotion . realSpeed . y * 0.02f ) ;
if ( volume > 1.0f ) volume = 1.0f ;
m_sound - > Play ( SOUND_PLOUF , pos , volume ) ;
}
// Management particles "cop".
2012-09-10 21:29:38 +00:00
if ( m_water - > GetLava ( ) ) return ;
2012-06-26 20:23:05 +00:00
if ( advance = = 0.0f & & turn = = 0.0f )
{
turn = 10.0f ;
delay = 0.50f ;
}
else if ( advance = = 0.0f )
{
delay = 0.24f ;
}
else
{
delay = 0.06f ;
}
2012-09-10 21:29:38 +00:00
m_engine - > ParticleAdapt ( delay ) ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
if ( aTime - m_lastWaterParticle < delay ) return ;
m_lastWaterParticle = aTime ;
2012-06-26 20:23:05 +00:00
force = ( advance + turn ) * 0.16f ;
if ( force < 0.001f ) return ;
2015-07-12 09:01:16 +00:00
pos = m_object - > GetPosition ( ) ;
2012-06-26 20:23:05 +00:00
pos . y = level + 0.1f ;
if ( advance = = 0 )
{
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 10.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 10.0f ;
}
else
{
pos . x + = ( Math : : Rand ( ) - 0.5f ) * 4.0f ;
pos . z + = ( Math : : Rand ( ) - 0.5f ) * 4.0f ;
}
speed . y = 0.0f ;
speed . x = 0.0f ;
speed . z = 0.0f ;
dim . x = Math : : Min ( Math : : Rand ( ) * force + force + 1.0f , 10.0f ) ;
dim . y = dim . x ;
2012-09-10 21:29:38 +00:00
m_particle - > CreateParticle ( pos , speed , dim , Gfx : : PARTIFLIC , 3.0f , 0.0f , 0.0f ) ;
2012-06-26 20:23:05 +00:00
}
// Creates the trace under the robot.
2015-07-14 11:42:47 +00:00
void CPhysics : : WheelParticle ( TraceColor color , float width )
2012-06-26 20:23:05 +00:00
{
Math : : Matrix * mat ;
Math : : Vector goal1 , goal2 , wheel1 , wheel2 ;
2012-09-10 21:29:38 +00:00
float dist1 , dist2 , step ;
2012-06-26 20:23:05 +00:00
2012-09-10 21:29:38 +00:00
mat = m_object - > GetWorldMatrix ( 0 ) ;
2012-06-26 20:23:05 +00:00
// Draw a trace on the ground.
2015-07-14 11:42:47 +00:00
if ( color ! = TraceColor : : Default )
2012-06-26 20:23:05 +00:00
{
step = 2.0f ;
2015-08-09 20:46:05 +00:00
if ( color = = TraceColor : : BlackArrow | |
color = = TraceColor : : RedArrow )
{
step = 4.0f ; // arrow?
}
2012-09-10 21:29:38 +00:00
step / = m_engine - > GetTracePrecision ( ) ;
2012-06-26 20:23:05 +00:00
goal1 . x = step / 2.0f ;
goal1 . y = 0.0f ;
goal1 . z = - width / 2.0f ;
goal1 = Transform ( * mat , goal1 ) ;
goal2 . x = step / 2.0f ;
goal2 . y = 0.0f ;
goal2 . z = width / 2.0f ;
goal2 = Transform ( * mat , goal2 ) ;
2012-09-10 21:29:38 +00:00
if ( ! m_bWheelParticleBrake )
2012-06-26 20:23:05 +00:00
{
2012-09-10 21:29:38 +00:00
m_wheelParticlePos [ 0 ] = goal1 ;
m_wheelParticlePos [ 1 ] = goal2 ;
2012-06-26 20:23:05 +00:00
}
while ( true )
{
2012-09-10 21:29:38 +00:00
dist1 = Math : : Distance ( m_wheelParticlePos [ 0 ] , goal1 ) ;
2012-06-26 20:23:05 +00:00
if ( dist1 < step ) break ;
2015-05-06 19:59:29 +00:00
2012-09-10 21:29:38 +00:00
dist2 = Math : : Distance ( m_wheelParticlePos [ 1 ] , goal2 ) ;
2015-05-06 19:59:29 +00:00
2012-09-10 21:29:38 +00:00
wheel1 = Math : : SegmentPoint ( m_wheelParticlePos [ 0 ] , goal1 , step ) ;
2015-05-06 19:59:29 +00:00
wheel2 = Math : : SegmentPoint ( m_wheelParticlePos [ 1 ] , goal2 , step * dist2 / dist1 ) ;
2012-06-26 20:23:05 +00:00
if ( m_linMotion . realSpeed . x > = 0.0f )
{
2015-08-18 20:09:33 +00:00
m_particle - > CreateWheelTrace ( m_wheelParticlePos [ 0 ] , m_wheelParticlePos [ 1 ] , wheel1 , wheel2 , color ) ;
2012-06-26 20:23:05 +00:00
}
else
{
2015-08-18 20:09:33 +00:00
m_particle - > CreateWheelTrace ( m_wheelParticlePos [ 1 ] , m_wheelParticlePos [ 0 ] , wheel2 , wheel1 , color ) ;
2012-06-26 20:23:05 +00:00
}
2015-05-06 19:59:29 +00:00
2012-09-10 21:29:38 +00:00
m_wheelParticlePos [ 0 ] = wheel1 ;
m_wheelParticlePos [ 1 ] = wheel2 ;
2012-06-26 20:23:05 +00:00
}
2012-09-10 21:29:38 +00:00
m_bWheelParticleBrake = true ;
2012-06-26 20:23:05 +00:00
}
else
{
2012-09-10 21:29:38 +00:00
m_bWheelParticleBrake = false ;
2012-06-26 20:23:05 +00:00
}
}
// Returns an error related to the general state.
2012-09-10 21:29:38 +00:00
Error CPhysics : : GetError ( )
2012-06-26 20:23:05 +00:00
{
2015-07-10 21:47:59 +00:00
ObjectType type = m_object - > GetType ( ) ;
2012-06-26 20:23:05 +00:00
if ( type = = OBJECT_HUMAN | |
type = = OBJECT_TECH | |
type = = OBJECT_MOTHER | |
type = = OBJECT_ANT | |
type = = OBJECT_SPIDER | |
type = = OBJECT_BEE | |
type = = OBJECT_WORM | |
type = = OBJECT_APOLLO2 | |
type = = OBJECT_MOBILEdr ) return ERR_OK ;
2012-06-26 21:01:17 +00:00
2015-08-15 19:29:08 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : ProgramStorage ) )
2012-06-26 20:23:05 +00:00
{
2020-09-14 19:19:16 +00:00
if ( dynamic_cast < CProgramStorageObject & > ( * m_object ) . GetActiveVirus ( ) )
2015-08-10 11:46:39 +00:00
{
return ERR_VEH_VIRUS ;
}
2012-06-26 20:23:05 +00:00
}
2015-07-10 21:47:59 +00:00
if ( m_object - > Implements ( ObjectInterfaceType : : Powered ) )
2012-06-26 20:23:05 +00:00
{
2020-09-14 19:19:16 +00:00
CObject * power = dynamic_cast < CPoweredObject & > ( * m_object ) . GetPower ( ) ; // searches for the object battery used
2015-08-11 20:51:09 +00:00
if ( power = = nullptr | | ! power - > Implements ( ObjectInterfaceType : : PowerContainer ) )
2015-07-10 21:47:59 +00:00
{
return ERR_VEH_POWER ;
}
else
{
2020-09-14 19:19:16 +00:00
if ( dynamic_cast < CPowerContainerObject & > ( * power ) . GetEnergy ( ) = = 0.0f ) return ERR_VEH_ENERGY ;
2015-07-10 21:47:59 +00:00
}
2012-06-26 20:23:05 +00:00
}
return ERR_OK ;
}
2014-03-09 13:36:39 +00:00
void CPhysics : : SetFalling ( )
{
if ( m_fallingHeight = = 0.0f & & m_floorHeight > = m_minFallingHeight )
2015-07-12 09:01:16 +00:00
m_fallingHeight = m_object - > GetPosition ( ) . y ;
2014-03-09 13:36:39 +00:00
}
float CPhysics : : GetFallingHeight ( )
{
return m_fallingHeight ;
}
void CPhysics : : SetMinFallingHeight ( float value )
{
if ( value < 0.0f ) return ;
m_minFallingHeight = value ;
}
float CPhysics : : GetMinFallingHeight ( )
{
return m_minFallingHeight ;
}
void CPhysics : : SetFallDamageFraction ( float value )
{
if ( value < 0.0f ) return ;
m_fallDamageFraction = value ;
}
float CPhysics : : GetFallDamageFraction ( )
{
return m_fallDamageFraction ;
}