GameEffect.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Source/Effects/GameEffect.h>
  9. #include <AzCore/Console/IConsole.h>
  10. #if AZ_TRAIT_CLIENT
  11. # include <PopcornFX/PopcornFXBus.h>
  12. #endif
  13. namespace MultiplayerSample
  14. {
  15. AZ_CVAR(bool, cl_KillEffectOnRestart, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Controls whether or not to kill current effects on restart");
  16. void GameEffect::Reflect(AZ::ReflectContext* context)
  17. {
  18. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  19. if (serializeContext)
  20. {
  21. serializeContext->Class<GameEffect>()
  22. ->Version(1)
  23. ->Field("ParticleAsset", &GameEffect::m_particleAssetId)
  24. ->Field("AudioTrigger", &GameEffect::m_audioTrigger)
  25. ->Field("EffectOffset", &GameEffect::m_effectOffset);
  26. AZ::EditContext* editContext = serializeContext->GetEditContext();
  27. if (editContext)
  28. {
  29. editContext->Class<GameEffect>("GameEffect", "A single game effect, consisting of a particle effect and a sound trigger pair")
  30. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  31. ->DataElement(AZ::Edit::UIHandlers::Default, &GameEffect::m_particleAssetId, "ParticleAsset", "The particle effect to play upon effect trigger")
  32. #if AZ_TRAIT_CLIENT
  33. ->Attribute(AZ_CRC_CE("SupportedAssetTypes"), []() { return AZStd::vector<AZ::Data::AssetType>({ PopcornFX::AssetTypeId }); })
  34. #endif
  35. ->DataElement(AZ::Edit::UIHandlers::Default, &GameEffect::m_audioTrigger, "AudioTrigger", "The audio trigger name of the sound to play upon effect trigger")
  36. ->DataElement(AZ::Edit::UIHandlers::Default, &GameEffect::m_effectOffset, "EffectOffset", "The offset to apply when triggering an effect");
  37. }
  38. }
  39. }
  40. GameEffect::~GameEffect()
  41. {
  42. #if AZ_TRAIT_CLIENT
  43. if (m_popcornFx != nullptr)
  44. {
  45. m_popcornFx->DestroyEffect(m_emitter);
  46. m_emitter = nullptr;
  47. }
  48. if (m_audioSystem != nullptr)
  49. {
  50. m_audioTriggerId = INVALID_AUDIO_CONTROL_ID;
  51. if (m_audioProxy != nullptr)
  52. {
  53. m_audioSystem->RecycleAudioProxy(m_audioProxy);
  54. m_audioProxy = nullptr;
  55. }
  56. }
  57. #endif
  58. }
  59. void GameEffect::Initialize()
  60. {
  61. #if AZ_TRAIT_CLIENT
  62. m_popcornFx = PopcornFX::PopcornFXRequestBus::FindFirstHandler();
  63. m_audioSystem = AZ::Interface<Audio::IAudioSystem>::Get();
  64. if (m_popcornFx != nullptr)
  65. {
  66. const PopcornFX::SpawnParams params = PopcornFX::SpawnParams(true, false, AZ::Transform::CreateIdentity());
  67. m_emitter = m_popcornFx->SpawnEffectById(m_particleAssetId, params);
  68. }
  69. if (m_audioSystem != nullptr)
  70. {
  71. m_audioProxy = m_audioSystem->GetAudioProxy();
  72. m_audioProxy->Initialize(m_audioTrigger.c_str(), this);
  73. m_audioProxy->SetObstructionCalcType(Audio::ObstructionType::Ignore);
  74. m_audioTriggerId = m_audioSystem->GetAudioTriggerID(m_audioTrigger.c_str());
  75. }
  76. #endif
  77. }
  78. bool GameEffect::SetAttribute([[maybe_unused]] const char* attributeName, [[maybe_unused]] float value) const
  79. {
  80. #if AZ_TRAIT_CLIENT
  81. if (m_popcornFx != nullptr)
  82. {
  83. int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
  84. if (attrId >= 0)
  85. {
  86. return m_popcornFx->EffectSetAttributeAsFloat(m_emitter, attrId, value);
  87. }
  88. }
  89. #endif
  90. return false;
  91. }
  92. bool GameEffect::SetAttribute([[maybe_unused]] const char* attributeName, [[maybe_unused]] const AZ::Vector2& value) const
  93. {
  94. #if AZ_TRAIT_CLIENT
  95. if (m_popcornFx != nullptr)
  96. {
  97. int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
  98. if (attrId >= 0)
  99. {
  100. return m_popcornFx->EffectSetAttributeAsFloat2(m_emitter, attrId, value);
  101. }
  102. }
  103. #endif
  104. return false;
  105. }
  106. bool GameEffect::SetAttribute([[maybe_unused]] const char* attributeName, [[maybe_unused]] const AZ::Vector3& value) const
  107. {
  108. #if AZ_TRAIT_CLIENT
  109. if (m_popcornFx != nullptr)
  110. {
  111. int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
  112. if (attrId >= 0)
  113. {
  114. return m_popcornFx->EffectSetAttributeAsFloat3(m_emitter, attrId, value);
  115. }
  116. }
  117. #endif
  118. return false;
  119. }
  120. bool GameEffect::SetAttribute([[maybe_unused]] const char* attributeName, [[maybe_unused]] const AZ::Vector4& value) const
  121. {
  122. #if AZ_TRAIT_CLIENT
  123. if (m_popcornFx != nullptr)
  124. {
  125. int32_t attrId = m_popcornFx->EffectGetAttributeId(m_emitter, attributeName);
  126. if (attrId >= 0)
  127. {
  128. return m_popcornFx->EffectSetAttributeAsFloat4(m_emitter, attrId, value);
  129. }
  130. }
  131. #endif
  132. return false;
  133. }
  134. void GameEffect::TriggerEffect([[maybe_unused]] const AZ::Transform& transform) const
  135. {
  136. #if AZ_TRAIT_CLIENT
  137. const AZ::Vector3 offsetPosition = transform.TransformPoint(m_effectOffset);
  138. AZ::Transform transformOffset = transform;
  139. transformOffset.SetTranslation(offsetPosition);
  140. if (m_emitter != nullptr)
  141. {
  142. if (PopcornFX::PopcornFXRequests* popcornFx = PopcornFX::PopcornFXRequestBus::FindFirstHandler())
  143. {
  144. popcornFx->EffectSetTransform(m_emitter, transformOffset);
  145. popcornFx->EffectRestart(m_emitter, cl_KillEffectOnRestart);
  146. }
  147. }
  148. if ((m_audioProxy != nullptr) && (m_audioTriggerId != INVALID_AUDIO_CONTROL_ID))
  149. {
  150. m_audioProxy->SetPosition(offsetPosition);
  151. m_audioProxy->ExecuteTrigger(m_audioTriggerId);
  152. }
  153. #endif
  154. }
  155. const AZ::Vector3& GameEffect::GetEffectOffset() const
  156. {
  157. return m_effectOffset;
  158. }
  159. }