📄 explosion.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "game/fx/explosion.h"
#include "console/consoleTypes.h"
#include "console/typeValidators.h"
#include "dgl/dgl.h"
#include "platform/platformAudio.h"
#include "audio/audioDataBlock.h"
#include "sceneGraph/sceneGraph.h"
#include "sceneGraph/sceneState.h"
#include "core/bitStream.h"
#include "sim/netConnection.h"
#include "ts/tsShape.h"
#include "ts/tsShapeInstance.h"
#include "math/mRandom.h"
#include "math/mathIO.h"
#include "math/mathUtils.h"
#include "game/debris.h"
#include "game/gameConnection.h"
#include "game/fx/particleEngine.h"
#include "game/fx/cameraFXMgr.h"
#include "util/safeDelete.h"
IMPLEMENT_CONOBJECT(Explosion);
#define MaxLightRadius 20
MRandomLCG sgRandom(0xdeadbeef);
ConsoleFunction( calcExplosionCoverage, F32, 4, 4, "(Point3F source, SceneObject originator, bitset coverageMask)")
{
Point3F pos, center;
dSscanf(argv[1], "%g %g %g", &pos.x, &pos.y, &pos.z);
S32 id = dAtoi(argv[2]);
U32 covMask = (U32)dAtoi(argv[3]);
SceneObject* sceneObject = NULL;
if (Sim::findObject(id, sceneObject) == false)
{
Con::warnf(ConsoleLogEntry::General, "calcExplosionCoverage: couldn't find object: %s", argv[2]);
return 1.0;
}
#ifdef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if ( sceneObject->getContainer() == NULL)
#else
if (sceneObject->isClientObject() || sceneObject->getContainer() == NULL)
#endif
{
Con::warnf(ConsoleLogEntry::General, "calcExplosionCoverage: object is on the client, or not in the container system");
return 1.0;
}
sceneObject->getObjBox().getCenter(¢er);
center.convolve(sceneObject->getScale());
sceneObject->getTransform().mulP(center);
RayInfo rayInfo;
sceneObject->disableCollision();
if (sceneObject->getContainer()->castRay(pos, center, covMask, &rayInfo) == true)
{
// Try casting up and then out
if (sceneObject->getContainer()->castRay(pos, pos + Point3F(0, 0, 1), covMask, &rayInfo) == false)
{
if (sceneObject->getContainer()->castRay(pos + Point3F(0, 0, 1), center, covMask, &rayInfo) == false)
{
sceneObject->enableCollision();
return 1.0;
}
}
sceneObject->enableCollision();
return 0.0;
}
else
{
sceneObject->enableCollision();
return 1.0;
}
}
//----------------------------------------------------------------------------
//
IMPLEMENT_CO_DATABLOCK_V1(ExplosionData);
ExplosionData::ExplosionData()
{
dtsFileName = NULL;
particleDensity = 10;
particleRadius = 1;
faceViewer = false;
soundProfile = NULL;
particleEmitter = NULL;
soundProfileId = 0;
particleEmitterId = 0;
explosionScale.set(1, 1, 1);
playSpeed = 1.0;
dMemset( emitterList, 0, sizeof( emitterList ) );
dMemset( emitterIDList, 0, sizeof( emitterIDList ) );
dMemset( debrisList, 0, sizeof( debrisList ) );
dMemset( debrisIDList, 0, sizeof( debrisIDList ) );
debrisThetaMin = 0;
debrisThetaMax = 90;
debrisPhiMin = 0;
debrisPhiMax = 360;
debrisNum = 1;
debrisNumVariance = 0;
debrisVelocity = 2.0;
debrisVelocityVariance = 0.0;
dMemset( explosionList, 0, sizeof( explosionList ) );
dMemset( explosionIDList, 0, sizeof( explosionIDList ) );
delayMS = 0;
delayVariance = 0;
lifetimeMS = 1000;
lifetimeVariance = 0;
offset = 0;
shockwave = NULL;
shockwaveID = 0;
shockwaveOnTerrain = false;
shakeCamera = false;
camShakeFreq.set( 10.0, 10.0, 10.0 );
camShakeAmp.set( 1.0, 1.0, 1.0 );
camShakeDuration = 1.5;
camShakeRadius = 10.0;
camShakeFalloff = 10.0;
for( U32 i=0; i<EC_NUM_TIME_KEYS; i++ )
{
times[i] = 1.0;
}
times[0] = 0.0;
for( U32 j=0; j<EC_NUM_TIME_KEYS; j++ )
{
sizes[j].set( 1.0, 1.0, 1.0 );
}
//
lightStartRadius = lightEndRadius = 0;
lightStartColor.set(1,1,1);
lightEndColor.set(1,1,1);
}
IMPLEMENT_CONSOLETYPE(ExplosionData)
IMPLEMENT_SETDATATYPE(ExplosionData)
IMPLEMENT_GETDATATYPE(ExplosionData)
void ExplosionData::initPersistFields()
{
Parent::initPersistFields();
addField("explosionShape", TypeFilename, Offset(dtsFileName, ExplosionData));
addField("soundProfile", TypeAudioProfilePtr, Offset(soundProfile, ExplosionData));
addField("faceViewer", TypeBool, Offset(faceViewer, ExplosionData));
addField("particleEmitter", TypeParticleEmitterDataPtr, Offset(particleEmitter, ExplosionData));
addField("particleDensity", TypeS32, Offset(particleDensity, ExplosionData));
addField("particleRadius", TypeF32, Offset(particleRadius, ExplosionData));
addField("explosionScale", TypePoint3F, Offset(explosionScale, ExplosionData));
addField("playSpeed", TypeF32, Offset(playSpeed, ExplosionData));
addField("emitter", TypeParticleEmitterDataPtr, Offset(emitterList, ExplosionData), EC_NUM_EMITTERS);
addField("debris", TypeDebrisDataPtr, Offset(debrisList, ExplosionData), EC_NUM_DEBRIS_TYPES);
addField("debrisThetaMin", TypeF32, Offset(debrisThetaMin, ExplosionData));
addField("debrisThetaMax", TypeF32, Offset(debrisThetaMax, ExplosionData));
addField("debrisPhiMin", TypeF32, Offset(debrisPhiMin, ExplosionData));
addField("debrisPhiMax", TypeF32, Offset(debrisPhiMax, ExplosionData));
addField("debrisNum", TypeS32, Offset(debrisNum, ExplosionData));
addField("debrisNumVariance", TypeS32, Offset(debrisNumVariance, ExplosionData));
addField("debrisVelocity", TypeF32, Offset(debrisVelocity, ExplosionData));
addField("debrisVelocityVariance", TypeF32, Offset(debrisVelocityVariance, ExplosionData));
addField("subExplosion", TypeExplosionDataPtr, Offset(explosionList, ExplosionData), EC_MAX_SUB_EXPLOSIONS );
addField("delayMS", TypeS32, Offset(delayMS, ExplosionData));
addField("delayVariance", TypeS32, Offset(delayVariance, ExplosionData));
addField("lifetimeMS", TypeS32, Offset(lifetimeMS, ExplosionData));
addField("lifetimeVariance", TypeS32, Offset(lifetimeVariance, ExplosionData));
addField("offset", TypeF32, Offset(offset, ExplosionData));
addField("times", TypeF32, Offset(times, ExplosionData), EC_NUM_TIME_KEYS );
addField("sizes", TypePoint3F, Offset(sizes, ExplosionData), EC_NUM_TIME_KEYS );
addField("shakeCamera", TypeBool, Offset(shakeCamera, ExplosionData));
addField("camShakeFreq", TypePoint3F, Offset(camShakeFreq, ExplosionData));
addField("camShakeAmp", TypePoint3F, Offset(camShakeAmp, ExplosionData));
addField("camShakeDuration", TypeF32, Offset(camShakeDuration, ExplosionData));
addField("camShakeRadius", TypeF32, Offset(camShakeRadius, ExplosionData));
addField("camShakeFalloff", TypeF32, Offset(camShakeFalloff, ExplosionData));
addNamedFieldV(lightStartRadius, TypeF32, ExplosionData, new FRangeValidator(0, MaxLightRadius));
addNamedFieldV(lightEndRadius, TypeF32, ExplosionData, new FRangeValidator(0, MaxLightRadius));
addNamedField(lightStartColor, TypeColorF, ExplosionData);
addNamedField(lightEndColor, TypeColorF, ExplosionData);
}
bool ExplosionData::onAdd()
{
if (Parent::onAdd() == false)
return false;
if (!soundProfile && soundProfileId != 0)
if (Sim::findObject(soundProfileId, soundProfile) == false)
Con::errorf(ConsoleLogEntry::General, "Error, unable to load sound profile for explosion datablock");
if (!particleEmitter && particleEmitterId != 0)
if (Sim::findObject(particleEmitterId, particleEmitter) == false)
Con::errorf(ConsoleLogEntry::General, "Error, unable to load particle emitter for explosion datablock");
if (explosionScale.x < 0.01 || explosionScale.y < 0.01 || explosionScale.z < 0.01)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s)::onAdd: ExplosionScale components must be >= 0.01", getName());
explosionScale.x = explosionScale.x < 0.01 ? 0.01 : explosionScale.x;
explosionScale.y = explosionScale.y < 0.01 ? 0.01 : explosionScale.y;
explosionScale.z = explosionScale.z < 0.01 ? 0.01 : explosionScale.z;
}
if (debrisThetaMin < 0.0f)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) debrisThetaMin < 0.0", getName());
debrisThetaMin = 0.0f;
}
if (debrisThetaMax > 180.0f)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) debrisThetaMax > 180.0", getName());
debrisThetaMax = 180.0f;
}
if (debrisThetaMin > debrisThetaMax)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) debrisThetaMin > debrisThetaMax", getName());
debrisThetaMin = debrisThetaMax;
}
if (debrisPhiMin < 0.0f)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) debrisPhiMin < 0.0", getName());
debrisPhiMin = 0.0f;
}
if (debrisPhiMax > 360.0f)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) debrisPhiMax > 360.0", getName());
debrisPhiMax = 360.0f;
}
if (debrisPhiMin > debrisPhiMax)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) debrisPhiMin > debrisPhiMax", getName());
debrisPhiMin = debrisPhiMax;
}
if (debrisNum > 1000)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) debrisNum > 1000", getName());
debrisNum = 1000;
}
if (debrisNumVariance > 1000)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) debrisNumVariance > 1000", getName());
debrisNumVariance = 1000;
}
if (debrisVelocity < 0.1)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) debrisVelocity < 0.1", getName());
debrisVelocity = 0.1;
}
if (debrisVelocityVariance > 1000)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) debrisVelocityVariance > 1000", getName());
debrisVelocityVariance = 1000;
}
if (playSpeed < 0.05)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) playSpeed < 0.05", getName());
playSpeed = 0.05;
}
if (lifetimeMS < 1)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) lifetimeMS < 1", getName());
lifetimeMS = 1;
}
if (lifetimeVariance > lifetimeMS)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) lifetimeVariance > lifetimeMS", getName());
lifetimeVariance = lifetimeMS;
}
if (delayMS < 0)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) delayMS < 0", getName());
delayMS = 0;
}
if (delayVariance > delayMS)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) delayVariance > delayMS", getName());
delayVariance = delayMS;
}
if (offset < 0.0)
{
Con::warnf(ConsoleLogEntry::General, "ExplosionData(%s) offset < 0.0", getName());
offset = 0.0;
}
S32 i;
for( i=0; i<EC_NUM_DEBRIS_TYPES; i++ )
{
if( !debrisList[i] && debrisIDList[i] != 0 )
{
if( !Sim::findObject( debrisIDList[i], debrisList[i] ) )
{
Con::errorf( ConsoleLogEntry::General, "ExplosionData::onAdd: Invalid packet, bad datablockId(debris): 0x%x", debrisIDList[i] );
}
}
}
for( i=0; i<EC_NUM_EMITTERS; i++ )
{
if( !emitterList[i] && emitterIDList[i] != 0 )
{
if( Sim::findObject( emitterIDList[i], emitterList[i] ) == false)
{
Con::errorf( ConsoleLogEntry::General, "ExplosionData::onAdd: Invalid packet, bad datablockId(particle emitter): 0x%x", emitterIDList[i] );
}
}
}
for( S32 k=0; k<EC_MAX_SUB_EXPLOSIONS; k++ )
{
if( !explosionList[k] && explosionIDList[k] != 0 )
{
if( Sim::findObject( explosionIDList[k], explosionList[k] ) == false)
{
Con::errorf( ConsoleLogEntry::General, "ExplosionData::onAdd: Invalid packet, bad datablockId(explosion): 0x%x", explosionIDList[k] );
}
}
}
return true;
}
void ExplosionData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(dtsFileName);
if (stream->writeFlag(soundProfile != NULL))
stream->writeRangedU32(soundProfile->getId(), DataBlockObjectIdFirst,
DataBlockObjectIdLast);
if (stream->writeFlag(particleEmitter))
stream->writeRangedU32(particleEmitter->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
stream->writeInt(particleDensity, 14);
stream->write(particleRadius);
stream->writeFlag(faceViewer);
if(stream->writeFlag(explosionScale.x != 1 || explosionScale.y != 1 || explosionScale.z != 1))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -