|
@@ -24,6 +24,7 @@
|
|
|
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
|
|
// Copyright (C) 2015 Faust Logic, Inc.
|
|
|
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
|
|
+
|
|
|
#include "platform/platform.h"
|
|
|
#include "T3D/fx/explosion.h"
|
|
|
|
|
@@ -54,6 +55,8 @@
|
|
|
#include "renderInstance/renderPassManager.h"
|
|
|
#include "console/engineAPI.h"
|
|
|
|
|
|
+#include "sfx/sfxProfile.h"
|
|
|
+
|
|
|
IMPLEMENT_CONOBJECT(Explosion);
|
|
|
|
|
|
ConsoleDocClass( Explosion,
|
|
@@ -285,6 +288,105 @@ ExplosionData::ExplosionData()
|
|
|
lightNormalOffset = 0.1f;
|
|
|
}
|
|
|
|
|
|
+//#define TRACK_EXPLOSION_DATA_CLONES
|
|
|
+
|
|
|
+#ifdef TRACK_EXPLOSION_DATA_CLONES
|
|
|
+static int explosion_data_clones = 0;
|
|
|
+#endif
|
|
|
+
|
|
|
+ExplosionData::ExplosionData(const ExplosionData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
|
|
+{
|
|
|
+#ifdef TRACK_EXPLOSION_DATA_CLONES
|
|
|
+ explosion_data_clones++;
|
|
|
+ if (explosion_data_clones == 1)
|
|
|
+ Con::errorf("ExplosionData -- Clones are on the loose!");
|
|
|
+#endif
|
|
|
+
|
|
|
+ dtsFileName = other.dtsFileName;
|
|
|
+ faceViewer = other.faceViewer;
|
|
|
+ particleDensity = other.particleDensity;
|
|
|
+ particleRadius = other.particleRadius;
|
|
|
+ soundProfile = other.soundProfile;
|
|
|
+ particleEmitter = other.particleEmitter;
|
|
|
+ particleEmitterId = other.particleEmitterId; // -- for pack/unpack of particleEmitter ptr
|
|
|
+ explosionScale = other.explosionScale;
|
|
|
+ playSpeed = other.playSpeed;
|
|
|
+ explosionShape = other.explosionShape; // -- TSShape loaded using dtsFileName
|
|
|
+ explosionAnimation = other.explosionAnimation; // -- from explosionShape sequence "ambient"
|
|
|
+ dMemcpy( emitterList, other.emitterList, sizeof( emitterList ) );
|
|
|
+ dMemcpy( emitterIDList, other.emitterIDList, sizeof( emitterIDList ) ); // -- for pack/unpack of emitterList ptrs
|
|
|
+ dMemcpy( debrisList, other.debrisList, sizeof( debrisList ) );
|
|
|
+ dMemcpy( debrisIDList, other.debrisIDList, sizeof( debrisIDList ) ); // -- for pack/unpack of debrisList ptrs
|
|
|
+ debrisThetaMin = other.debrisThetaMin;
|
|
|
+ debrisThetaMax = other.debrisThetaMax;
|
|
|
+ debrisPhiMin = other.debrisPhiMin;
|
|
|
+ debrisPhiMax = other.debrisPhiMax;
|
|
|
+ debrisNum = other.debrisNum;
|
|
|
+ debrisNumVariance = other.debrisNumVariance;
|
|
|
+ debrisVelocity = other.debrisVelocity;
|
|
|
+ debrisVelocityVariance = other.debrisVelocityVariance;
|
|
|
+ dMemcpy( explosionList, other.explosionList, sizeof( explosionList ) );
|
|
|
+ dMemcpy( explosionIDList, other.explosionIDList, sizeof( explosionIDList ) ); // -- for pack/unpack of explosionList ptrs
|
|
|
+ delayMS = other.delayMS;
|
|
|
+ delayVariance = other.delayVariance;
|
|
|
+ lifetimeMS = other.lifetimeMS;
|
|
|
+ lifetimeVariance = other.lifetimeVariance;
|
|
|
+ offset = other.offset;
|
|
|
+ dMemcpy( sizes, other.times, sizeof( sizes ) );
|
|
|
+ dMemcpy( times, other.times, sizeof( times ) );
|
|
|
+ shakeCamera = other.shakeCamera;
|
|
|
+ camShakeFreq = other.camShakeFreq;
|
|
|
+ camShakeAmp = other.camShakeAmp;
|
|
|
+ camShakeDuration = other.camShakeDuration;
|
|
|
+ camShakeRadius = other.camShakeRadius;
|
|
|
+ camShakeFalloff = other.camShakeFalloff;
|
|
|
+ lightStartRadius = other.lightStartRadius;
|
|
|
+ lightEndRadius = other.lightEndRadius;
|
|
|
+ lightStartColor = other.lightStartColor;
|
|
|
+ lightEndColor = other.lightEndColor;
|
|
|
+ lightStartBrightness = other.lightStartBrightness;
|
|
|
+ lightEndBrightness = other.lightEndBrightness;
|
|
|
+ lightNormalOffset = other.lightNormalOffset;
|
|
|
+ // Note - Explosion calls mDataBlock->getName() in warning messages but
|
|
|
+ // that should be safe.
|
|
|
+}
|
|
|
+
|
|
|
+ExplosionData::~ExplosionData()
|
|
|
+{
|
|
|
+ if (!isTempClone())
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (soundProfile && soundProfile->isTempClone())
|
|
|
+ {
|
|
|
+ delete soundProfile;
|
|
|
+ soundProfile = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // particleEmitter, emitterList[*], debrisList[*], explosionList[*] will delete themselves
|
|
|
+
|
|
|
+#ifdef TRACK_EXPLOSION_DATA_CLONES
|
|
|
+ if (explosion_data_clones > 0)
|
|
|
+ {
|
|
|
+ explosion_data_clones--;
|
|
|
+ if (explosion_data_clones == 0)
|
|
|
+ Con::errorf("ExplosionData -- Clones eliminated!");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ Con::errorf("ExplosionData -- Too many clones deleted!");
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+ExplosionData* ExplosionData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
|
|
|
+{
|
|
|
+ if (!owner || getSubstitutionCount() == 0)
|
|
|
+ return this;
|
|
|
+
|
|
|
+ ExplosionData* sub_explosion_db = new ExplosionData(*this, true);
|
|
|
+ performSubstitutions(sub_explosion_db, owner, index);
|
|
|
+
|
|
|
+ return sub_explosion_db;
|
|
|
+}
|
|
|
+
|
|
|
void ExplosionData::initPersistFields()
|
|
|
{
|
|
|
addField( "explosionShape", TypeShapeFilename, Offset(dtsFileName, ExplosionData),
|
|
@@ -818,6 +920,10 @@ Explosion::Explosion()
|
|
|
mLight = LIGHTMGR->createLightInfo();
|
|
|
|
|
|
mNetFlags.set( IsGhost );
|
|
|
+ ss_object = 0;
|
|
|
+ ss_index = 0;
|
|
|
+ mDataBlock = 0;
|
|
|
+ soundProfile_clone = 0;
|
|
|
}
|
|
|
|
|
|
Explosion::~Explosion()
|
|
@@ -830,6 +936,18 @@ Explosion::~Explosion()
|
|
|
}
|
|
|
|
|
|
SAFE_DELETE(mLight);
|
|
|
+
|
|
|
+ if (soundProfile_clone)
|
|
|
+ {
|
|
|
+ delete soundProfile_clone;
|
|
|
+ soundProfile_clone = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mDataBlock && mDataBlock->isTempClone())
|
|
|
+ {
|
|
|
+ delete mDataBlock;
|
|
|
+ mDataBlock = 0;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
@@ -988,6 +1106,8 @@ bool Explosion::onNewDataBlock( GameBaseData *dptr, bool reload )
|
|
|
if (!mDataBlock || !Parent::onNewDataBlock( dptr, reload ))
|
|
|
return false;
|
|
|
|
|
|
+ if (mDataBlock->isTempClone())
|
|
|
+ return true;
|
|
|
scriptOnNewDataBlock();
|
|
|
return true;
|
|
|
}
|
|
@@ -1200,7 +1320,8 @@ void Explosion::launchDebris( Point3F &axis )
|
|
|
launchDir *= debrisVel;
|
|
|
|
|
|
Debris *debris = new Debris;
|
|
|
- debris->setDataBlock( mDataBlock->debrisList[0] );
|
|
|
+ debris->setSubstitutionData(ss_object, ss_index);
|
|
|
+ debris->setDataBlock(mDataBlock->debrisList[0]->cloneAndPerformSubstitutions(ss_object, ss_index));
|
|
|
debris->setTransform( getTransform() );
|
|
|
debris->init( pos, launchDir );
|
|
|
|
|
@@ -1228,7 +1349,8 @@ void Explosion::spawnSubExplosions()
|
|
|
{
|
|
|
MatrixF trans = getTransform();
|
|
|
Explosion* pExplosion = new Explosion;
|
|
|
- pExplosion->setDataBlock( mDataBlock->explosionList[i] );
|
|
|
+ pExplosion->setSubstitutionData(ss_object, ss_index);
|
|
|
+ pExplosion->setDataBlock(mDataBlock->explosionList[i]->cloneAndPerformSubstitutions(ss_object, ss_index));
|
|
|
pExplosion->setTransform( trans );
|
|
|
pExplosion->setInitialState( trans.getPosition(), mInitialNormal, 1);
|
|
|
if (!pExplosion->registerObject())
|
|
@@ -1266,12 +1388,18 @@ bool Explosion::explode()
|
|
|
resetWorldBox();
|
|
|
}
|
|
|
|
|
|
- if (mDataBlock->soundProfile)
|
|
|
- SFX->playOnce( mDataBlock->soundProfile, &getTransform() );
|
|
|
+ SFXProfile* sound_prof = dynamic_cast<SFXProfile*>(mDataBlock->soundProfile);
|
|
|
+ if (sound_prof)
|
|
|
+ {
|
|
|
+ soundProfile_clone = sound_prof->cloneAndPerformSubstitutions(ss_object, ss_index);
|
|
|
+ SFX->playOnce( soundProfile_clone, &getTransform() );
|
|
|
+ if (!soundProfile_clone->isTempClone())
|
|
|
+ soundProfile_clone = 0;
|
|
|
+ }
|
|
|
|
|
|
if (mDataBlock->particleEmitter) {
|
|
|
mMainEmitter = new ParticleEmitter;
|
|
|
- mMainEmitter->setDataBlock(mDataBlock->particleEmitter);
|
|
|
+ mMainEmitter->setDataBlock(mDataBlock->particleEmitter->cloneAndPerformSubstitutions(ss_object, ss_index));
|
|
|
mMainEmitter->registerObject();
|
|
|
|
|
|
mMainEmitter->emitParticles(getPosition(), mInitialNormal, mDataBlock->particleRadius,
|
|
@@ -1283,7 +1411,7 @@ bool Explosion::explode()
|
|
|
if( mDataBlock->emitterList[i] != NULL )
|
|
|
{
|
|
|
ParticleEmitter * pEmitter = new ParticleEmitter;
|
|
|
- pEmitter->setDataBlock( mDataBlock->emitterList[i] );
|
|
|
+ pEmitter->setDataBlock(mDataBlock->emitterList[i]->cloneAndPerformSubstitutions(ss_object, ss_index));
|
|
|
if( !pEmitter->registerObject() )
|
|
|
{
|
|
|
Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() );
|