#pragma once #include "Runtime/RetroTypes.hpp" #include namespace metaforce { class CRandom16; class CStateManager; struct SCameraShakePoint { friend class CCameraShakeData; bool x0_useEnvelope = false; float x4_value = 0.f; float x8_magnitude = 0.f; float xc_attackTime = 0.f; float x10_sustainTime = 0.f; float x14_duration = 0.f; constexpr SCameraShakePoint() noexcept = default; constexpr SCameraShakePoint(bool useEnvelope, float attackTime, float sustainTime, float duration, float magnitude) noexcept : x0_useEnvelope(useEnvelope) , x8_magnitude(magnitude) , xc_attackTime(attackTime) , x10_sustainTime(sustainTime) , x14_duration(duration) {} [[nodiscard]] constexpr float GetValue() const noexcept { return x0_useEnvelope ? x8_magnitude : x4_value; } static SCameraShakePoint LoadCameraShakePoint(CInputStream& in); void Update(float curTime); }; class CCameraShakerComponent { friend class CCameraShakeData; bool x4_useModulation = false; SCameraShakePoint x8_am, x20_fm; float x38_value = 0.f; public: constexpr CCameraShakerComponent() noexcept = default; constexpr CCameraShakerComponent(bool useModulation, const SCameraShakePoint& am, const SCameraShakePoint& fm) noexcept : x4_useModulation(useModulation), x8_am(am), x20_fm(fm) {} static CCameraShakerComponent LoadNewCameraShakerComponent(CInputStream& in); void Update(float curTime, float duration, float distAtt); [[nodiscard]] constexpr float GetValue() const noexcept { return x38_value; } }; class CCameraShakeData { friend class CCameraManager; float x0_duration; float x4_curTime = 0.f; CCameraShakerComponent x8_shakerX; CCameraShakerComponent x44_shakerY; CCameraShakerComponent x80_shakerZ; u32 xbc_shakerId = 0; u32 xc0_flags; // 0x1: positional sfx zeus::CVector3f xc4_sfxPos; float xd0_sfxDist; public: static const CCameraShakeData skChargedShotCameraShakeData; constexpr CCameraShakeData() = default; constexpr CCameraShakeData(float duration, float sfxDist, u32 flags, const zeus::CVector3f& sfxPos, const CCameraShakerComponent& shaker1, const CCameraShakerComponent& shaker2, const CCameraShakerComponent& shaker3) noexcept : x0_duration(duration) , x8_shakerX(shaker1) , x44_shakerY(shaker2) , x80_shakerZ(shaker3) , xc0_flags(flags) , xc4_sfxPos(sfxPos) , xd0_sfxDist(sfxDist) {} constexpr CCameraShakeData(float duration, float magnitude) noexcept : CCameraShakeData( duration, 100.f, 0, zeus::skZero3f, CCameraShakerComponent{}, CCameraShakerComponent{}, CCameraShakerComponent{true, SCameraShakePoint{false, 0.25f * duration, 0.f, 0.75f * duration, magnitude}, SCameraShakePoint{true, 0.f, 0.f, 0.5f * duration, 2.f}}) {} explicit CCameraShakeData(CInputStream&); static constexpr CCameraShakeData BuildLandingCameraShakeData(float duration, float magnitude) noexcept { return { duration, 100.f, 0, zeus::skZero3f, CCameraShakerComponent{ true, SCameraShakePoint(false, 0.15f * duration, 0.f, 0.85f * duration, magnitude), SCameraShakePoint(true, 0.f, 0.f, 0.4f * duration, 1.5f), }, CCameraShakerComponent{}, CCameraShakerComponent{ true, SCameraShakePoint(false, 0.25f * duration, 0.f, 0.75f * duration, magnitude), SCameraShakePoint(true, 0.f, 0.f, 0.5f * duration, 2.f), }, }; } static constexpr CCameraShakeData BuildProjectileCameraShake(float duration, float magnitude) noexcept { return { duration, 100.f, 0, zeus::skZero3f, CCameraShakerComponent{ true, SCameraShakePoint(false, 0.f, 0.f, duration, magnitude), SCameraShakePoint(true, 0.f, 0.f, 0.5f * duration, 3.f), }, CCameraShakerComponent{}, CCameraShakerComponent{}, }; } static constexpr CCameraShakeData BuildMissileCameraShake(float duration, float magnitude, float sfxDistance, const zeus::CVector3f& sfxPos) noexcept { CCameraShakeData ret(duration, magnitude); ret.SetSfxPositionAndDistance(sfxPos, sfxDistance); return ret; } static constexpr CCameraShakeData BuildPhazonCameraShakeData(float duration, float magnitude) noexcept { return { duration, 100.f, 0, zeus::skZero3f, CCameraShakerComponent{ true, SCameraShakePoint(false, 0.15f * duration, 0.f, 0.25f * duration, magnitude), SCameraShakePoint(true, 0.f, 0.f, 0.4f * duration, 0.3f), }, CCameraShakerComponent{}, CCameraShakerComponent{ true, SCameraShakePoint(false, 0.25f * duration, 0.f, 0.25f * duration, magnitude), SCameraShakePoint(true, 0.f, 0.f, 0.5f * duration, 0.5f), }, }; } static constexpr CCameraShakeData BuildPatternedExplodeShakeData(float duration, float magnitude) noexcept { return { duration, 100.f, 0, zeus::skZero3f, CCameraShakerComponent{ true, SCameraShakePoint(false, 0.25f * duration, 0.f, 0.75f * duration, magnitude), SCameraShakePoint(true, 0.f, 0.f, 0.5f * duration, 2.0f), }, CCameraShakerComponent{}, CCameraShakerComponent{}, }; } static constexpr CCameraShakeData BuildPatternedExplodeShakeData(const zeus::CVector3f& pos, float duration, float magnitude, float distance) noexcept { CCameraShakeData shakeData = BuildPatternedExplodeShakeData(duration, magnitude); shakeData.SetSfxPositionAndDistance(pos, distance); return shakeData; } void Update(float dt, CStateManager& mgr); zeus::CVector3f GetPoint() const; float GetMaxAMComponent() const; float GetMaxFMComponent() const; void SetShakerId(u32 id) { xbc_shakerId = id; } u32 GetShakerId() const { return xbc_shakerId; } static CCameraShakeData LoadCameraShakeData(CInputStream& in); constexpr void SetSfxPositionAndDistance(const zeus::CVector3f& pos, float sfxDistance) noexcept { xc0_flags |= 0x1; xc4_sfxPos = pos; xd0_sfxDist = sfxDistance; } }; } // namespace metaforce