📄 hovervehicle.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "game/vehicles/hoverVehicle.h"
#include "core/bitStream.h"
#include "dgl/dgl.h"
#include "sceneGraph/sceneState.h"
#include "collision/clippedPolyList.h"
#include "collision/planeExtractor.h"
#include "game/moveManager.h"
#include "ts/tsShapeInstance.h"
#include "console/consoleTypes.h"
#include "terrain/terrData.h"
#include "sceneGraph/sceneGraph.h"
#include "audio/audioDataBlock.h"
#include "game/fx/particleEngine.h"
#include "math/mathIO.h"
#include "dgl/materialPropertyMap.h"
#include "terrain/waterBlock.h"
IMPLEMENT_CO_DATABLOCK_V1(HoverVehicleData);
IMPLEMENT_CO_NETOBJECT_V1(HoverVehicle);
namespace {
const U32 sIntergrationsPerTick = 1;
const F32 sHoverVehicleGravity = -20;
const U32 sCollisionMoveMask = (TerrainObjectType | InteriorObjectType |
PlayerObjectType | StaticTSObjectType |
StaticShapeObjectType | VehicleObjectType |
VehicleBlockerObjectType);
const U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
const U32 sClientCollisionMask = sCollisionMoveMask;
void nonFilter(SceneObject* object,void *key)
{
Container::CallbackInfo* info = reinterpret_cast<Container::CallbackInfo*>(key);
object->buildPolyList(info->polyList,info->boundingBox,info->boundingSphere);
}
} // namespace {}
const char* HoverVehicle::sJetSequence[HoverVehicle::JetAnimCount] =
{
"activateBack",
"maintainBack",
};
const char* HoverVehicleData::sJetNode[HoverVehicleData::MaxJetNodes] =
{
"JetNozzle0", // Thrust Forward
"JetNozzle1",
"JetNozzleX", // Thrust Backward
"JetNozzleX",
"JetNozzle2", // Thrust Downward
"JetNozzle3",
};
// Convert thrust direction into nodes & emitters
HoverVehicle::JetActivation HoverVehicle::sJetActivation[NumThrustDirections] = {
{ HoverVehicleData::ForwardJetNode, HoverVehicleData::ForwardJetEmitter },
{ HoverVehicleData::BackwardJetNode, HoverVehicleData::BackwardJetEmitter },
{ HoverVehicleData::DownwardJetNode, HoverVehicleData::DownwardJetEmitter },
};
//--------------------------------------------------------------------------
//--------------------------------------
//
HoverVehicleData::HoverVehicleData()
{
dragForce = 0;
vertFactor = 0.25;
floatingThrustFactor = 0.15;
mainThrustForce = 0;
reverseThrustForce = 0;
strafeThrustForce = 0;
turboFactor = 1.0;
stabLenMin = 0.5;
stabLenMax = 2.0;
stabSpringConstant = 30;
stabDampingConstant = 10;
gyroDrag = 10;
normalForce = 30;
restorativeForce = 10;
steeringForce = 25;
rollForce = 2.5;
pitchForce = 2.5;
dustTrailEmitter = NULL;
dustTrailID = 0;
dustTrailOffset.set( 0.0, 0.0, 0.0 );
dustTrailFreqMod = 15.0;
triggerTrailHeight = 2.5;
floatingGravMag = 1;
brakingForce = 0;
brakingActivationSpeed = 0;
for (S32 k = 0; k < MaxJetNodes; k++)
jetNode[k] = -1;
for (S32 j = 0; j < MaxJetEmitters; j++)
jetEmitter[j] = 0;
for (S32 i = 0; i < MaxSounds; i++)
sound[i] = 0;
}
HoverVehicleData::~HoverVehicleData()
{
}
//--------------------------------------------------------------------------
void HoverVehicleData::initPersistFields()
{
Parent::initPersistFields();
addField("dragForce", TypeF32, Offset(dragForce, HoverVehicleData));
addField("vertFactor", TypeF32, Offset(vertFactor, HoverVehicleData));
addField("floatingThrustFactor", TypeF32, Offset(floatingThrustFactor, HoverVehicleData));
addField("mainThrustForce", TypeF32, Offset(mainThrustForce, HoverVehicleData));
addField("reverseThrustForce", TypeF32, Offset(reverseThrustForce, HoverVehicleData));
addField("strafeThrustForce", TypeF32, Offset(strafeThrustForce, HoverVehicleData));
addField("turboFactor", TypeF32, Offset(turboFactor, HoverVehicleData));
addField("stabLenMin", TypeF32, Offset(stabLenMin, HoverVehicleData));
addField("stabLenMax", TypeF32, Offset(stabLenMax, HoverVehicleData));
addField("stabSpringConstant", TypeF32, Offset(stabSpringConstant, HoverVehicleData));
addField("stabDampingConstant", TypeF32, Offset(stabDampingConstant, HoverVehicleData));
addField("gyroDrag", TypeF32, Offset(gyroDrag, HoverVehicleData));
addField("normalForce", TypeF32, Offset(normalForce, HoverVehicleData));
addField("restorativeForce", TypeF32, Offset(restorativeForce, HoverVehicleData));
addField("steeringForce", TypeF32, Offset(steeringForce, HoverVehicleData));
addField("rollForce", TypeF32, Offset(rollForce, HoverVehicleData));
addField("pitchForce", TypeF32, Offset(pitchForce, HoverVehicleData));
addField("jetSound", TypeAudioProfilePtr, Offset(sound[JetSound], HoverVehicleData));
addField("engineSound", TypeAudioProfilePtr, Offset(sound[EngineSound], HoverVehicleData));
addField("floatSound", TypeAudioProfilePtr, Offset(sound[FloatSound], HoverVehicleData));
addField("dustTrailEmitter", TypeParticleEmitterDataPtr, Offset(dustTrailEmitter, HoverVehicleData));
addField("dustTrailOffset", TypePoint3F, Offset(dustTrailOffset, HoverVehicleData));
addField("triggerTrailHeight", TypeF32, Offset(triggerTrailHeight, HoverVehicleData));
addField("dustTrailFreqMod", TypeF32, Offset(dustTrailFreqMod, HoverVehicleData));
addField("floatingGravMag", TypeF32, Offset(floatingGravMag, HoverVehicleData));
addField("brakingForce", TypeF32, Offset(brakingForce, HoverVehicleData));
addField("brakingActivationSpeed", TypeF32, Offset(brakingActivationSpeed, HoverVehicleData));
addField("forwardJetEmitter",TypeParticleEmitterDataPtr, Offset(jetEmitter[ForwardJetEmitter], HoverVehicleData));
}
//--------------------------------------------------------------------------
bool HoverVehicleData::onAdd()
{
if(!Parent::onAdd())
return false;
return true;
}
bool HoverVehicleData::preload(bool server, char errorBuffer[256])
{
if (Parent::preload(server, errorBuffer) == false)
return false;
if (dragForce <= 0.01f) {
Con::warnf("HoverVehicleData::preload: dragForce must be at least 0.01");
dragForce = 0.01f;
}
if (vertFactor < 0.0f || vertFactor > 1.0f) {
Con::warnf("HoverVehicleData::preload: vert factor must be [0, 1]");
vertFactor = vertFactor < 0.0f ? 0.0f : 1.0f;
}
if (floatingThrustFactor < 0.0f || floatingThrustFactor > 1.0f) {
Con::warnf("HoverVehicleData::preload: floatingThrustFactor must be [0, 1]");
floatingThrustFactor = floatingThrustFactor < 0.0f ? 0.0f : 1.0f;
}
maxThrustSpeed = (mainThrustForce + strafeThrustForce) / dragForce;
massCenter = Point3F(0, 0, 0);
// Resolve objects transmitted from server
if (!server) {
for (S32 i = 0; i < MaxSounds; i++)
if (sound[i])
Sim::findObject(SimObjectId(sound[i]),sound[i]);
for (S32 j = 0; j < MaxJetEmitters; j++)
if (jetEmitter[j])
Sim::findObject(SimObjectId(jetEmitter[j]),jetEmitter[j]);
}
if( !dustTrailEmitter && dustTrailID != 0 )
{
if( !Sim::findObject( dustTrailID, dustTrailEmitter ) )
{
Con::errorf( ConsoleLogEntry::General, "HoverVehicleData::preload Invalid packet, bad datablockId(dustTrailEmitter): 0x%x", dustTrailID );
}
}
// Resolve jet nodes
for (S32 j = 0; j < MaxJetNodes; j++)
jetNode[j] = shape->findNode(sJetNode[j]);
return true;
}
//--------------------------------------------------------------------------
void HoverVehicleData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(dragForce);
stream->write(vertFactor);
stream->write(floatingThrustFactor);
stream->write(mainThrustForce);
stream->write(reverseThrustForce);
stream->write(strafeThrustForce);
stream->write(turboFactor);
stream->write(stabLenMin);
stream->write(stabLenMax);
stream->write(stabSpringConstant);
stream->write(stabDampingConstant);
stream->write(gyroDrag);
stream->write(normalForce);
stream->write(restorativeForce);
stream->write(steeringForce);
stream->write(rollForce);
stream->write(pitchForce);
mathWrite(*stream, dustTrailOffset);
stream->write(triggerTrailHeight);
stream->write(dustTrailFreqMod);
for (S32 i = 0; i < MaxSounds; i++)
if (stream->writeFlag(sound[i]))
stream->writeRangedU32(packed? SimObjectId(sound[i]):
sound[i]->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
for (S32 j = 0; j < MaxJetEmitters; j++)
{
if (stream->writeFlag(jetEmitter[j]))
{
SimObjectId writtenId = packed ? SimObjectId(jetEmitter[j]) : jetEmitter[j]->getId();
stream->writeRangedU32(writtenId, DataBlockObjectIdFirst,DataBlockObjectIdLast);
}
}
if (stream->writeFlag( dustTrailEmitter ))
{
stream->writeRangedU32( dustTrailEmitter->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast );
}
stream->write(floatingGravMag);
stream->write(brakingForce);
stream->write(brakingActivationSpeed);
}
void HoverVehicleData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&dragForce);
stream->read(&vertFactor);
stream->read(&floatingThrustFactor);
stream->read(&mainThrustForce);
stream->read(&reverseThrustForce);
stream->read(&strafeThrustForce);
stream->read(&turboFactor);
stream->read(&stabLenMin);
stream->read(&stabLenMax);
stream->read(&stabSpringConstant);
stream->read(&stabDampingConstant);
stream->read(&gyroDrag);
stream->read(&normalForce);
stream->read(&restorativeForce);
stream->read(&steeringForce);
stream->read(&rollForce);
stream->read(&pitchForce);
mathRead(*stream, &dustTrailOffset);
stream->read(&triggerTrailHeight);
stream->read(&dustTrailFreqMod);
for (S32 i = 0; i < MaxSounds; i++)
sound[i] = stream->readFlag()?
(AudioProfile*) stream->readRangedU32(DataBlockObjectIdFirst,
DataBlockObjectIdLast): 0;
for (S32 j = 0; j < MaxJetEmitters; j++) {
jetEmitter[j] = NULL;
if (stream->readFlag())
jetEmitter[j] = (ParticleEmitterData*)stream->readRangedU32(DataBlockObjectIdFirst,
DataBlockObjectIdLast);
}
if( stream->readFlag() )
{
dustTrailID = (S32) stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
}
stream->read(&floatingGravMag);
stream->read(&brakingForce);
stream->read(&brakingActivationSpeed);
}
//--------------------------------------------------------------------------
//--------------------------------------
//
HoverVehicle::HoverVehicle()
{
// Todo: ScopeAlways?
mNetFlags.set(Ghostable);
mFloating = false;
mForwardThrust = 0;
mReverseThrust = 0;
mLeftThrust = 0;
mRightThrust = 0;
mJetSound = NULL_AUDIOHANDLE;
mEngineSound = NULL_AUDIOHANDLE;
mFloatSound = NULL_AUDIOHANDLE;
mDustTrailEmitter = NULL;
mBackMaintainOn = false;
for (S32 i = 0; i < JetAnimCount; i++)
mJetThread[i] = 0;
}
HoverVehicle::~HoverVehicle()
{
//
}
//--------------------------------------------------------------------------
bool HoverVehicle::onAdd()
{
if(!Parent::onAdd())
return false;
addToScene();
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
if( !isServerObject() )
#endif
{
if( mDataBlock->dustTrailEmitter )
{
mDustTrailEmitter = new ParticleEmitter;
mDustTrailEmitter->onNewDataBlock( mDataBlock->dustTrailEmitter );
if( !mDustTrailEmitter->registerObject() )
{
Con::warnf( ConsoleLogEntry::General, "Could not register dust emitter for class: %s", mDataBlock->getName() );
delete mDustTrailEmitter;
mDustTrailEmitter = NULL;
}
}
// Jet Sequences
for (S32 i = 0; i < JetAnimCount; i++) {
TSShape const* shape = mShapeInstance->getShape();
mJetSeq[i] = shape->findSequence(sJetSequence[i]);
if (mJetSeq[i] != -1) {
if (i == BackActivate) {
mJetThread[i] = mShapeInstance->addThread();
mShapeInstance->setSequence(mJetThread[i],mJetSeq[i],0);
mShapeInstance->setTimeScale(mJetThread[i],0);
}
}
else
mJetThread[i] = 0;
}
}
if (isServerObject())
scriptOnAdd();
return true;
}
void HoverVehicle::onRemove()
{
scriptOnRemove();
removeFromScene();
if (mJetSound != NULL_AUDIOHANDLE)
alxStop(mJetSound);
if (mEngineSound != NULL_AUDIOHANDLE)
alxStop(mEngineSound);
if (mFloatSound != NULL_AUDIOHANDLE)
alxStop(mFloatSound);
Parent::onRemove();
}
bool HoverVehicle::onNewDataBlock(GameBaseData* dptr)
{
mDataBlock = dynamic_cast<HoverVehicleData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr))
return false;
// Todo: Uncomment if this is a "leaf" class
scriptOnNewDataBlock();
return true;
}
//--------------------------------------------------------------------------
void HoverVehicle::advanceTime(F32 dt)
{
Parent::advanceTime(dt);
// Update jetsound...
if (mJetting) {
if (mJetSound == NULL_AUDIOHANDLE && mDataBlock->sound[HoverVehicleData::JetSound] != NULL)
mJetSound = alxPlay(mDataBlock->sound[HoverVehicleData::JetSound], &getTransform());
if (mJetSound != NULL_AUDIOHANDLE)
alxSourceMatrixF(mJetSound, &getTransform());
} else {
if (mJetSound != NULL_AUDIOHANDLE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -