diff --git a/NewHorizons/Builder/Body/StarBuilder.cs b/NewHorizons/Builder/Body/StarBuilder.cs index def3fa05..940db684 100644 --- a/NewHorizons/Builder/Body/StarBuilder.cs +++ b/NewHorizons/Builder/Body/StarBuilder.cs @@ -178,16 +178,6 @@ namespace NewHorizons.Builder.Body } surfaceAudio.SetStarEvolutionController(controller); starGO.SetActive(true); - - // It fucking insists on this existing and its really annoying - var supernovaVolume = new GameObject("SupernovaVolumePlaceholder"); - supernovaVolume.transform.SetParent(starGO.transform); - supernovaVolume.layer = LayerMask.NameToLayer("BasicEffectVolume"); - var sphere = supernovaVolume.AddComponent(); - sphere.radius = 0f; - sphere.isTrigger = true; - supernovaVolume.AddComponent(); - supernova._supernovaVolume = supernovaVolume.AddComponent(); } var shockLayerRuleset = sector.gameObject.AddComponent(); @@ -208,9 +198,9 @@ namespace NewHorizons.Builder.Body if (!isStellarRemnant) { - var supernova = MakeSupernova(starGO, starModule); + var supernova = MakeSupernova(starGO, starModule, true); - supernova._belongsToProxySun = true; + supernova.SetIsProxy(true); starGO.SetActive(false); var controller = starGO.AddComponent(); @@ -312,7 +302,7 @@ namespace NewHorizons.Builder.Body return starGO; } - public static SupernovaEffectController MakeSupernova(GameObject starGO, StarModule starModule) + public static StellarDeathController MakeSupernova(GameObject starGO, StarModule starModule, bool noAudio = false) { var supernovaGO = SearchUtilities.Find("Sun_Body/Sector_SUN/Effects_SUN/Supernova").InstantiateInactive(); supernovaGO.name = "Supernova"; @@ -320,41 +310,63 @@ namespace NewHorizons.Builder.Body supernovaGO.transform.localPosition = Vector3.zero; var supernova = supernovaGO.GetComponent(); - supernova._surface = starGO.GetComponentInChildren(); - supernova._supernovaScale = new AnimationCurve(new Keyframe(0, 200, 0, 0, 1f / 3f, 1f / 3f), new Keyframe(45, starModule.supernovaSize, 1758.508f, 1758.508f, 1f / 3f, 1f / 3f)); - supernova._supernovaAlpha = new AnimationCurve(new Keyframe(5, 1, 0, 0, 1f / 3f, 1f / 3f), new Keyframe(15, 1.0002f, 0, 0, 1f / 3f, 1f / 3f), new Keyframe(50, 0, -0.0578f, 1 / 3f, -0.0578f, 1 / 3f)); - supernova._supernovaVolume = null; + var stellarDeath = supernovaGO.AddComponent(); + stellarDeath.enabled = false; + stellarDeath._surface = starGO.GetComponentInChildren(); + stellarDeath._supernovaScale = new AnimationCurve(new Keyframe(0, 200, 0, 0, 1f / 3f, 1f / 3f), new Keyframe(45, starModule.supernovaSize, 1758.508f, 1758.508f, 1f / 3f, 1f / 3f)); + stellarDeath._supernovaAlpha = new AnimationCurve(new Keyframe(5, 1, 0, 0, 1f / 3f, 1f / 3f), new Keyframe(15, 1.0002f, 0, 0, 1f / 3f, 1f / 3f), new Keyframe(50, 0, -0.0578f, 1 / 3f, -0.0578f, 1 / 3f)); + stellarDeath._explosionParticles = supernova._explosionParticles; + stellarDeath._shockwave = supernova._shockwave; + stellarDeath._shockwaveLength = supernova._shockwaveLength; + stellarDeath._shockwaveAlpha = supernova._shockwaveAlpha; + stellarDeath._shockwaveScale = supernova._shockwaveScale; + stellarDeath._supernovaMaterial = supernova._supernovaMaterial; + GameObject.Destroy(supernova); if (starModule.supernovaTint != null) { var colour = starModule.supernovaTint.ToColor(); - var supernovaMaterial = new Material(supernova._supernovaMaterial); + var supernovaMaterial = new Material(stellarDeath._supernovaMaterial); var ramp = ImageUtilities.LerpGreyscaleImage(ImageUtilities.GetTexture(Main.Instance, "Assets/textures/Effects_SUN_Supernova_d.png"), Color.white, colour); supernovaMaterial.SetTexture(ColorRamp, ramp); - supernova._supernovaMaterial = supernovaMaterial; + stellarDeath._supernovaMaterial = supernovaMaterial; // Motes - var moteMaterial = supernova.GetComponentInChildren().material; + var moteMaterial = supernovaGO.GetComponentInChildren().material; moteMaterial.color = new Color(colour.r * 3f, colour.g * 3f, colour.b * 3f, moteMaterial.color.a); } - foreach (var controller in supernova.GetComponentsInChildren()) + foreach (var controller in supernovaGO.GetComponentsInChildren()) { Object.DestroyImmediate(controller); } - var supernovaWallAudio = new GameObject("SupernovaWallAudio"); - supernovaWallAudio.transform.SetParent(supernovaGO.transform, false); - supernovaWallAudio.transform.localPosition = Vector3.zero; - supernovaWallAudio.transform.localScale = Vector3.one; - supernovaWallAudio.layer = LayerMask.NameToLayer("BasicEffectVolume"); - supernovaWallAudio.AddComponent(); - supernova._audioSource = supernovaWallAudio.AddComponent(); + if (!noAudio) + { + var supernovaWallAudio = new GameObject("SupernovaWallAudio"); + supernovaWallAudio.transform.SetParent(supernovaGO.transform, false); + supernovaWallAudio.transform.localPosition = Vector3.zero; + supernovaWallAudio.transform.localScale = Vector3.one; + supernovaWallAudio.layer = LayerMask.NameToLayer("BasicEffectVolume"); + var audioSource = supernovaWallAudio.AddComponent(); + audioSource.loop = true; + audioSource.maxDistance = 2000; + audioSource.dopplerLevel = 0; + audioSource.rolloffMode = AudioRolloffMode.Custom; + audioSource.playOnAwake = false; + audioSource.spatialBlend = 1; + audioSource.volume = 0.5f; + audioSource.velocityUpdateMode = AudioVelocityUpdateMode.Fixed; + stellarDeath._audioSource = supernovaWallAudio.AddComponent(); + stellarDeath._audioSource._audioSource = audioSource; + stellarDeath._audioSource._audioLibraryClip = AudioType.Sun_SupernovaWall_LP; + stellarDeath._audioSource.SetTrack(OWAudioMixer.TrackName.EndTimes_SFX); + } supernovaGO.SetActive(true); - return supernova; + return stellarDeath; } } } diff --git a/NewHorizons/Components/SizeControllers/StarEvolutionController.cs b/NewHorizons/Components/SizeControllers/StarEvolutionController.cs index e0a5b01d..e499fb56 100644 --- a/NewHorizons/Components/SizeControllers/StarEvolutionController.cs +++ b/NewHorizons/Components/SizeControllers/StarEvolutionController.cs @@ -19,7 +19,7 @@ namespace NewHorizons.Components.SizeControllers public GameObject atmosphere; public StarController controller; - public SupernovaEffectController supernova; + public StellarDeathController supernova; public bool WillExplode { get; set; } public MColor StartColour { get; set; } public MColor EndColour { get; set; } diff --git a/NewHorizons/Components/StellarDeathController.cs b/NewHorizons/Components/StellarDeathController.cs new file mode 100644 index 00000000..cf6b6738 --- /dev/null +++ b/NewHorizons/Components/StellarDeathController.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace NewHorizons.Components +{ + public class StellarDeathController : MonoBehaviour + { + public ParticleSystem[] _explosionParticles; + public MeshRenderer _shockwave; + public float _shockwaveLength = 5f; + public AnimationCurve _shockwaveScale = AnimationCurve.Linear(0.0f, 0.0f, 1f, 100000f); + public AnimationCurve _shockwaveAlpha = AnimationCurve.Linear(0.0f, 1f, 1f, 0.0f); + [Space] + public TessellatedSphereRenderer _surface; + public Material _supernovaMaterial; + public AnimationCurve _supernovaScale = new AnimationCurve(new Keyframe(0, 200, 0, 0, 1f / 3f, 1f / 3f), new Keyframe(45, 50000, 1758.508f, 1758.508f, 1f / 3f, 1f / 3f)); + public AnimationCurve _supernovaAlpha = new AnimationCurve(new Keyframe(5, 1, 0, 0, 1f / 3f, 1f / 3f), new Keyframe(15, 1.0002f, 0, 0, 1f / 3f, 1f / 3f), new Keyframe(50, 0, -0.0578f, 1 / 3f, -0.0578f, 1 / 3f)); + [Space] + public OWAudioSource _audioSource; + private float _time; + private float _currentSupernovaScale; + private Material _localSupernovaMat; + private bool _isProxy; + private ParticleSystemRenderer[] _cachedParticleRenderers; + + private void Awake() + { + _cachedParticleRenderers = new ParticleSystemRenderer[_explosionParticles.Length]; + for (int index = 0; index < _explosionParticles.Length; ++index) + _cachedParticleRenderers[index] = _explosionParticles[index].GetComponent(); + } + + private void OnEnable() + { + _shockwave.enabled = true; + foreach (var particle in _explosionParticles) particle.Play(); + _time = 0.0f; + _currentSupernovaScale = _supernovaScale.Evaluate(0.0f); + _localSupernovaMat = new Material(_supernovaMaterial); + _surface.sharedMaterial = _localSupernovaMat; + + if (_audioSource == null) return; + + _audioSource.AssignAudioLibraryClip(AudioType.Sun_SupernovaWall_LP); + _audioSource.SetLocalVolume(0); + _audioSource.Play(); + } + + private void OnDisable() + { + _shockwave.enabled = false; + + if (_audioSource == null) return; + + _audioSource.SetLocalVolume(0); + _audioSource.Stop(); + } + + private void FixedUpdate() + { + _time += Time.deltaTime; + float shockwaveTime = Mathf.Clamp01(_time / _shockwaveLength); + _shockwave.transform.localScale = Vector3.one * _shockwaveScale.Evaluate(shockwaveTime); + _shockwave.material.color = Color.Lerp(Color.black, _shockwave.sharedMaterial.color, _shockwaveAlpha.Evaluate(shockwaveTime)); + _currentSupernovaScale = _supernovaScale.Evaluate(_time); + _surface.transform.localScale = Vector3.one * _currentSupernovaScale; + _localSupernovaMat.color = Color.Lerp(Color.black, _supernovaMaterial.color, _supernovaAlpha.Evaluate(_time)); + + float distanceToPlayer = PlayerState.InDreamWorld() ? 20000f : (Vector3.Distance(transform.position, Locator.GetPlayerCamera().transform.position) - GetSupernovaRadius()); + + if (_isProxy) return; + + if (_audioSource != null) + { + float dt = Mathf.InverseLerp(12000f, 0.0f, distanceToPlayer); + _audioSource.SetLocalVolume(Mathf.Lerp(0.0f, 1f, dt * dt) * Mathf.InverseLerp(0.0f, 5f, _time)); + } + + RumbleManager.UpdateSupernova(distanceToPlayer); + } + + public float GetSupernovaRadius() => _currentSupernovaScale; + + public void SetIsProxy(bool isProxy) => _isProxy = isProxy; + + public void SetParticlesVisibility(bool visible) + { + foreach (var particleRenderer in _cachedParticleRenderers) particleRenderer.enabled = visible; + } + + public void SetRenderingEnabled(bool renderingEnabled) + { + if (!enabled) return; + _shockwave.enabled = renderingEnabled; + SetParticlesVisibility(renderingEnabled); + } + } +}