diff --git a/NewHorizons/Builder/Body/ProxyBuilder.cs b/NewHorizons/Builder/Body/ProxyBuilder.cs index 15eb6635..4ff3c84d 100644 --- a/NewHorizons/Builder/Body/ProxyBuilder.cs +++ b/NewHorizons/Builder/Body/ProxyBuilder.cs @@ -156,6 +156,11 @@ namespace NewHorizons.Builder.Body } } + if (body.Config.Base.hasSupernovaShockEffect && body.Config.Star == null && body.Config.name != "Sun" && body.Config.FocalPoint == null) + { + proxyController._supernovaPlanetEffectController = SupernovaEffectBuilder.Make(newProxy, null, body.Config, heightMap, procGen, null, null, null, proxyController._atmosphere, proxyController._fog); + } + // Remove all collisions if there are any foreach (var col in newProxy.GetComponentsInChildren()) { diff --git a/NewHorizons/Builder/Body/StarBuilder.cs b/NewHorizons/Builder/Body/StarBuilder.cs index f3ef4b15..ab76c9e2 100644 --- a/NewHorizons/Builder/Body/StarBuilder.cs +++ b/NewHorizons/Builder/Body/StarBuilder.cs @@ -142,6 +142,7 @@ namespace NewHorizons.Builder.Body controller.supernova = supernova; controller.StartColour = starModule.tint; controller.EndColour = starModule.endTint; + controller.SupernovaColour = starModule.supernovaTint; controller.WillExplode = starModule.goSupernova; controller.lifespan = starModule.lifespan; controller.normalRamp = !string.IsNullOrEmpty(starModule.starRampTexture) ? ImageUtilities.GetTexture(mod, starModule.starRampTexture) : ramp; @@ -192,6 +193,7 @@ namespace NewHorizons.Builder.Body controller.supernova = supernova; controller.StartColour = starModule.tint; controller.EndColour = starModule.endTint; + controller.SupernovaColour = starModule.supernovaTint; controller.WillExplode = starModule.goSupernova; controller.lifespan = starModule.lifespan; controller.normalRamp = !string.IsNullOrEmpty(starModule.starRampTexture) ? ImageUtilities.GetTexture(mod, starModule.starRampTexture) : ramp; diff --git a/NewHorizons/Builder/Body/SupernovaEffectBuilder.cs b/NewHorizons/Builder/Body/SupernovaEffectBuilder.cs new file mode 100644 index 00000000..746a976f --- /dev/null +++ b/NewHorizons/Builder/Body/SupernovaEffectBuilder.cs @@ -0,0 +1,172 @@ +using UnityEngine; +using NewHorizons.Utility; +using NewHorizons.External.Configs; +using NewHorizons.Components; +using System.Linq; +using NewHorizons.Handlers; + +namespace NewHorizons.Builder.Body +{ + public static class SupernovaEffectBuilder + { + public static NHSupernovaPlanetEffectController Make(GameObject planetGO, Sector sector, PlanetConfig config, GameObject heightMap, GameObject procGen, Light ambientLight, PlanetaryFogController fog, LODGroup atmosphere, Renderer atmosphereRenderer, Renderer fogImpostor) + { + var vanillaController = planetGO.GetComponentInChildren(); + if (vanillaController != null) + { + ReplaceVanillaWithNH(vanillaController); + } + + var currentController = planetGO.GetComponentInChildren(); + if (currentController != null) + { + if (currentController._ambientLight == null && ambientLight != null) + { + currentController._ambientLight = ambientLight; + currentController._ambientLightOrigIntensity = config.Base.ambientLight; + } + + if (currentController._atmosphere == null && atmosphere != null) currentController._atmosphere = atmosphere; + + if (currentController._fog == null && fog != null) currentController._fog = fog; + + return currentController; + } + else + { + var supernovaController = new GameObject("SupernovaController"); + supernovaController.transform.SetParent(sector?.transform ?? planetGO.transform, false); + var supernovaEffectController = supernovaController.AddComponent(); + supernovaEffectController._ambientLight = ambientLight; + supernovaEffectController._ambientLightOrigIntensity = config.Base.ambientLight; + supernovaEffectController._atmosphere = atmosphere; + supernovaEffectController._atmosphereRenderer = atmosphereRenderer; + supernovaEffectController._fog = fog; + supernovaEffectController._fogImpostor = fogImpostor; + + var shockLayerGD = SearchUtilities.Find("GiantsDeep_Body/Shocklayer_GD"); + var shockLayer = new GameObject("ShockLayer"); + shockLayer.transform.SetParent(sector?.transform ?? planetGO.transform, false); + shockLayer.AddComponent().sharedMesh = shockLayerGD.GetComponent().sharedMesh; + + var shockLayerMaterial = new Material(shockLayerGD.GetComponent().sharedMaterial); + shockLayerMaterial.name = "ShockLayer_mat"; + + var shockLayerRenderer = shockLayer.AddComponent(); + shockLayerRenderer.sharedMaterial = shockLayerMaterial; + supernovaEffectController._shockLayer = shockLayerRenderer; + + var biggestSize = config.Base.surfaceSize; + var noMeshChange = false; + + if (config.Atmosphere != null) + { + if (config.Atmosphere.size > biggestSize) biggestSize = config.Atmosphere.size; + if (config.Atmosphere.fogSize > biggestSize) biggestSize = config.Atmosphere.fogSize; + if (config.Atmosphere.clouds != null) + { + noMeshChange = true; + if (config.Atmosphere.clouds.innerCloudRadius > biggestSize) biggestSize = config.Atmosphere.clouds.innerCloudRadius; + if (config.Atmosphere.clouds.outerCloudRadius > biggestSize) biggestSize = config.Atmosphere.clouds.outerCloudRadius; + } + } + + if (config.Base.groundSize > biggestSize) + { + noMeshChange = true; + biggestSize = config.Base.groundSize; + } + + if (config.HeightMap != null) + { + if (config.HeightMap.minHeight > biggestSize) biggestSize = config.HeightMap.minHeight; + if (config.HeightMap.maxHeight > biggestSize) biggestSize = config.HeightMap.maxHeight; + } + + if (config.ProcGen != null) + { + if (config.ProcGen.scale > biggestSize) biggestSize = config.ProcGen.scale; + } + + if (config.Lava != null) + { + noMeshChange = true; + var lavaSize = config.Lava.size; + if (config.Lava.curve != null) lavaSize *= config.Lava.curve.Max(tvp => tvp.value); + if (lavaSize > biggestSize) biggestSize = lavaSize; + } + + if (config.Water != null) + { + noMeshChange = true; + var waterSize = config.Water.size; + if (config.Water.curve != null) waterSize *= config.Water.curve.Max(tvp => tvp.value); + if (waterSize > biggestSize) biggestSize = waterSize; + } + + if (config.Sand != null) + { + noMeshChange = true; + var sandSize = config.Sand.size; + if (config.Sand.curve != null) sandSize *= config.Sand.curve.Max(tvp => tvp.value); + if (sandSize > biggestSize) biggestSize = sandSize; + } + + if (config.Props?.singularities != null) + { + noMeshChange = true; + foreach (var singularity in config.Props.singularities) + { + if (singularity.size > biggestSize) biggestSize = singularity.size; + } + } + + supernovaEffectController._shockLayerStartRadius = biggestSize; + supernovaEffectController._shockLayerFullRadius = biggestSize * 10f; + supernovaEffectController._shockLayerTrailFlare = 100; + supernovaEffectController._shockLayerTrailLength = biggestSize < 600 ? 300 : 600; + + shockLayer.transform.position = planetGO.transform.position; + shockLayer.transform.localScale = Vector3.one * biggestSize * 1.1f; + + if (!noMeshChange) + { + if (heightMap != null) + { + shockLayer.GetComponent().sharedMesh = heightMap.GetComponent().sharedMesh; + shockLayer.transform.localScale = Vector3.one * 1.1f; + shockLayer.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(90, 0, 0)); + } + else if (procGen != null) + { + shockLayer.GetComponent().sharedMesh = procGen.GetComponent().sharedMesh; + shockLayer.transform.localScale = Vector3.one * 1.1f; + shockLayer.transform.rotation = Quaternion.Euler(90, 0, 0); + } + } + + return supernovaEffectController; + } + } + + public static void ReplaceVanillaWithNH(SupernovaPlanetEffectController vanillaController) + { + if (vanillaController._shockLayer != null) vanillaController._shockLayer.gameObject.SetActive(true); + var supernovaEffectController = vanillaController.gameObject.GetAddComponent(); + supernovaEffectController._atmosphere = vanillaController._atmosphere; + supernovaEffectController._ambientLight = vanillaController._ambientLight; + supernovaEffectController._ambientLightOrigIntensity = vanillaController._ambientLightOrigIntensity; + supernovaEffectController._atmosphere = vanillaController._atmosphere; + supernovaEffectController._fog = vanillaController._fog; + supernovaEffectController._fogOrigTint = vanillaController._fogOrigTint; + supernovaEffectController._shockLayer = vanillaController._shockLayer; + supernovaEffectController._shockLayerColor = vanillaController._shockLayerColor; + supernovaEffectController._shockLayerFullRadius = vanillaController._shockLayerFullRadius; + supernovaEffectController._shockLayerStartRadius = vanillaController._shockLayerStartRadius; + supernovaEffectController._shockLayerTrailFlare = vanillaController._shockLayerTrailFlare; + supernovaEffectController._shockLayerTrailLength = vanillaController._shockLayerTrailLength; + supernovaEffectController._sunController = SearchUtilities.Find("Sun_Body").GetComponent(); + Object.Destroy(vanillaController); + } + } +} diff --git a/NewHorizons/Components/NHProxy.cs b/NewHorizons/Components/NHProxy.cs index d40c74bf..f19f9ae9 100644 --- a/NewHorizons/Components/NHProxy.cs +++ b/NewHorizons/Components/NHProxy.cs @@ -15,6 +15,7 @@ namespace NewHorizons.Components private SolarFlareEmitter _solarFlareEmitter; public CloudLightningGenerator _lightningGenerator; public MeshRenderer _mainBody; + public NHSupernovaPlanetEffectController _supernovaPlanetEffectController; public override void Awake() { @@ -33,6 +34,8 @@ namespace NewHorizons.Components } if (_lightningGenerator == null) _lightningGenerator = GetComponentInChildren(); + + if (_supernovaPlanetEffectController == null) _supernovaPlanetEffectController = GetComponentInChildren(); // Start off _outOfRange = false; @@ -87,6 +90,12 @@ namespace NewHorizons.Components _lightningGenerator.enabled = on; } + if (_supernovaPlanetEffectController != null) + { + if (on) _supernovaPlanetEffectController.Enable(); + else _supernovaPlanetEffectController.Disable(); + } + foreach (var renderer in _starRenderers) { renderer.enabled = on; diff --git a/NewHorizons/Components/NHSupernovaPlanetEffectController.cs b/NewHorizons/Components/NHSupernovaPlanetEffectController.cs new file mode 100644 index 00000000..5f964a55 --- /dev/null +++ b/NewHorizons/Components/NHSupernovaPlanetEffectController.cs @@ -0,0 +1,195 @@ +using NewHorizons.Components.SizeControllers; +using NewHorizons.Handlers; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using static SupernovaPlanetEffectController; + +namespace NewHorizons.Components +{ + public class NHSupernovaPlanetEffectController : MonoBehaviour + { + public Light _ambientLight; + public float _ambientLightOrigIntensity; + public LODGroup _atmosphere; + public Renderer _atmosphereRenderer; + public PlanetaryFogController _fog; + public Renderer _fogImpostor; + public Color _fogOrigTint; + [Space] + public MeshRenderer _shockLayer; + [ColorUsage(true, true)] + public Color _shockLayerColor = new Color(0.3569f, 0.7843f, 1f, 1f); + public float _shockLayerStartRadius = 1000f; + public float _shockLayerFullRadius = 10000f; + public float _shockLayerTrailLength = 300f; + public float _shockLayerTrailFlare = 100f; + + private LOD[] _atmosphereLODs; + + public StarEvolutionController _starEvolutionController; + + public SunController _sunController; + + public void Awake() + { + if (s_matPropBlock_Atmosphere == null) + { + s_matPropBlock_Atmosphere = new MaterialPropertyBlock(); + s_propID_SunIntensity = Shader.PropertyToID("_SunIntensity"); + s_propID_Tint = Shader.PropertyToID("_Tint"); + s_matPropBlock_ShockLayer = new MaterialPropertyBlock(); + s_propID_Color = Shader.PropertyToID("_Color"); + s_propID_WorldToLocalShockMatrix = Shader.PropertyToID("_WorldToShockLocalMatrix"); + s_propID_Dir = Shader.PropertyToID("_Dir"); + s_propID_Length = Shader.PropertyToID("_Length"); + s_propID_Flare = Shader.PropertyToID("_Flare"); + s_propID_TrailFade = Shader.PropertyToID("_TrailFade"); + s_propID_GradientLerp = Shader.PropertyToID("_GradientLerp"); + s_propID_MainTex_ST = Shader.PropertyToID("_MainTex_ST"); + } + } + + public void Start() + { + SupernovaEffectHandler.RegisterPlanetEffect(this); + if (_atmosphere != null) _atmosphereLODs = _atmosphere.GetLODs(); + if (_fog != null) + { + _fogOrigTint = _fog.fogTint; + _fogImpostor = _fog.fogImpostor; + } + else if (_fogImpostor != null) + { + _fogOrigTint = _fogImpostor.material.GetColor(s_propID_Tint); + } + if (_shockLayer != null) _shockLayer.enabled = false; + } + + public void OnDestroy() + { + SupernovaEffectHandler.UnregisterPlanetEffect(this); + } + + public void Enable() + { + enabled = true; + } + + public void Disable() + { + enabled = false; + if (_shockLayer != null) _shockLayer.enabled = false; + } + + public void Update() + { + SupernovaEffectHandler.GetNearestStarSupernova(this); + if (_starEvolutionController != null) + { + if (_starEvolutionController.HasSupernovaStarted()) + { + if (_shockLayer != null) + { + if (!_shockLayer.enabled) _shockLayer.enabled = true; + Vector3 dir = Vector3.Normalize(transform.position - _starEvolutionController.transform.position); + s_matPropBlock_ShockLayer.SetColor(s_propID_Color, _starEvolutionController.SupernovaColour != null ? _starEvolutionController.SupernovaColour.ToColor() : new Color(0.3569f, 0.7843f, 1f, 1f)); + s_matPropBlock_ShockLayer.SetMatrix(s_propID_WorldToLocalShockMatrix, Matrix4x4.TRS(transform.position, Quaternion.LookRotation(dir, Vector3.up), Vector3.one).inverse); + s_matPropBlock_ShockLayer.SetVector(s_propID_Dir, dir); + s_matPropBlock_ShockLayer.SetFloat(s_propID_Length, _shockLayerTrailLength); + s_matPropBlock_ShockLayer.SetFloat(s_propID_Flare, _shockLayerTrailFlare); + s_matPropBlock_ShockLayer.SetFloat(s_propID_TrailFade, 1f - Mathf.InverseLerp(_shockLayerStartRadius, _shockLayerFullRadius, _starEvolutionController.GetSupernovaRadius())); + s_matPropBlock_ShockLayer.SetFloat(s_propID_GradientLerp, 0); + s_matPropBlock_ShockLayer.SetVector(s_propID_MainTex_ST, _shockLayer.sharedMaterial.GetVector(s_propID_MainTex_ST) with { w = -Time.timeSinceLevelLoad }); + _shockLayer.SetPropertyBlock(s_matPropBlock_ShockLayer); + } + } + if (_starEvolutionController.IsCollapsing()) + { + float collapseProgress = _starEvolutionController.GetCollapseProgress(); + + if (_ambientLight != null) _ambientLight.intensity = _ambientLightOrigIntensity * (1f - collapseProgress); + + if (_atmosphere != null) + { + s_matPropBlock_Atmosphere.SetFloat(s_propID_SunIntensity, 1f - collapseProgress); + + foreach (var lod in _atmosphereLODs) + foreach (var renderer in lod.renderers) + renderer.SetPropertyBlock(s_matPropBlock_Atmosphere); + } + + if (_atmosphereRenderer != null) + { + s_matPropBlock_Atmosphere.SetFloat(s_propID_SunIntensity, 1f - collapseProgress); + + _atmosphereRenderer.SetPropertyBlock(s_matPropBlock_Atmosphere); + } + + if (_fog != null) _fog.fogTint = Color.Lerp(_fogOrigTint, Color.black, collapseProgress); + + if (_fogImpostor != null) _fogImpostor.material.SetColor(s_propID_Tint, Color.Lerp(_fogOrigTint, Color.black, collapseProgress)); + } + else + { + if (_shockLayer != null) _shockLayer.enabled = false; + } + } + else if (_sunController != null) + { + if (_sunController.HasSupernovaStarted()) + { + if (_shockLayer != null) + { + if (!_shockLayer.enabled) _shockLayer.enabled = true; + Vector3 dir = Vector3.Normalize(transform.position - _sunController.transform.position); + s_matPropBlock_ShockLayer.SetColor(s_propID_Color, _shockLayerColor); + s_matPropBlock_ShockLayer.SetMatrix(s_propID_WorldToLocalShockMatrix, Matrix4x4.TRS(transform.position, Quaternion.LookRotation(dir, Vector3.up), Vector3.one).inverse); + s_matPropBlock_ShockLayer.SetVector(s_propID_Dir, dir); + s_matPropBlock_ShockLayer.SetFloat(s_propID_Length, _shockLayerTrailLength); + s_matPropBlock_ShockLayer.SetFloat(s_propID_Flare, _shockLayerTrailFlare); + s_matPropBlock_ShockLayer.SetFloat(s_propID_TrailFade, 1f - Mathf.InverseLerp(_shockLayerStartRadius, _shockLayerFullRadius, _sunController.GetSupernovaRadius())); + s_matPropBlock_ShockLayer.SetFloat(s_propID_GradientLerp, 0); + s_matPropBlock_ShockLayer.SetVector(s_propID_MainTex_ST, _shockLayer.sharedMaterial.GetVector(s_propID_MainTex_ST) with { w = -Time.timeSinceLevelLoad }); + _shockLayer.SetPropertyBlock(s_matPropBlock_ShockLayer); + } + } + else if (_sunController._collapseStarted) + { + float collapseProgress = _sunController.GetCollapseProgress(); + + if (_ambientLight != null) _ambientLight.intensity = _ambientLightOrigIntensity * (1f - collapseProgress); + + if (_atmosphere != null) + { + s_matPropBlock_Atmosphere.SetFloat(s_propID_SunIntensity, 1f - collapseProgress); + + foreach (var lod in _atmosphereLODs) + foreach (var renderer in lod.renderers) + renderer.SetPropertyBlock(s_matPropBlock_Atmosphere); + } + + if (_atmosphereRenderer != null) + { + s_matPropBlock_Atmosphere.SetFloat(s_propID_SunIntensity, 1f - collapseProgress); + + _atmosphereRenderer.SetPropertyBlock(s_matPropBlock_Atmosphere); + } + + if (_fog != null) _fog.fogTint = Color.Lerp(_fogOrigTint, Color.black, collapseProgress); + + if (_fogImpostor != null) _fogImpostor.material.SetColor(s_propID_Tint, Color.Lerp(_fogOrigTint, Color.black, collapseProgress)); + } + else + { + if (_shockLayer != null) _shockLayer.enabled = false; + } + } + else + { + if (_shockLayer != null) _shockLayer.enabled = false; + } + } + } +} diff --git a/NewHorizons/Components/SizeControllers/StarEvolutionController.cs b/NewHorizons/Components/SizeControllers/StarEvolutionController.cs index 4120d873..2d66070c 100644 --- a/NewHorizons/Components/SizeControllers/StarEvolutionController.cs +++ b/NewHorizons/Components/SizeControllers/StarEvolutionController.cs @@ -1,4 +1,5 @@ using NewHorizons.Builder.Body; +using NewHorizons.Handlers; using NewHorizons.Utility; using System; using System.Collections.Generic; @@ -19,6 +20,7 @@ namespace NewHorizons.Components.SizeControllers public bool WillExplode { get; set; } public MColor StartColour { get; set; } public MColor EndColour { get; set; } + public MColor SupernovaColour { get; set; } public Texture normalRamp; public Texture collapseRamp; @@ -48,6 +50,8 @@ namespace NewHorizons.Components.SizeControllers private bool _isSupernova; private float _supernovaStartTime; + public bool _disabled; + private Material _collapseStartSurfaceMaterial; private Material _collapseEndSurfaceMaterial; private Material _startSurfaceMaterial; @@ -58,7 +62,10 @@ namespace NewHorizons.Components.SizeControllers private StarEvolutionController _proxy; + public UnityEvent CollapseStart = new UnityEvent(); + public UnityEvent CollapseStop = new UnityEvent(); public UnityEvent SupernovaStart = new UnityEvent(); + public UnityEvent SupernovaStop = new UnityEvent(); private float maxScale; private float minScale; @@ -148,6 +155,8 @@ namespace NewHorizons.Components.SizeControllers _flareEmitter = GetComponentInChildren(); _surfaceMaterial = supernova._surface._materials[0]; + SupernovaEffectHandler.RegisterStar(this); + var secondsElapsed = TimeLoop.GetSecondsElapsed(); var lifespanInSeconds = lifespan * 60; if (secondsElapsed >= lifespanInSeconds) @@ -164,6 +173,7 @@ namespace NewHorizons.Components.SizeControllers public void OnDestroy() { + SupernovaEffectHandler.UnregisterStar(this); } public void SetProxy(StarEvolutionController proxy) @@ -260,6 +270,8 @@ namespace NewHorizons.Components.SizeControllers if (controller != null) StarLightController.RemoveStar(controller); + _disabled = true; + // Just turn off the star entirely base.gameObject.SetActive(false); @@ -289,6 +301,7 @@ namespace NewHorizons.Components.SizeControllers Logger.LogVerbose($"{gameObject.transform.root.name} started collapse"); + CollapseStart.Invoke(); _isCollapsing = true; _collapseStartSize = CurrentScale; _collapseTimer = 0f; @@ -303,6 +316,7 @@ namespace NewHorizons.Components.SizeControllers Logger.LogVerbose($"{gameObject.transform.root.name} stopped collapse"); + CollapseStop.Invoke(); _isCollapsing = false; supernova._surface._materials[0].CopyPropertiesFromMaterial(_endSurfaceMaterial); @@ -332,6 +346,7 @@ namespace NewHorizons.Components.SizeControllers Logger.LogVerbose($"{gameObject.transform.root.name} stopped supernova"); + SupernovaStop.Invoke(); supernova.enabled = false; _isSupernova = false; if (atmosphere != null) atmosphere.SetActive(true); @@ -354,6 +369,24 @@ namespace NewHorizons.Components.SizeControllers if (_proxy != null) _proxy.StopSupernova(); } + public bool IsCollapsing() => _isCollapsing; + + public float GetCollapseProgress() => _collapseTimer / collapseTime; + + public bool HasSupernovaStarted() => _isSupernova; + + public bool IsPointInsideSupernova(Vector3 worldPosition) => _isSupernova && (worldPosition - transform.position).sqrMagnitude < (supernova.GetSupernovaRadius() * supernova.GetSupernovaRadius()); + + public bool IsPointInsideMaxSupernova(Vector3 worldPosition) => (worldPosition - transform.position).sqrMagnitude < (supernovaSize * supernovaSize); + + public float GetDistanceToSupernova(Vector3 worldPosition) => Vector3.Distance(worldPosition, transform.position) - supernova.GetSupernovaRadius(); + + public float GetDistanceToMaxSupernova(Vector3 worldPosition) => Vector3.Distance(worldPosition, transform.position) - supernovaSize; + + public float GetSupernovaRadius() => supernova.GetSupernovaRadius(); + + public float GetMaxSupernovaRadius() => supernovaSize; + protected new void FixedUpdate() { // If we've gone supernova and its been 45 seconds that means it has faded out and is gone diff --git a/NewHorizons/External/Modules/BaseModule.cs b/NewHorizons/External/Modules/BaseModule.cs index 2d434f66..aad6549c 100644 --- a/NewHorizons/External/Modules/BaseModule.cs +++ b/NewHorizons/External/Modules/BaseModule.cs @@ -56,6 +56,11 @@ namespace NewHorizons.External.Modules /// public bool hasMapMarker; + /// + /// Does this planet have a shock effect when the nearest star goes supernova? + /// + [DefaultValue(true)] public bool hasSupernovaShockEffect = true; + /// /// Can this planet survive entering a star? /// diff --git a/NewHorizons/Handlers/PlanetCreationHandler.cs b/NewHorizons/Handlers/PlanetCreationHandler.cs index bffe3fea..61eb5d20 100644 --- a/NewHorizons/Handlers/PlanetCreationHandler.cs +++ b/NewHorizons/Handlers/PlanetCreationHandler.cs @@ -31,11 +31,12 @@ namespace NewHorizons.Handlers _existingBodyDict = new(); _customBodyDict = new(); - + // Set up stars // Need to manage this when there are multiple stars var sun = SearchUtilities.Find("Sun_Body"); var starController = sun.AddComponent(); + SupernovaEffectHandler.RegisterSun(sun.GetComponent()); starController.Light = SearchUtilities.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent(); starController.AmbientLight = SearchUtilities.Find("Sun_Body/AmbientLight_SUN").GetComponent(); starController.FaceActiveCamera = SearchUtilities.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent(); @@ -467,9 +468,10 @@ namespace NewHorizons.Handlers { var sphereOfInfluence = GetSphereOfInfluence(body); + Light ambientLight = null; if (body.Config.Base.ambientLight != 0) { - AmbientLightBuilder.Make(go, sector, sphereOfInfluence, body.Config.Base.ambientLight); + ambientLight = AmbientLightBuilder.Make(go, sector, sphereOfInfluence, body.Config.Base.ambientLight); } if (body.Config.Base.groundSize != 0) @@ -477,17 +479,19 @@ namespace NewHorizons.Handlers GeometryBuilder.Make(go, sector, body.Config.Base.groundSize); } + GameObject heightMap = null; if (body.Config.HeightMap != null) { // resolution = tris on edge per face // divide by 4 to account for all the way around the equator var res = body.Config.HeightMap.resolution / 4; - HeightMapBuilder.Make(go, sector, body.Config.HeightMap, body.Mod, res, true); + heightMap = HeightMapBuilder.Make(go, sector, body.Config.HeightMap, body.Mod, res, true); } + GameObject procGen = null; if (body.Config.ProcGen != null) { - ProcGenBuilder.Make(go, sector, body.Config.ProcGen); + procGen = ProcGenBuilder.Make(go, sector, body.Config.ProcGen); } if (body.Config.Star != null) @@ -539,7 +543,8 @@ namespace NewHorizons.Handlers } var willHaveCloak = body.Config.Cloak != null && body.Config.Cloak.radius != 0f; - + PlanetaryFogController fog = null; + LODGroup atmosphere = null; if (body.Config.Atmosphere != null) { var surfaceSize = body.Config.Base.surfaceSize; @@ -556,9 +561,11 @@ namespace NewHorizons.Handlers EffectsBuilder.Make(go, sector, body.Config, surfaceSize); if (body.Config.Atmosphere.fogSize != 0) - FogBuilder.Make(go, sector, body.Config.Atmosphere); + { + fog = FogBuilder.Make(go, sector, body.Config.Atmosphere); + } - AtmosphereBuilder.Make(go, sector, body.Config.Atmosphere, surfaceSize); + atmosphere = AtmosphereBuilder.Make(go, sector, body.Config.Atmosphere, surfaceSize).GetComponentInChildren(); } if (body.Config.Props != null) @@ -577,6 +584,11 @@ namespace NewHorizons.Handlers CloakBuilder.Make(go, sector, rb, body.Config.Cloak, !body.Config.ReferenceFrame.hideInMap, body.Mod); } + if (body.Config.Base.hasSupernovaShockEffect && body.Config.Star == null && body.Config.name != "Sun" && body.Config.FocalPoint == null) + { + SupernovaEffectBuilder.Make(go, sector, body.Config, heightMap, procGen, ambientLight, fog, atmosphere, null, fog?._fogImpostor); + } + return go; } diff --git a/NewHorizons/Handlers/SupernovaEffectHandler.cs b/NewHorizons/Handlers/SupernovaEffectHandler.cs new file mode 100644 index 00000000..760b99b3 --- /dev/null +++ b/NewHorizons/Handlers/SupernovaEffectHandler.cs @@ -0,0 +1,90 @@ +using NewHorizons.Components; +using NewHorizons.Components.SizeControllers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.Handlers +{ + public class SupernovaEffectHandler + { + private static List _supernovaPlanetEffectControllers = new List(); + private static List _starEvolutionControllers = new List(); + private static SunController _sunController; + + public static void RegisterStar(StarEvolutionController starEvolutionController) + { + _starEvolutionControllers.SafeAdd(starEvolutionController); + } + + public static void UnregisterStar(StarEvolutionController starEvolutionController) + { + _starEvolutionControllers.Remove(starEvolutionController); + } + + public static void RegisterSun(SunController sunController) + { + _sunController = sunController; + } + + public static void UnregisterSun() + { + _sunController = null; + } + + public static void RegisterPlanetEffect(NHSupernovaPlanetEffectController supernovaPlanetEffectController) + { + _supernovaPlanetEffectControllers.SafeAdd(supernovaPlanetEffectController); + } + + public static void UnregisterPlanetEffect(NHSupernovaPlanetEffectController supernovaPlanetEffectController) + { + _supernovaPlanetEffectControllers.Remove(supernovaPlanetEffectController); + } + + public static void GetNearestStarSupernova(NHSupernovaPlanetEffectController supernovaPlanetEffectController) + { + if (supernovaPlanetEffectController == null) return; + + StarEvolutionController nearestStarEvolutionController = null; + float nearestDistance = float.MaxValue; + foreach (StarEvolutionController starEvolutionController in _starEvolutionControllers) + { + if (starEvolutionController == null) continue; + if (starEvolutionController._disabled) continue; + float distance = (supernovaPlanetEffectController.transform.position - starEvolutionController.transform.position).sqrMagnitude; + if (starEvolutionController.IsPointInsideMaxSupernova(supernovaPlanetEffectController.transform.position) && distance < nearestDistance) + { + nearestDistance = distance; + nearestStarEvolutionController = starEvolutionController; + } + } + + if (_sunController != null && _sunController.gameObject.activeSelf) + { + float distance = (supernovaPlanetEffectController.transform.position - _sunController.transform.position).sqrMagnitude; + if (InPointInsideSunSupernova(supernovaPlanetEffectController) && distance < nearestDistance) + { + supernovaPlanetEffectController._sunController = _sunController; + supernovaPlanetEffectController._starEvolutionController = null; + } + else + { + supernovaPlanetEffectController._sunController = null; + supernovaPlanetEffectController._starEvolutionController = nearestStarEvolutionController; + } + } + else + { + supernovaPlanetEffectController._sunController = null; + supernovaPlanetEffectController._starEvolutionController = nearestStarEvolutionController; + } + } + + public static SunController GetSunController() => _sunController; + + public static bool InPointInsideSunSupernova(NHSupernovaPlanetEffectController supernovaPlanetEffectController) => _sunController != null && (supernovaPlanetEffectController.transform.position - _sunController.transform.position).sqrMagnitude < 2500000000f;//(50000f*50000f); + } +} diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 7b51f660..1215468b 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -302,6 +302,14 @@ namespace NewHorizons AtmosphereBuilder.Init(); BrambleNodeBuilder.Init(BodyDict[CurrentStarSystem].Select(x => x.Config).Where(x => x.Bramble?.dimension != null).ToArray()); + if (isSolarSystem) + { + foreach (var supernovaPlanetEffectController in GameObject.FindObjectsOfType()) + { + SupernovaEffectBuilder.ReplaceVanillaWithNH(supernovaPlanetEffectController); + } + } + if (isSolarSystem) { PlanetCreationHandler.Init(BodyDict[CurrentStarSystem]);