📄 vehicle.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "game/vehicles/vehicle.h"
#include "platform/platform.h"
#include "dgl/dgl.h"
#include "game/game.h"
#include "math/mMath.h"
#include "console/simBase.h"
#include "console/console.h"
#include "console/consoleTypes.h"
#include "collision/clippedPolyList.h"
#include "collision/planeExtractor.h"
#include "game/moveManager.h"
#include "core/bitStream.h"
#include "core/dnet.h"
#include "game/gameConnection.h"
#include "ts/tsShapeInstance.h"
#include "game/fx/particleEngine.h"
#include "audio/audioDataBlock.h"
#include "math/mathIO.h"
#include "sceneGraph/sceneState.h"
#include "terrain/terrData.h"
#include "dgl/materialPropertyMap.h"
#include "game/trigger.h"
#include "game/item.h"
//----------------------------------------------------------------------------
namespace {
const U32 sMoveRetryCount = 3;
// Client prediction
const S32 sMaxWarpTicks = 3; // Max warp duration in ticks
const S32 sMaxPredictionTicks = 30; // Number of ticks to predict
const F32 sVehicleGravity = -20;
// Physics and collision constants
static F32 sRestTol = 0.5; // % of gravity energy to be at rest
static int sRestCount = 10; // Consecutive ticks before comming to rest
} // namespace {}
// Trigger objects that are not normally collided with.
static U32 sTriggerMask = ItemObjectType |
TriggerObjectType |
CorpseObjectType;
IMPLEMENT_CONOBJECT(VehicleData);
//----------------------------------------------------------------------------
VehicleData::VehicleData()
{
body.friction = 0;
body.restitution = 1;
minImpactSpeed = 25;
softImpactSpeed = 25;
hardImpactSpeed = 50;
minRollSpeed = 0;
maxSteeringAngle = 0.785; // 45 deg.
cameraRoll = true;
cameraLag = 0;
cameraDecay = 0;
cameraOffset = 0;
minDrag = 0;
maxDrag = 0;
integration = 1;
collisionTol = 0.1;
contactTol = 0.1;
massCenter.set(0,0,0);
massBox.set(0,0,0);
drag = 0.7;
density = 4;
jetForce = 500;
jetEnergyDrain = 0.8;
minJetEnergy = 1;
for (S32 i = 0; i < Body::MaxSounds; i++)
body.sound[i] = 0;
dustEmitter = NULL;
dustID = 0;
triggerDustHeight = 3.0;
dustHeight = 1.0;
dMemset( damageEmitterList, 0, sizeof( damageEmitterList ) );
dMemset( damageEmitterIDList, 0, sizeof( damageEmitterIDList ) );
dMemset( damageLevelTolerance, 0, sizeof( damageLevelTolerance ) );
dMemset( splashEmitterList, 0, sizeof( splashEmitterList ) );
dMemset( splashEmitterIDList, 0, sizeof( splashEmitterIDList ) );
numDmgEmitterAreas = 0;
splashFreqMod = 300.0;
splashVelEpsilon = 0.50;
exitSplashSoundVel = 2.0;
softSplashSoundVel = 1.0;
medSplashSoundVel = 2.0;
hardSplashSoundVel = 3.0;
genericShadowLevel = Vehicle_GenericShadowLevel;
noShadowLevel = Vehicle_NoShadowLevel;
dMemset(waterSound, 0, sizeof(waterSound));
collDamageThresholdVel = 20;
collDamageMultiplier = 0.05;
}
//----------------------------------------------------------------------------
bool VehicleData::preload(bool server, char errorBuffer[256])
{
if (!Parent::preload(server, errorBuffer))
return false;
// Resolve objects transmitted from server
if (!server) {
for (S32 i = 0; i < Body::MaxSounds; i++)
if (body.sound[i])
Sim::findObject(SimObjectId(body.sound[i]),body.sound[i]);
}
if( !dustEmitter && dustID != 0 )
{
if( !Sim::findObject( dustID, dustEmitter ) )
{
Con::errorf( ConsoleLogEntry::General, "VehicleData::preload Invalid packet, bad datablockId(dustEmitter): 0x%x", dustID );
}
}
U32 i;
for( i=0; i<VC_NUM_DAMAGE_EMITTERS; i++ )
{
if( !damageEmitterList[i] && damageEmitterIDList[i] != 0 )
{
if( !Sim::findObject( damageEmitterIDList[i], damageEmitterList[i] ) )
{
Con::errorf( ConsoleLogEntry::General, "VehicleData::preload Invalid packet, bad datablockId(damageEmitter): 0x%x", damageEmitterIDList[i] );
}
}
}
for( i=0; i<VC_NUM_SPLASH_EMITTERS; i++ )
{
if( !splashEmitterList[i] && splashEmitterIDList[i] != 0 )
{
if( !Sim::findObject( splashEmitterIDList[i], splashEmitterList[i] ) )
{
Con::errorf( ConsoleLogEntry::General, "VehicleData::preload Invalid packet, bad datablockId(splashEmitter): 0x%x", splashEmitterIDList[i] );
}
}
}
return true;
}
//----------------------------------------------------------------------------
void VehicleData::packData(BitStream* stream)
{
S32 i;
Parent::packData(stream);
stream->write(body.restitution);
stream->write(body.friction);
for (i = 0; i < Body::MaxSounds; i++)
if (stream->writeFlag(body.sound[i]))
stream->writeRangedU32(packed? SimObjectId(body.sound[i]):
body.sound[i]->getId(),DataBlockObjectIdFirst,
DataBlockObjectIdLast);
stream->write(minImpactSpeed);
stream->write(softImpactSpeed);
stream->write(hardImpactSpeed);
stream->write(minRollSpeed);
stream->write(maxSteeringAngle);
stream->write(maxDrag);
stream->write(minDrag);
stream->write(integration);
stream->write(collisionTol);
stream->write(contactTol);
mathWrite(*stream,massCenter);
mathWrite(*stream,massBox);
stream->write(jetForce);
stream->write(jetEnergyDrain);
stream->write(minJetEnergy);
stream->writeFlag(cameraRoll);
stream->write(cameraLag);
stream->write(cameraDecay);
stream->write(cameraOffset);
stream->write( triggerDustHeight );
stream->write( dustHeight );
stream->write( numDmgEmitterAreas );
stream->write(exitSplashSoundVel);
stream->write(softSplashSoundVel);
stream->write(medSplashSoundVel);
stream->write(hardSplashSoundVel);
// write the water sound profiles
for(i = 0; i < MaxSounds; i++)
if(stream->writeFlag(waterSound[i]))
stream->writeRangedU32(waterSound[i]->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast);
if (stream->writeFlag( dustEmitter ))
{
stream->writeRangedU32( dustEmitter->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast );
}
for (i = 0; i < VC_NUM_DAMAGE_EMITTERS; i++)
{
if( stream->writeFlag( damageEmitterList[i] != NULL ) )
{
stream->writeRangedU32( damageEmitterList[i]->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast );
}
}
for (i = 0; i < VC_NUM_SPLASH_EMITTERS; i++)
{
if( stream->writeFlag( splashEmitterList[i] != NULL ) )
{
stream->writeRangedU32( splashEmitterList[i]->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast );
}
}
for (int j = 0; j < VC_NUM_DAMAGE_EMITTER_AREAS; j++)
{
stream->write( damageEmitterOffset[j].x );
stream->write( damageEmitterOffset[j].y );
stream->write( damageEmitterOffset[j].z );
}
for (int k = 0; k < VC_NUM_DAMAGE_LEVELS; k++)
{
stream->write( damageLevelTolerance[k] );
}
stream->write(splashFreqMod);
stream->write(splashVelEpsilon);
stream->write(collDamageThresholdVel);
stream->write(collDamageMultiplier);
}
void VehicleData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&body.restitution);
stream->read(&body.friction);
S32 i;
for (i = 0; i < Body::MaxSounds; i++) {
body.sound[i] = NULL;
if (stream->readFlag())
body.sound[i] = (AudioProfile*)stream->readRangedU32(DataBlockObjectIdFirst,
DataBlockObjectIdLast);
}
stream->read(&minImpactSpeed);
stream->read(&softImpactSpeed);
stream->read(&hardImpactSpeed);
stream->read(&minRollSpeed);
stream->read(&maxSteeringAngle);
stream->read(&maxDrag);
stream->read(&minDrag);
stream->read(&integration);
stream->read(&collisionTol);
stream->read(&contactTol);
mathRead(*stream,&massCenter);
mathRead(*stream,&massBox);
stream->read(&jetForce);
stream->read(&jetEnergyDrain);
stream->read(&minJetEnergy);
cameraRoll = stream->readFlag();
stream->read(&cameraLag);
stream->read(&cameraDecay);
stream->read(&cameraOffset);
stream->read( &triggerDustHeight );
stream->read( &dustHeight );
stream->read( &numDmgEmitterAreas );
stream->read(&exitSplashSoundVel);
stream->read(&softSplashSoundVel);
stream->read(&medSplashSoundVel);
stream->read(&hardSplashSoundVel);
// write the water sound profiles
for(i = 0; i < MaxSounds; i++)
if(stream->readFlag())
{
U32 id = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
waterSound[i] = dynamic_cast<AudioProfile*>( Sim::findObject(id) );
}
if( stream->readFlag() )
{
dustID = (S32) stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
}
for (i = 0; i < VC_NUM_DAMAGE_EMITTERS; i++)
{
if( stream->readFlag() )
{
damageEmitterIDList[i] = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
}
}
for (i = 0; i < VC_NUM_SPLASH_EMITTERS; i++)
{
if( stream->readFlag() )
{
splashEmitterIDList[i] = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
}
}
for( int j=0; j<VC_NUM_DAMAGE_EMITTER_AREAS; j++ )
{
stream->read( &damageEmitterOffset[j].x );
stream->read( &damageEmitterOffset[j].y );
stream->read( &damageEmitterOffset[j].z );
}
for( int k=0; k<VC_NUM_DAMAGE_LEVELS; k++ )
{
stream->read( &damageLevelTolerance[k] );
}
stream->read(&splashFreqMod);
stream->read(&splashVelEpsilon);
stream->read(&collDamageThresholdVel);
stream->read(&collDamageMultiplier);
}
//----------------------------------------------------------------------------
void VehicleData::initPersistFields()
{
Parent::initPersistFields();
addField("jetForce", TypeF32, Offset(jetForce, VehicleData));
addField("jetEnergyDrain", TypeF32, Offset(jetEnergyDrain, VehicleData));
addField("minJetEnergy", TypeF32, Offset(minJetEnergy, VehicleData));
addField("massCenter", TypePoint3F, Offset(massCenter, VehicleData));
addField("massBox", TypePoint3F, Offset(massBox, VehicleData));
addField("bodyRestitution", TypeF32, Offset(body.restitution, VehicleData));
addField("bodyFriction", TypeF32, Offset(body.friction, VehicleData));
addField("softImpactSound", TypeAudioProfilePtr, Offset(body.sound[Body::SoftImpactSound], VehicleData));
addField("hardImpactSound", TypeAudioProfilePtr, Offset(body.sound[Body::HardImpactSound], VehicleData));
addField("minImpactSpeed", TypeF32, Offset(minImpactSpeed, VehicleData));
addField("softImpactSpeed", TypeF32, Offset(softImpactSpeed, VehicleData));
addField("hardImpactSpeed", TypeF32, Offset(hardImpactSpeed, VehicleData));
addField("minRollSpeed", TypeF32, Offset(minRollSpeed, VehicleData));
addField("maxSteeringAngle", TypeF32, Offset(maxSteeringAngle, VehicleData));
addField("maxDrag", TypeF32, Offset(maxDrag, VehicleData));
addField("minDrag", TypeF32, Offset(minDrag, VehicleData));
addField("integration", TypeS32, Offset(integration, VehicleData));
addField("collisionTol", TypeF32, Offset(collisionTol, VehicleData));
addField("contactTol", TypeF32, Offset(contactTol, VehicleData));
addField("cameraRoll", TypeBool, Offset(cameraRoll, VehicleData));
addField("cameraLag", TypeF32, Offset(cameraLag, VehicleData));
addField("cameraDecay", TypeF32, Offset(cameraDecay, VehicleData));
addField("cameraOffset", TypeF32, Offset(cameraOffset, VehicleData));
addField("dustEmitter", TypeParticleEmitterDataPtr, Offset(dustEmitter, VehicleData));
addField("triggerDustHeight", TypeF32, Offset(triggerDustHeight, VehicleData));
addField("dustHeight", TypeF32, Offset(dustHeight, VehicleData));
addField("damageEmitter", TypeParticleEmitterDataPtr, Offset(damageEmitterList, VehicleData), VC_NUM_DAMAGE_EMITTERS);
addField("splashEmitter", TypeParticleEmitterDataPtr, Offset(splashEmitterList, VehicleData), VC_NUM_SPLASH_EMITTERS);
addField("damageEmitterOffset", TypePoint3F, Offset(damageEmitterOffset, VehicleData), VC_NUM_DAMAGE_EMITTER_AREAS);
addField("damageLevelTolerance", TypeF32, Offset(damageLevelTolerance, VehicleData), VC_NUM_DAMAGE_LEVELS);
addField("numDmgEmitterAreas", TypeF32, Offset(numDmgEmitterAreas, VehicleData));
addField("splashFreqMod", TypeF32, Offset(splashFreqMod, VehicleData));
addField("splashVelEpsilon", TypeF32, Offset(splashVelEpsilon, VehicleData));
addField("exitSplashSoundVelocity", TypeF32, Offset(exitSplashSoundVel, VehicleData));
addField("softSplashSoundVelocity", TypeF32, Offset(softSplashSoundVel, VehicleData));
addField("mediumSplashSoundVelocity", TypeF32, Offset(medSplashSoundVel, VehicleData));
addField("hardSplashSoundVelocity", TypeF32, Offset(hardSplashSoundVel, VehicleData));
addField("exitingWater", TypeAudioProfilePtr, Offset(waterSound[ExitWater], VehicleData));
addField("impactWaterEasy", TypeAudioProfilePtr, Offset(waterSound[ImpactSoft], VehicleData));
addField("impactWaterMedium", TypeAudioProfilePtr, Offset(waterSound[ImpactMedium], VehicleData));
addField("impactWaterHard", TypeAudioProfilePtr, Offset(waterSound[ImpactHard], VehicleData));
addField("waterWakeSound", TypeAudioProfilePtr, Offset(waterSound[Wake], VehicleData));
addField("collDamageThresholdVel", TypeF32, Offset(collDamageThresholdVel, VehicleData));
addField("collDamageMultiplier", TypeF32, Offset(collDamageMultiplier, VehicleData));
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(Vehicle);
Vehicle::Vehicle()
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -