diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp index b60fd1af69..95738b18a8 100644 --- a/source/graphics/Model.cpp +++ b/source/graphics/Model.cpp @@ -251,7 +251,7 @@ const CBoundingBoxAligned CModel::GetObjectSelectionBoundsRec() ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // BuildAnimation: load raw animation frame animation from given file, and build a // animation specific to this model -CSkeletonAnim* CModel::BuildAnimation(const VfsPath& pathname, const CStr& name, float speed, float actionpos, float actionpos2) +CSkeletonAnim* CModel::BuildAnimation(const VfsPath& pathname, const CStr& name, float speed, float actionpos, float actionpos2, float soundpos) { CSkeletonAnimDef* def = m_SkeletonAnimManager.GetAnimation(pathname); if (!def) @@ -272,6 +272,11 @@ CSkeletonAnim* CModel::BuildAnimation(const VfsPath& pathname, const CStr& name, else anim->m_ActionPos2 = actionpos2 * anim->m_AnimDef->GetDuration(); + if (soundpos == -1.f) + anim->m_SoundPos = -1.f; + else + anim->m_SoundPos = soundpos * anim->m_AnimDef->GetDuration(); + anim->m_ObjectBounds.SetEmpty(); InvalidateBounds(); diff --git a/source/graphics/Model.h b/source/graphics/Model.h index 77e62241e0..6de1fca8f1 100644 --- a/source/graphics/Model.h +++ b/source/graphics/Model.h @@ -197,9 +197,10 @@ public: * @param speed animation speed as a factor of the default animation speed * @param actionpos offset of 'action' event, in range [0, 1] * @param actionpos2 offset of 'action2' event, in range [0, 1] + * @param sound offset of 'sound' event, in range [0, 1] * @return new animation, or NULL on error */ - CSkeletonAnim* BuildAnimation(const VfsPath& pathname, const CStr& name, float speed, float actionpos, float actionpos2); + CSkeletonAnim* BuildAnimation(const VfsPath& pathname, const CStr& name, float speed, float actionpos, float actionpos2, float soundpos); /** * Add a prop to the model on the given point. diff --git a/source/graphics/ObjectBase.cpp b/source/graphics/ObjectBase.cpp index 89bcb95c37..3cb2aae37f 100644 --- a/source/graphics/ObjectBase.cpp +++ b/source/graphics/ObjectBase.cpp @@ -71,6 +71,7 @@ bool CObjectBase::Load(const VfsPath& pathname) AT(speed); AT(event); AT(load); + AT(sound); AT(attachpoint); AT(actor); AT(frequency); @@ -222,6 +223,11 @@ bool CObjectBase::Load(const VfsPath& pathname) float pos = ae.Value.ToFloat(); anim.m_ActionPos2 = clamp(pos, 0.f, 1.f); } + else if (ae.Name == at_sound) + { + float pos = ae.Value.ToFloat(); + anim.m_SoundPos = clamp(pos, 0.f, 1.f); + } } currentVariant->m_Anims.push_back(anim); } diff --git a/source/graphics/ObjectBase.h b/source/graphics/ObjectBase.h index 6c5595bd7f..708551526e 100644 --- a/source/graphics/ObjectBase.h +++ b/source/graphics/ObjectBase.h @@ -39,8 +39,7 @@ public: struct Anim { // constructor - Anim() : m_Speed(1.f), m_ActionPos(-1.f), m_ActionPos2(-1.f) {} - + Anim() : m_Speed(1.f), m_ActionPos(-1.f), m_ActionPos2(-1.f), m_SoundPos(-1.f) {} // name of the animation - "Idle", "Run", etc CStr m_AnimName; // filename of the animation - manidle.psa, manrun.psa, etc @@ -51,6 +50,7 @@ public: // happens, or -1.0 if unspecified float m_ActionPos; float m_ActionPos2; + float m_SoundPos; }; struct Prop diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp index 5fd3598381..ac36f73d7e 100644 --- a/source/graphics/ObjectEntry.cpp +++ b/source/graphics/ObjectEntry.cpp @@ -164,7 +164,7 @@ bool CObjectEntry::BuildVariation(const std::vector >& selections if (! it->second.m_FileName.empty()) { - CSkeletonAnim* anim = model->BuildAnimation(it->second.m_FileName, name, it->second.m_Speed, it->second.m_ActionPos, it->second.m_ActionPos2); + CSkeletonAnim* anim = model->BuildAnimation(it->second.m_FileName, name, it->second.m_Speed, it->second.m_ActionPos, it->second.m_ActionPos2, it->second.m_SoundPos); if (anim) m_Animations.insert(std::make_pair(name, anim)); } @@ -179,6 +179,7 @@ bool CObjectEntry::BuildVariation(const std::vector >& selections anim->m_Speed = 0.f; anim->m_ActionPos = 0.f; anim->m_ActionPos2 = 0.f; + anim->m_SoundPos = 0.f; m_Animations.insert(std::make_pair("idle", anim)); // Ignore errors, since they're probably saying this is a non-animated model diff --git a/source/graphics/SkeletonAnim.h b/source/graphics/SkeletonAnim.h index b67eefb749..13f6d586e8 100644 --- a/source/graphics/SkeletonAnim.h +++ b/source/graphics/SkeletonAnim.h @@ -46,6 +46,7 @@ public: // ActionPos2 is used for loading projectile ammunition. float m_ActionPos; float m_ActionPos2; + float m_SoundPos; // object space bounds of the model when this animation is applied to it CBoundingBoxAligned m_ObjectBounds; }; diff --git a/source/graphics/UnitAnimation.cpp b/source/graphics/UnitAnimation.cpp index 98972d5c30..b20e6ba2f4 100644 --- a/source/graphics/UnitAnimation.cpp +++ b/source/graphics/UnitAnimation.cpp @@ -67,6 +67,7 @@ void CUnitAnimation::AddModel(CModel* model, const CObjectEntry* object) state.time = 0.f; state.pastLoadPos = false; state.pastActionPos = false; + state.pastSoundPos = false; m_AnimStates.push_back(state); @@ -157,8 +158,10 @@ void CUnitAnimation::Update(float time) float actionPos = it->anims[it->animIdx]->m_ActionPos; float loadPos = it->anims[it->animIdx]->m_ActionPos2; + float soundPos = it->anims[it->animIdx]->m_SoundPos; bool hasActionPos = (actionPos != -1.f); bool hasLoadPos = (loadPos != -1.f); + bool hasSoundPos = (soundPos != -1.f); // Find the current animation speed float speed; @@ -183,7 +186,7 @@ void CUnitAnimation::Update(float time) if (hasLoadPos) it->model->HideAmmoProp(); - if (!m_ActionSound.empty()) + if ( !hasSoundPos && !m_ActionSound.empty() ) { CmpPtr cmpSoundManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); if (cmpSoundManager) @@ -192,6 +195,17 @@ void CUnitAnimation::Update(float time) it->pastActionPos = true; } + if (hasSoundPos && !it->pastSoundPos && it->time + advance >= soundPos) + { + if (!m_ActionSound.empty() ) + { + CmpPtr cmpSoundManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); + if (cmpSoundManager) + cmpSoundManager->PlaySoundGroup(m_ActionSound, m_Entity); + } + + it->pastSoundPos = true; + } if (it->time + advance < duration) { @@ -219,6 +233,7 @@ void CUnitAnimation::Update(float time) it->pastActionPos = false; it->pastLoadPos = false; + it->pastSoundPos = false; it->model->UpdateTo(it->time); } diff --git a/source/graphics/UnitAnimation.h b/source/graphics/UnitAnimation.h index 21efd7c17c..eb831f4691 100644 --- a/source/graphics/UnitAnimation.h +++ b/source/graphics/UnitAnimation.h @@ -100,6 +100,7 @@ private: float time; bool pastLoadPos; bool pastActionPos; + bool pastSoundPos; }; std::vector m_AnimStates;