Merge branch 'Preview4_0' of https://github.com/TorqueGameEngines/Torque3D into UpdatedProjectImporter

This commit is contained in:
JeffR 2022-01-20 17:48:17 -06:00
commit 1952820ef2
14 changed files with 657 additions and 312 deletions

View file

@ -218,6 +218,9 @@ bool SoundAsset::loadSound()
{
Con::errorf("SoundAsset::initializeAsset: Attempted to load file %s but it was not valid!", mSoundFile);
mLoadedState = BadFileReference;
mSFXProfile.setDescription(NULL);
mSFXProfile.setSoundFileName(StringTable->insert(StringTable->EmptyString()));
mSFXProfile.setPreload(false);
return false;
}
else
@ -257,7 +260,7 @@ StringTableEntry SoundAsset::getAssetIdByFileName(StringTableEntry fileName)
if (fileName == StringTable->EmptyString())
return StringTable->EmptyString();
StringTableEntry materialAssetId = "";
StringTableEntry soundAssetId = StringTable->EmptyString();
AssetQuery query;
U32 foundCount = AssetDatabase.findAssetType(&query, "SoundAsset");
@ -268,7 +271,7 @@ StringTableEntry SoundAsset::getAssetIdByFileName(StringTableEntry fileName)
SoundAsset* soundAsset = AssetDatabase.acquireAsset<SoundAsset>(query.mAssetList[i]);
if (soundAsset && soundAsset->getSoundPath() == fileName)
{
materialAssetId = soundAsset->getAssetId();
soundAssetId = soundAsset->getAssetId();
AssetDatabase.releaseAsset(query.mAssetList[i]);
break;
}
@ -276,7 +279,7 @@ StringTableEntry SoundAsset::getAssetIdByFileName(StringTableEntry fileName)
}
}
return materialAssetId;
return soundAssetId;
}
U32 SoundAsset::getAssetById(StringTableEntry assetId, AssetPtr<SoundAsset>* soundAsset)
@ -330,8 +333,8 @@ DefineEngineMethod(SoundAsset, getSoundPath, const char*, (), , "")
}
DefineEngineMethod(SoundAsset, playSound, S32, (Point3F position), (Point3F::Zero),
"Gets the number of materials for this shape asset.\n"
"@return Material count.\n")
"Plays the sound for this asset.\n"
"@return (sound plays).\n")
{
if (object->getSfxProfile())
{

View file

@ -859,9 +859,6 @@ bool ExplosionData::preload(bool server, String &errorStr)
if (Parent::preload(server, errorStr) == false)
return false;
if (!server && !getSoundProfile())
return false;
if( !server )
{
@ -870,12 +867,18 @@ bool ExplosionData::preload(bool server, String &errorStr)
_setSound(getSound());
if (!getSoundProfile())
{
Con::errorf(ConsoleLogEntry::General, "SplashData::preload: Cant get an sfxProfile for splash.");
return false;
}
}
if (!particleEmitter && particleEmitterId != 0)
if (Sim::findObject(particleEmitterId, particleEmitter) == false)
{
Con::errorf(ConsoleLogEntry::General, "Error, unable to load particle emitter for explosion datablock");
return false;
}
}
if (mExplosionShapeAsset.notNull()) {

View file

@ -1562,33 +1562,50 @@ void GameConnection::packetDropped(PacketNotify *note)
//----------------------------------------------------------------------------
void GameConnection::play2D(SFXProfile* profile)
void GameConnection::play2D(StringTableEntry assetId)
{
postNetEvent(new Sim2DAudioEvent(profile));
if (AssetDatabase.isDeclaredAsset(assetId))
{
AssetPtr<SoundAsset> tempSoundAsset;
tempSoundAsset = assetId;
postNetEvent(new SimSoundAssetEvent(tempSoundAsset));
}
}
void GameConnection::play3D(SFXProfile* profile, const MatrixF *transform)
void GameConnection::play3D(StringTableEntry assetId, const MatrixF *transform)
{
if ( !transform )
play2D(profile);
play2D(assetId);
else if ( !mControlObject )
postNetEvent(new Sim3DAudioEvent(profile,transform));
else
if (AssetDatabase.isDeclaredAsset(assetId))
{
// TODO: Maybe improve this to account for the duration
// of the sound effect and if the control object can get
// into hearing range within time?
// Only post the event if it's within audible range
// of the control object.
Point3F ear,pos;
transform->getColumn(3,&pos);
mControlObject->getTransform().getColumn(3,&ear);
if ((ear - pos).len() < profile->getDescription()->mMaxDistance)
postNetEvent(new Sim3DAudioEvent(profile,transform));
}
AssetPtr<SoundAsset> tempSoundAsset;
tempSoundAsset = assetId;
if (!mControlObject)
postNetEvent(new SimSoundAssetEvent(tempSoundAsset, transform));
else
{
// TODO: Maybe improve this to account for the duration
// of the sound effect and if the control object can get
// into hearing range within time?
// Only post the event if it's within audible range
// of the control object.
tempSoundAsset->getSfxDescription();
Point3F ear, pos;
transform->getColumn(3, &pos);
mControlObject->getTransform().getColumn(3, &ear);
if ((ear - pos).len() < tempSoundAsset->getSfxDescription()->mMaxDistance)
postNetEvent(new SimSoundAssetEvent(tempSoundAsset, transform));
}
}
}
void GameConnection::doneScopingScene()
@ -2010,49 +2027,49 @@ DefineEngineMethod( GameConnection, isControlObjectRotDampedCamera, bool, (),,
return object->isControlObjectRotDampedCamera();
}
DefineEngineMethod( GameConnection, play2D, bool, (SFXProfile* profile),,
DefineEngineMethod( GameConnection, play2D, bool, (StringTableEntry assetId),,
"@brief Used on the server to play a 2D sound that is not attached to any object.\n\n"
"@param profile The SFXProfile that defines the sound to play.\n\n"
"@param assetID The SoundAsset ID that defines the sound to play.\n"
"@tsexample\n"
"function ServerPlay2D(%profile)\n"
"function ServerPlay2D(%assetId)\n"
"{\n"
" // Play the given sound profile on every client.\n"
" // Play the given sound asset on every client.\n"
" // The sounds will be transmitted as an event, not attached to any object.\n"
" for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)\n"
" ClientGroup.getObject(%idx).play2D(%profile);\n"
" ClientGroup.getObject(%idx).play2D(%assetId);\n"
"}\n"
"@endtsexample\n\n")
{
if(!profile)
if(assetId == StringTable->EmptyString())
return false;
object->play2D(profile);
object->play2D(assetId);
return true;
}
DefineEngineMethod( GameConnection, play3D, bool, (SFXProfile* profile, TransformF location),,
DefineEngineMethod( GameConnection, play3D, bool, (StringTableEntry assetId, TransformF location),,
"@brief Used on the server to play a 3D sound that is not attached to any object.\n\n"
"@param profile The SFXProfile that defines the sound to play.\n"
"@param assetID The SoundAsset ID that defines the sound to play.\n"
"@param location The position and orientation of the 3D sound given in the form of \"x y z ax ay az aa\".\n\n"
"@tsexample\n"
"function ServerPlay3D(%profile,%transform)\n"
"function ServerPlay3D(%assetId,%transform)\n"
"{\n"
" // Play the given sound profile at the given position on every client\n"
" // Play the given sound asset at the given position on every client\n"
" // The sound will be transmitted as an event, not attached to any object.\n"
" for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)\n"
" ClientGroup.getObject(%idx).play3D(%profile,%transform);\n"
" ClientGroup.getObject(%idx).play3D(%assetID,%transform);\n"
"}\n"
"@endtsexample\n\n")
{
if(!profile)
if(assetId == StringTable->EmptyString())
return false;
MatrixF mat = location.getMatrix();
object->play3D(profile,&mat);
object->play3D(assetId,&mat);
return true;
}

View file

@ -352,8 +352,8 @@ public:
/// @name Sound
/// @{
void play2D(SFXProfile *profile);
void play3D(SFXProfile *profile, const MatrixF *transform);
void play2D(StringTableEntry assetId);
void play3D(StringTableEntry assetId, const MatrixF *transform);
/// @}
/// @name Misc.

View file

@ -47,6 +47,7 @@
//--------------------------------------------------------------------------
IMPLEMENT_CO_CLIENTEVENT_V1(SimDataBlockEvent);
IMPLEMENT_CO_CLIENTEVENT_V1(SimSoundAssetEvent);
IMPLEMENT_CO_CLIENTEVENT_V1(Sim2DAudioEvent);
IMPLEMENT_CO_CLIENTEVENT_V1(Sim3DAudioEvent);
IMPLEMENT_CO_CLIENTEVENT_V1(SetMissionCRCEvent);
@ -293,6 +294,104 @@ void SimDataBlockEvent::process(NetConnection *cptr)
//----------------------------------------------------------------------------
static F32 SoundPosAccuracy = 0.5;
static S32 SoundRotBits = 8;
SimSoundAssetEvent::SimSoundAssetEvent(AssetPtr<SoundAsset> asset, const MatrixF* mat)
{
// cant get here unless the asset is declared.
mAsset = asset;
if (mat)
mTransform = *mat;
}
void SimSoundAssetEvent::pack(NetConnection* con, BitStream* stream)
{
NetStringHandle assetIdStr = mAsset->getAssetId();
con->packNetStringHandleU(stream, assetIdStr);
// only stream if this is a 3d sound asset.
if (mAsset->is3D())
{
SFXDescription* ad = mAsset->getSfxDescription();
if (stream->writeFlag(ad->mConeInsideAngle || ad->mConeOutsideAngle))
{
QuatF q(mTransform);
q.normalize();
// LH - we can get a valid quat that's very slightly over 1 in and so
// this fails (barely) check against zero. So use some error-
AssertFatal((1.0 - ((q.x * q.x) + (q.y * q.y) + (q.z * q.z))) >= (0.0 - 0.001),
"QuatF::normalize() is broken in Sim3DAudioEvent");
stream->writeSignedFloat(q.x, SoundRotBits);
stream->writeSignedFloat(q.y, SoundRotBits);
stream->writeSignedFloat(q.z, SoundRotBits);
stream->writeFlag(q.w < 0.0);
}
Point3F pos;
mTransform.getColumn(3, &pos);
stream->writeCompressedPoint(pos, SoundPosAccuracy);
}
}
void SimSoundAssetEvent::write(NetConnection* con, BitStream* stream)
{
// Just do the normal pack...
pack(con, stream);
}
void SimSoundAssetEvent::unpack(NetConnection* con, BitStream* stream)
{
StringTableEntry temp = StringTable->insert(con->unpackNetStringHandleU(stream).getString());
if (AssetDatabase.isDeclaredAsset(temp))
{
AssetPtr<SoundAsset> tempSoundAsset;
tempSoundAsset = temp;
mAsset = temp;
}
if (mAsset->is3D())
{
if (stream->readFlag()) {
QuatF q;
q.x = stream->readSignedFloat(SoundRotBits);
q.y = stream->readSignedFloat(SoundRotBits);
q.z = stream->readSignedFloat(SoundRotBits);
F32 value = ((q.x * q.x) + (q.y * q.y) + (q.z * q.z));
// #ifdef __linux
// Hmm, this should never happen, but it does...
if (value > 1.f)
value = 1.f;
// #endif
q.w = mSqrt(1.f - value);
if (stream->readFlag())
q.w = -q.w;
q.setMatrix(&mTransform);
}
else
mTransform.identity();
Point3F pos;
stream->readCompressedPoint(&pos, SoundPosAccuracy);
mTransform.setColumn(3, pos);
}
}
void SimSoundAssetEvent::process(NetConnection* con)
{
if (mAsset->is3D())
SFX->playOnce(mAsset->getSfxProfile(), &mTransform);
else
SFX->playOnce(mAsset->getSfxProfile());
}
Sim2DAudioEvent::Sim2DAudioEvent(SFXProfile *profile)
{
@ -321,11 +420,6 @@ void Sim2DAudioEvent::process(NetConnection *)
SFX->playOnce( mProfile );
}
//----------------------------------------------------------------------------
static F32 SoundPosAccuracy = 0.5;
static S32 SoundRotBits = 8;
Sim3DAudioEvent::Sim3DAudioEvent(SFXProfile *profile,const MatrixF* mat)
{
mProfile = profile;

View file

@ -39,6 +39,9 @@
#include "core/stream/bitStream.h"
#endif
#include "T3D/assets/SoundAsset.h"
class QuitEvent : public SimEvent
{
@ -102,6 +105,23 @@ class SimDataBlockEvent : public NetEvent
DECLARE_CATEGORY( "Game Networking" );
};
class SimSoundAssetEvent : public NetEvent
{
private:
AssetPtr<SoundAsset> mAsset;
MatrixF mTransform;
public:
typedef NetEvent Parent;
SimSoundAssetEvent(AssetPtr<SoundAsset> asset = NULL, const MatrixF* mat = NULL);
void pack(NetConnection*, BitStream* bstream);
void write(NetConnection*, BitStream* bstream);
void unpack(NetConnection*, BitStream* bstream);
void process(NetConnection*);
DECLARE_CONOBJECT(SimSoundAssetEvent);
};
class Sim2DAudioEvent: public NetEvent
{
private:

View file

@ -1009,7 +1009,7 @@ ShapeBase::ShapeBase()
for (i = 0; i < MaxSoundThreads; i++) {
mSoundThread[i].play = false;
mSoundThread[i].profile = 0;
mSoundThread[i].asset = 0;
mSoundThread[i].sound = 0;
}
@ -2233,24 +2233,30 @@ void ShapeBase::applyImpulse(const Point3F&,const VectorF&)
//----------------------------------------------------------------------------
void ShapeBase::playAudio(U32 slot,SFXTrack* profile)
void ShapeBase::playAudio(U32 slot, StringTableEntry assetId)
{
AssertFatal( slot < MaxSoundThreads, "ShapeBase::playAudio() bad slot index" );
Sound& st = mSoundThread[slot];
if( profile && ( !st.play || st.profile != profile ) )
if (AssetDatabase.isDeclaredAsset(assetId))
{
AssetPtr<SoundAsset> tempSoundAsset;
tempSoundAsset = assetId;
SoundThread& st = mSoundThread[slot];
if (tempSoundAsset && (!st.play || st.asset != tempSoundAsset))
{
setMaskBits(SoundMaskN << slot);
st.play = true;
st.profile = profile;
st.asset = tempSoundAsset;
updateAudioState(st);
}
}
}
void ShapeBase::stopAudio(U32 slot)
{
AssertFatal( slot < MaxSoundThreads, "ShapeBase::stopAudio() bad slot index" );
Sound& st = mSoundThread[slot];
SoundThread& st = mSoundThread[slot];
if ( st.play )
{
st.play = false;
@ -2263,7 +2269,7 @@ void ShapeBase::updateServerAudio()
{
// Timeout non-looping sounds
for (S32 i = 0; i < MaxSoundThreads; i++) {
Sound& st = mSoundThread[i];
SoundThread& st = mSoundThread[i];
if (st.play && st.timeout && st.timeout < Sim::getCurrentTime()) {
clearMaskBits(SoundMaskN << i);
st.play = false;
@ -2271,17 +2277,18 @@ void ShapeBase::updateServerAudio()
}
}
void ShapeBase::updateAudioState(Sound& st)
void ShapeBase::updateAudioState(SoundThread& st)
{
SFX_DELETE( st.sound );
if ( st.play && st.profile )
if ( st.play && st.asset )
{
if ( isGhost() )
{
if ( Sim::findObject( SimObjectId((uintptr_t)st.profile), st.profile ) )
// if asset is valid, play
if (st.asset->isAssetValid() )
{
st.sound = SFX->createSource( st.profile, &getTransform() );
st.sound = SFX->createSource( st.asset->getSfxProfile() , &getTransform() );
if ( st.sound )
st.sound->play();
}
@ -2292,12 +2299,17 @@ void ShapeBase::updateAudioState(Sound& st)
{
// Non-looping sounds timeout on the server
st.timeout = 0;
if ( !st.profile->getDescription()->mIsLooping )
if ( !st.asset->getSfxDescription()->mIsLooping )
st.timeout = Sim::getCurrentTime() + sAudioTimeout;
}
}
else
{
// st.sound was not stopped before. If this causes issues remove.
st.play = false;
if (st.sound)
st.sound->stop();
}
}
void ShapeBase::updateAudioPos()
@ -3122,13 +3134,15 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
if (stream->writeFlag(mask & SoundMask)) {
for (S32 i = 0; i < MaxSoundThreads; i++) {
Sound& st = mSoundThread[i];
SoundThread& st = mSoundThread[i];
if (stream->writeFlag(mask & (SoundMaskN << i)))
if (stream->writeFlag(st.play))
stream->writeRangedU32(st.profile->getId(),DataBlockObjectIdFirst,
DataBlockObjectIdLast);
{
NetStringHandle assetIdStr = st.asset->getAssetId();
con->packNetStringHandleU(stream, assetIdStr);
}
}
}
if (stream->writeFlag(mask & ImageMask)) {
for (S32 i = 0; i < MaxMountedImages; i++)
@ -3242,12 +3256,18 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream)
{
if ( stream->readFlag() )
{
Sound& st = mSoundThread[i];
SoundThread& st = mSoundThread[i];
st.play = stream->readFlag();
if ( st.play )
{
st.profile = (SFXTrack*)(uintptr_t)stream->readRangedU32( DataBlockObjectIdFirst,
DataBlockObjectIdLast );
StringTableEntry temp = StringTable->insert(con->unpackNetStringHandleU(stream).getString());
if (AssetDatabase.isDeclaredAsset(temp))
{
AssetPtr<SoundAsset> tempSoundAsset;
tempSoundAsset = temp;
st.asset = temp;
}
}
if ( isProperlyAdded() )
@ -3777,7 +3797,7 @@ DefineEngineMethod( ShapeBase, isHidden, bool, (),,
}
//----------------------------------------------------------------------------
DefineEngineMethod( ShapeBase, playAudio, bool, ( S32 slot, SFXTrack* track ),,
DefineEngineMethod( ShapeBase, playAudio, bool, ( S32 slot, StringTableEntry assetId),,
"@brief Attach a sound to this shape and start playing it.\n\n"
"@param slot Audio slot index for the sound (valid range is 0 - 3)\n" // 3 = ShapeBase::MaxSoundThreads-1
@ -3786,8 +3806,8 @@ DefineEngineMethod( ShapeBase, playAudio, bool, ( S32 slot, SFXTrack* track ),,
"@see stopAudio()\n")
{
if (track && slot >= 0 && slot < ShapeBase::MaxSoundThreads) {
object->playAudio(slot,track);
if (assetId && slot >= 0 && slot < ShapeBase::MaxSoundThreads) {
object->playAudio(slot, assetId);
return true;
}
return false;

View file

@ -265,6 +265,7 @@ struct ShapeBaseImageData: public GameBaseData {
F32 emitterTime; ///<
S32 emitterNode[MaxShapes]; ///< Node ID on the shape to emit from
SoundAsset* sound;
SFXTrack* soundTrack; ///<Holdover for special, non-asset cases like SFXPlaylists
};
/// @name State Data
/// Individual state data used to initialize struct array
@ -744,13 +745,13 @@ protected:
/// @name Scripted Sound
/// @{
struct Sound {
struct SoundThread {
bool play; ///< Are we playing this sound?
SimTime timeout; ///< Time until we stop playing this sound.
SFXTrack* profile; ///< Profile on server
AssetPtr<SoundAsset> asset; ///< Asset on server
SFXSource* sound; ///< Sound on client
};
Sound mSoundThread[MaxSoundThreads];
SoundThread mSoundThread[MaxSoundThreads];
/// @}
/// @name Scripted Animation Threads
@ -1114,7 +1115,7 @@ protected:
/// Updates the audio state of the supplied sound
/// @param st Sound
void updateAudioState(Sound& st);
void updateAudioState(SoundThread& st);
/// Recalculates the spacial sound based on the current position of the object
/// emitting the sound.
@ -1328,9 +1329,7 @@ public:
/// Plays an audio sound from a mounted object
/// @param slot Mount slot ID
/// @param track Audio track to play
void playAudio(U32 slot,SFXTrack* track);
void playAudio( U32 slot, SFXProfile* profile ) { playAudio( slot, ( SFXTrack* ) profile ); }
void playAudio(U32 slot, StringTableEntry assetId);
/// Stops audio from a mounted object
/// @param slot Mount slot ID

View file

@ -133,6 +133,7 @@ ShapeBaseImageData::StateData::StateData()
spin = IgnoreSpin;
recoil = NoRecoil;
sound = NULL;
soundTrack = NULL;
emitter = NULL;
shapeSequence = NULL;
shapeSequenceScale = true;
@ -372,6 +373,19 @@ bool ShapeBaseImageData::onAdd()
//_setstateSound(getstateSound(i),i);
s.sound = getstateSoundAsset(i);
if (s.sound == NULL && mstateSoundName[i] != StringTable->EmptyString())
{
//ok, so we've got some sort of special-case here like a fallback or SFXPlaylist. So do the hook-up now
SFXTrack* sndTrack;
if (!Sim::findObject(mstateSoundName[i], sndTrack))
{
Con::errorf("ShapeBaseImageData::onAdd() - attempted to find sound %s but failed!", mstateSoundName[i]);
}
else
{
s.soundTrack = sndTrack;
}
}
s.script = stateScript[i];
s.emitter = stateEmitter[i];
s.emitterTime = stateEmitterTime[i];
@ -2580,7 +2594,7 @@ bool ShapeBase::hasImageState(U32 imageSlot, const char* state)
return false;
}
void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
void ShapeBase::setImageState(U32 imageSlot, U32 newState, bool force)
{
if (!mMountedImageList[imageSlot].dataBlock)
return;
@ -2611,12 +2625,12 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
// Eject shell casing on every state change (client side only)
ShapeBaseImageData::StateData& nextStateData = image.dataBlock->state[newState];
if (isGhost() && nextStateData.ejectShell) {
ejectShellCasing( imageSlot );
ejectShellCasing(imageSlot);
}
// Shake camera on client.
if (isGhost() && nextStateData.fire && image.dataBlock->shakeCamera) {
shakeCamera( imageSlot );
shakeCamera(imageSlot);
}
// Server must animate the shape if it is a firestate...
@ -2632,12 +2646,12 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
if (!force && image.state == &image.dataBlock->state[newState]) {
image.delayTime = image.state->timeoutValue;
if (image.state->script && !isGhost())
scriptCallback(imageSlot,image.state->script);
scriptCallback(imageSlot, image.state->script);
// If this is a flash sequence, we need to select a new position for the
// animation if we're returning to that state...
F32 randomPos = Platform::getRandom();
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
for (U32 i = 0; i < ShapeBaseImageData::MaxShapes; ++i)
{
if (!image.dataBlock->shapeIsValid[i] || (i != imageShapeIndex && !image.doAnimateAllShapes))
continue;
@ -2665,7 +2679,7 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
// Mount pending images
if (image.nextImage != InvalidImagePtr && stateData.allowImageChange) {
setImage(imageSlot,image.nextImage,image.nextSkinNameHandle,image.nextLoaded);
setImage(imageSlot, image.nextImage, image.nextSkinNameHandle, image.nextLoaded);
return;
}
@ -2673,16 +2687,16 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
// (the first key frame should be it's off state).
// We need to do this across all image shapes to make sure we have no hold overs when switching
// rendering shapes while in the middle of a state change.
for (U32 i=0; i<ShapeBaseImageData::MaxShapes; ++i)
for (U32 i = 0; i < ShapeBaseImageData::MaxShapes; ++i)
{
// If we are to do a sequence transition then we need to keep the previous animThread active
if (image.animThread[i] && image.animThread[i]->getSequence()->isCyclic() && (stateData.sequenceNeverTransition || !(stateData.sequenceTransitionIn || lastState->sequenceTransitionOut))) {
image.shapeInstance[i]->setPos(image.animThread[i],0);
image.shapeInstance[i]->setTimeScale(image.animThread[i],0);
image.shapeInstance[i]->setPos(image.animThread[i], 0);
image.shapeInstance[i]->setTimeScale(image.animThread[i], 0);
}
if (image.flashThread[i]) {
image.shapeInstance[i]->setPos(image.flashThread[i],0);
image.shapeInstance[i]->setTimeScale(image.flashThread[i],0);
image.shapeInstance[i]->setPos(image.flashThread[i], 0);
image.shapeInstance[i]->setTimeScale(image.flashThread[i], 0);
}
}
@ -2695,10 +2709,10 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
if (image.delayTime <= 0 || !stateData.waitForTimeout)
{
if ((ns = stateData.transition.loaded[image.loaded]) != -1) {
setImageState(imageSlot,ns);
setImageState(imageSlot, ns);
return;
}
for (U32 i=0; i<ShapeBaseImageData::MaxGenericTriggers; ++i)
for (U32 i = 0; i < ShapeBaseImageData::MaxGenericTriggers; ++i)
{
if ((ns = stateData.transition.genericTrigger[i][image.genericTrigger[i]]) != -1) {
setImageState(imageSlot, ns);
@ -2707,7 +2721,7 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
}
//if (!imageData.usesEnergy)
if ((ns = stateData.transition.ammo[image.ammo]) != -1) {
setImageState(imageSlot,ns);
setImageState(imageSlot, ns);
return;
}
if ((ns = stateData.transition.target[image.target]) != -1) {
@ -2723,11 +2737,11 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
return;
}
if ((ns = stateData.transition.trigger[image.triggerDown]) != -1) {
setImageState(imageSlot,ns);
setImageState(imageSlot, ns);
return;
}
if ((ns = stateData.transition.altTrigger[image.altTriggerDown]) != -1) {
setImageState(imageSlot,ns);
setImageState(imageSlot, ns);
return;
}
}
@ -2752,7 +2766,7 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
// Apply recoil
if (stateData.recoil != ShapeBaseImageData::StateData::NoRecoil)
onImageRecoil(imageSlot,stateData.recoil);
onImageRecoil(imageSlot, stateData.recoil);
// Apply image state animation on mounting shape
if (stateData.shapeSequence && stateData.shapeSequence[0])
@ -2764,17 +2778,25 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
// lastState does not return an id for the prev state so we keep track of it.
if (lastState->sound && lastState->sound->getSfxProfile()->getDescription()->mIsLooping)
{
for(Vector<SFXSource*>::iterator i = image.mSoundSources.begin(); i != image.mSoundSources.end(); i++)
for (Vector<SFXSource*>::iterator i = image.mSoundSources.begin(); i != image.mSoundSources.end(); i++)
SFX_DELETE((*i));
image.mSoundSources.clear();
}
// Play sound
if( stateData.sound && isGhost() )
if (isGhost())
{
if (stateData.sound)
{
const Point3F& velocity = getVelocity();
image.addSoundSource(SFX->createSource(stateData.sound->getSfxProfile(), &getRenderTransform(), &velocity ));
image.addSoundSource(SFX->createSource(stateData.sound->getSfxProfile(), &getRenderTransform(), &velocity));
}
if (stateData.soundTrack)
{
const Point3F& velocity = getVelocity();
image.addSoundSource(SFX->createSource(stateData.soundTrack, &getRenderTransform(), &velocity));
}
}
// Play animation