diff --git a/NewHorizons/AssetBundle/shader b/NewHorizons/AssetBundle/shader index a6cf0246..148eca35 100644 Binary files a/NewHorizons/AssetBundle/shader and b/NewHorizons/AssetBundle/shader differ diff --git a/NewHorizons/AssetBundle/shader.manifest b/NewHorizons/AssetBundle/shader.manifest index d8a544b8..cb6d8e25 100644 --- a/NewHorizons/AssetBundle/shader.manifest +++ b/NewHorizons/AssetBundle/shader.manifest @@ -1,9 +1,9 @@ ManifestFileVersion: 0 -CRC: 3840241390 +CRC: 3597037522 Hashes: AssetFileHash: serializedVersion: 2 - Hash: 1c2c90716d1ed7c9cbf5f785e41eace6 + Hash: 33678ea445c06b269454371064cc3a5c TypeTreeHash: serializedVersion: 2 Hash: 6370d3f9de9eca57f523bce048404a46 @@ -12,6 +12,7 @@ ClassTypes: - Class: 48 Script: {instanceID: 0} Assets: -- Assets/SphereTextureWrapper.shader -- Assets/UnlitTransparent.shader +- Assets/Shaders/SphereTextureWrapper.shader +- Assets/Shaders/Ring.shader +- Assets/Shaders/UnlitTransparent.shader Dependencies: [] diff --git a/NewHorizons/Builder/Atmosphere/CloudsBuilder.cs b/NewHorizons/Builder/Atmosphere/CloudsBuilder.cs index 7188b6bb..c948ff6e 100644 --- a/NewHorizons/Builder/Atmosphere/CloudsBuilder.cs +++ b/NewHorizons/Builder/Atmosphere/CloudsBuilder.cs @@ -20,8 +20,6 @@ namespace NewHorizons.Atmosphere if (atmo.CloudCap == null) cap = ImageUtilities.ClearTexture(128, 128); else cap = assets.GetTexture(atmo.CloudCap); - - //if(atmo.CloudRamp == null) ramp = ImageUtilities.Scaled(image, 1, 128); if(atmo.CloudRamp == null) ramp = ImageUtilities.CanvasScaled(image, 1, image.height); else ramp = assets.GetTexture(atmo.CloudRamp); } @@ -31,6 +29,8 @@ namespace NewHorizons.Atmosphere return; } + Color cloudTint = atmo.CloudTint == null ? Color.white : (Color)atmo.CloudTint.ToColor32(); + GameObject cloudsMainGO = new GameObject(); cloudsMainGO.SetActive(false); cloudsMainGO.transform.parent = body.transform; @@ -56,8 +56,8 @@ namespace NewHorizons.Atmosphere foreach (var material in topMR.sharedMaterials) { - material.SetColor("_Color", atmo.CloudTint.ToColor32()); - material.SetColor("_TintColor", atmo.CloudTint.ToColor32()); + material.SetColor("_Color", cloudTint); + material.SetColor("_TintColor", cloudTint); material.SetTexture("_MainTex", image); material.SetTexture("_RampTex", ramp); @@ -84,7 +84,7 @@ namespace NewHorizons.Atmosphere bottomTSR.LODRadius = 1f; // It's always more green than expected - var bottomCloudTint = atmo.CloudTint.ToColor32(); + var bottomCloudTint = cloudTint; bottomCloudTint.g = (byte)(bottomCloudTint.g * 0.8f); foreach (Material material in bottomTSR.sharedMaterials) { diff --git a/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs b/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs index b620557f..868ec3b8 100644 --- a/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs +++ b/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs @@ -14,8 +14,10 @@ namespace NewHorizons.Builder.Body { static class AsteroidBeltBuilder { - public static void Make(string bodyName, AsteroidBeltModule belt, IModAssets assets) + public static void Make(string bodyName, IPlanetConfig parentConfig, IModAssets assets, string uniqueName) { + var belt = parentConfig.AsteroidBelt; + var minSize = 20; var maxSize = 50; int count = (int)(2f * Mathf.PI * belt.InnerRadius / (10f * maxSize)); @@ -28,7 +30,8 @@ namespace NewHorizons.Builder.Body var size = Random.Range(minSize, maxSize); var config = new Dictionary() { - {"Name", $"{bodyName} Asteroid {i+1}"}, + {"Name", $"{bodyName} Asteroid {i}"}, + {"StarSystem", parentConfig.StarSystem }, {"Base", new Dictionary() { {"HasMapMarker", false }, @@ -57,7 +60,9 @@ namespace NewHorizons.Builder.Body } }; - var asteroid = new NewHorizonsBody(new PlanetConfig(config), assets); + var asteroidConfig = new PlanetConfig(config); + if (belt.ProcGen != null) asteroidConfig.ProcGen = belt.ProcGen; + var asteroid = new NewHorizonsBody(new PlanetConfig(config), assets, uniqueName); Main.NextPassBodies.Add(asteroid); } } diff --git a/NewHorizons/Builder/Body/BlackHoleBuilder.cs b/NewHorizons/Builder/Body/BlackHoleBuilder.cs deleted file mode 100644 index 850651b4..00000000 --- a/NewHorizons/Builder/Body/BlackHoleBuilder.cs +++ /dev/null @@ -1,36 +0,0 @@ -using NewHorizons.External; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace NewHorizons.Builder.Body -{ - static class BlackHoleBuilder - { - public static void Make(GameObject body, BaseModule module, Sector sector) - { - var blackHole = GameObject.Instantiate(GameObject.Find("BrittleHollow_Body/BlackHole_BH"), body.transform); - blackHole.name = "BlackHole"; - blackHole.transform.localPosition = Vector3.zero; - //blackHole.transform.localScale = Vector3.one; //* module.BlackHoleSize; - - var blackHoleRenderer = blackHole.transform.Find("BlackHoleRenderer"); - //blackHoleRenderer.transform.localScale = Vector3.one; - - var singularityLOD = blackHoleRenderer.GetComponent(); - singularityLOD.SetSector(sector); - - /* - var meshRenderer = blackHoleRenderer.GetComponent(); - meshRenderer.material.SetFloat("_Radius", module.BlackHoleSize * 0.4f); - - var owRenderer = blackHoleRenderer.gameObject.AddComponent(); - var propID_Radius = Shader.PropertyToID("_Radius"); - owRenderer.SetMaterialProperty(propID_Radius, module.BlackHoleSize * 0.4f); - */ - } - } -} diff --git a/NewHorizons/Builder/Body/Geometry/CubeSphere.cs b/NewHorizons/Builder/Body/Geometry/CubeSphere.cs index 01653ee6..ebe11193 100644 --- a/NewHorizons/Builder/Body/Geometry/CubeSphere.cs +++ b/NewHorizons/Builder/Body/Geometry/CubeSphere.cs @@ -97,8 +97,8 @@ namespace NewHorizons.Body float latitude = (Mathf.Rad2Deg * Mathf.Acos(v.z / Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z))); float longitude = 180f; - if(v.x > 0) longitude = Mathf.Rad2Deg * Mathf.Atan(v.y / v.x) + 90f; - if(v.x < 0) longitude = Mathf.Rad2Deg * (Mathf.Atan(v.y / v.x) + Mathf.PI) + 90f; + if(v.x > 0) longitude = Mathf.Rad2Deg * Mathf.Atan(v.y / v.x); + if(v.x < 0) longitude = Mathf.Rad2Deg * (Mathf.Atan(v.y / v.x) + Mathf.PI); float sampleX = heightMap.width * longitude / 360f; float sampleY = heightMap.height * latitude / 180f; diff --git a/NewHorizons/Builder/Body/HeightMapBuilder.cs b/NewHorizons/Builder/Body/HeightMapBuilder.cs index 58ef8d21..cf47994a 100644 --- a/NewHorizons/Builder/Body/HeightMapBuilder.cs +++ b/NewHorizons/Builder/Body/HeightMapBuilder.cs @@ -33,6 +33,7 @@ namespace NewHorizons.Builder.Body } GameObject cubeSphere = new GameObject("CubeSphere"); + cubeSphere.SetActive(false); cubeSphere.transform.parent = go.transform; cubeSphere.transform.rotation = Quaternion.Euler(90, 0, 0); @@ -41,7 +42,7 @@ namespace NewHorizons.Builder.Body cubeSphere.AddComponent(); cubeSphere.GetComponent().mesh = mesh; - if(PlanetShader == null) PlanetShader = Main.ShaderBundle.LoadAsset("Assets/SphereTextureWrapper.shader"); + if(PlanetShader == null) PlanetShader = Main.ShaderBundle.LoadAsset("Assets/Shaders/SphereTextureWrapper.shader"); var cubeSphereMR = cubeSphere.AddComponent(); cubeSphereMR.material = new Material(PlanetShader); @@ -50,9 +51,13 @@ namespace NewHorizons.Builder.Body var cubeSphereMC = cubeSphere.AddComponent(); cubeSphereMC.sharedMesh = mesh; + if(go.GetComponent() != null) cubeSphere.AddComponent(); + // Fix rotation in the end cubeSphere.transform.localRotation = Quaternion.Euler(90, 0, 0); cubeSphere.transform.localPosition = Vector3.zero; + + cubeSphere.SetActive(true); } } } diff --git a/NewHorizons/Builder/Body/ProcGenBuilder.cs b/NewHorizons/Builder/Body/ProcGenBuilder.cs index e6a75575..e53e76d7 100644 --- a/NewHorizons/Builder/Body/ProcGenBuilder.cs +++ b/NewHorizons/Builder/Body/ProcGenBuilder.cs @@ -30,6 +30,8 @@ namespace NewHorizons.Builder.Body var cubeSphereMC = icosphere.AddComponent(); cubeSphereMC.sharedMesh = mesh; icosphere.transform.localRotation = Quaternion.Euler(90, 0, 0); + + icosphere.AddComponent(); } } } diff --git a/NewHorizons/Builder/Body/RingBuilder.cs b/NewHorizons/Builder/Body/RingBuilder.cs index 03df9906..4356a955 100644 --- a/NewHorizons/Builder/Body/RingBuilder.cs +++ b/NewHorizons/Builder/Body/RingBuilder.cs @@ -13,6 +13,7 @@ namespace NewHorizons.Builder.Body static class RingBuilder { public static Shader RingShader; + public static Shader UnlitShader; public static void Make(GameObject body, RingModule ring, IModAssets assets) { @@ -39,15 +40,16 @@ namespace NewHorizons.Builder.Body var ringMR = ringGO.AddComponent(); var texture = ringTexture; - if (RingShader == null) RingShader = Main.ShaderBundle.LoadAsset("Assets/UnlitTransparent.shader"); + if (RingShader == null) RingShader = Main.ShaderBundle.LoadAsset("Assets/Shaders/Ring.shader"); + if (UnlitShader == null) UnlitShader = Main.ShaderBundle.LoadAsset("Assets/Shaders/UnlitTransparent.shader"); - var mat = new Material(RingShader); + var mat = new Material(ring.Unlit ? UnlitShader : RingShader); mat.mainTexture = texture; - mat.renderQueue = 3000; + mat.renderQueue = 2895; ringMR.material = mat; // Make mesh - var segments = (int)Math.Max(20, ring.OuterRadius); + var segments = (int)Mathf.Clamp(ring.OuterRadius, 20, 2000); BuildRingMesh(ringMesh, segments, ring.InnerRadius, ring.OuterRadius); } diff --git a/NewHorizons/Builder/Body/SingularityBuilder.cs b/NewHorizons/Builder/Body/SingularityBuilder.cs new file mode 100644 index 00000000..c858ae22 --- /dev/null +++ b/NewHorizons/Builder/Body/SingularityBuilder.cs @@ -0,0 +1,234 @@ +using NewHorizons.Components; +using NewHorizons.External; +using NewHorizons.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Builder.Body +{ + static class SingularityBuilder + { + enum Polarity + { + BlackHole, + WhiteHole + } + + private static Shader blackHoleShader = null; + private static Shader whiteHoleShader = null; + + public static void Make(GameObject body, Sector sector, OWRigidbody OWRB, IPlanetConfig config) + { + + var size = config.Base.BlackHoleSize; + string pairedSingularity = null; + var polarity = Polarity.BlackHole; + + if (config.Singularity != null) + { + size = config.Singularity.Size; + pairedSingularity = config.Singularity.PairedSingularity; + if(config.Singularity.Type != null && config.Singularity.Type.ToUpper().Equals("WHITEHOLE")) + { + polarity = Polarity.WhiteHole; + } + } + bool isWormHole = config.Singularity.TargetStarSystem != null; + bool hasHazardVolume = !isWormHole && (pairedSingularity == null); + + Vector3 localPosition = config.Singularity.Position == null ? Vector3.zero : (Vector3)config.Singularity.Position; + + GameObject newSingularity = null; + switch (polarity) + { + case Polarity.BlackHole: + newSingularity = MakeBlackHole(body, sector, localPosition, size, hasHazardVolume, config.Singularity.TargetStarSystem); + break; + case Polarity.WhiteHole: + newSingularity = MakeWhiteHole(body, sector, OWRB, localPosition, size); + break; + } + + // Try to pair them + if(pairedSingularity != null && newSingularity != null) + { + var pairedSingularityAO = AstroObjectLocator.GetAstroObject(pairedSingularity); + if(pairedSingularityAO != null) + { + switch (polarity) + { + case Polarity.BlackHole: + PairSingularities(newSingularity, pairedSingularityAO.gameObject); + break; + case Polarity.WhiteHole: + PairSingularities(pairedSingularityAO.gameObject, newSingularity); + break; + } + } + } + } + + public static void PairSingularities(GameObject blackHole, GameObject whiteHole) + { + Logger.Log($"Pairing singularities {blackHole?.name}, {whiteHole?.name}"); + try + { + blackHole.GetComponentInChildren()._whiteHole = whiteHole.GetComponentInChildren(); + } + catch (Exception) + { + Logger.LogError($"Couldn't pair singularities"); + } + } + + public static GameObject MakeBlackHole(GameObject body, Sector sector, Vector3 localPosition, float size, bool hasDestructionVolume, string targetSolarSystem, bool makeAudio = true) + { + var blackHole = new GameObject("BlackHole"); + blackHole.SetActive(false); + blackHole.transform.parent = body.transform; + blackHole.transform.localPosition = localPosition; + + var blackHoleRender = new GameObject("BlackHoleRender"); + blackHoleRender.transform.parent = blackHole.transform; + blackHoleRender.transform.localPosition = Vector3.zero; + blackHoleRender.transform.localScale = Vector3.one * size; + + var meshFilter = blackHoleRender.AddComponent(); + meshFilter.mesh = GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleRenderer").GetComponent().mesh; + + var meshRenderer = blackHoleRender.AddComponent(); + if (blackHoleShader == null) blackHoleShader = GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleRenderer").GetComponent().sharedMaterial.shader; + meshRenderer.material = new Material(blackHoleShader); + meshRenderer.material.SetFloat("_Radius", size * 0.4f); + meshRenderer.material.SetFloat("_MaxDistortRadius", size * 0.95f); + meshRenderer.material.SetFloat("_MassScale", 1); + meshRenderer.material.SetFloat("_DistortFadeDist", size * 0.55f); + + if(makeAudio) + { + var blackHoleAmbience = GameObject.Instantiate(GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleAmbience"), blackHole.transform); + blackHoleAmbience.name = "BlackHoleAmbience"; + blackHoleAmbience.GetComponent().SetSector(sector); + + var blackHoleAudioSource = blackHoleAmbience.GetComponent(); + blackHoleAudioSource.maxDistance = size * 2.5f; + blackHoleAudioSource.minDistance = size * 0.4f; + blackHoleAmbience.transform.localPosition = Vector3.zero; + + var blackHoleOneShot = GameObject.Instantiate(GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleEmissionOneShot"), blackHole.transform); + var oneShotAudioSource = blackHoleOneShot.GetComponent(); + oneShotAudioSource.maxDistance = size * 3f; + oneShotAudioSource.minDistance = size * 0.4f; + } + + + if (hasDestructionVolume || targetSolarSystem != null) + { + var destructionVolumeGO = new GameObject("DestructionVolume"); + destructionVolumeGO.layer = LayerMask.NameToLayer("BasicEffectVolume"); + destructionVolumeGO.transform.parent = blackHole.transform; + destructionVolumeGO.transform.localScale = Vector3.one; + destructionVolumeGO.transform.localPosition = Vector3.zero; + + var sphereCollider = destructionVolumeGO.AddComponent(); + sphereCollider.radius = size * 0.4f; + sphereCollider.isTrigger = true; + + if (hasDestructionVolume) destructionVolumeGO.AddComponent(); + else if (targetSolarSystem != null) + { + var wormholeVolume = destructionVolumeGO.AddComponent(); + wormholeVolume.TargetSolarSystem = targetSolarSystem; + } + } + else + { + var blackHoleVolume = GameObject.Instantiate(GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleVolume"), blackHole.transform); + blackHoleVolume.name = "BlackHoleVolume"; + blackHoleVolume.GetComponent().radius = size * 0.4f; + } + + blackHole.SetActive(true); + return blackHole; + } + + public static GameObject MakeWhiteHole(GameObject body, Sector sector, OWRigidbody OWRB, Vector3 localPosition, float size, bool makeZeroGVolume = true) + { + var whiteHole = new GameObject("WhiteHole"); + whiteHole.SetActive(false); + whiteHole.transform.parent = body.transform; + whiteHole.transform.localPosition = localPosition; + + var whiteHoleRenderer = new GameObject("WhiteHoleRenderer"); + whiteHoleRenderer.transform.parent = whiteHole.transform; + whiteHoleRenderer.transform.localPosition = Vector3.zero; + whiteHoleRenderer.transform.localScale = Vector3.one * size * 2.8f; + + var meshFilter = whiteHoleRenderer.AddComponent(); + meshFilter.mesh = GameObject.Find("WhiteHole_Body/WhiteHoleVisuals/Singularity").GetComponent().mesh; + + var meshRenderer = whiteHoleRenderer.AddComponent(); + if (whiteHoleShader == null) whiteHoleShader = GameObject.Find("WhiteHole_Body/WhiteHoleVisuals/Singularity").GetComponent().sharedMaterial.shader; + meshRenderer.material = new Material(whiteHoleShader); + meshRenderer.sharedMaterial.SetFloat("_Radius", size * 0.4f); + meshRenderer.sharedMaterial.SetFloat("_DistortFadeDist", size); + meshRenderer.sharedMaterial.SetFloat("_MaxDistortRadius", size * 2.8f); + meshRenderer.sharedMaterial.SetColor("_Color", new Color(1.88f, 1.88f, 1.88f, 1f)); + + var ambientLight = GameObject.Instantiate(GameObject.Find("WhiteHole_Body/WhiteHoleVisuals/AmbientLight_WH")); + ambientLight.transform.parent = whiteHole.transform; + ambientLight.transform.localScale = Vector3.one; + ambientLight.transform.localPosition = Vector3.zero; + ambientLight.name = "AmbientLight"; + ambientLight.GetComponent().range = size * 7f; + + GameObject whiteHoleVolumeGO = GameObject.Instantiate(GameObject.Find("WhiteHole_Body/WhiteHoleVolume")); + whiteHoleVolumeGO.transform.parent = whiteHole.transform; + whiteHoleVolumeGO.transform.localPosition = Vector3.zero; + whiteHoleVolumeGO.transform.localScale = Vector3.one; + whiteHoleVolumeGO.GetComponent().radius = size; + whiteHoleVolumeGO.name = "WhiteHoleVolume"; + + var whiteHoleFluidVolume = whiteHoleVolumeGO.GetComponent(); + whiteHoleFluidVolume._innerRadius = size * 0.5f; + whiteHoleFluidVolume._outerRadius = size; + whiteHoleFluidVolume._attachedBody = OWRB; + + var whiteHoleVolume = whiteHoleVolumeGO.GetComponent(); + whiteHoleVolume._debrisDistMax = size * 6.5f; + whiteHoleVolume._debrisDistMin = size * 2f; + whiteHoleVolume._whiteHoleSector = sector; + whiteHoleVolume._fluidVolume = whiteHoleFluidVolume; + whiteHoleVolume._whiteHoleBody = OWRB; + whiteHoleVolume._whiteHoleProxyShadowSuperGroup = body.GetComponent(); + + whiteHoleVolumeGO.GetComponent().radius = size; + + whiteHoleVolume.enabled = true; + whiteHoleFluidVolume.enabled = true; + + if(makeZeroGVolume) + { + var zeroGVolume = GameObject.Instantiate(GameObject.Find("WhiteHole_Body/ZeroGVolume"), whiteHole.transform); + zeroGVolume.name = "ZeroGVolume"; + zeroGVolume.transform.localPosition = Vector3.zero; + zeroGVolume.GetComponent().radius = size * 10f; + zeroGVolume.GetComponent()._attachedBody = OWRB; + + var rulesetVolume = GameObject.Instantiate(GameObject.Find("WhiteHole_Body/Sector_WhiteHole/RulesetVolumes_WhiteHole"), body.transform); + rulesetVolume.name = "RulesetVolume"; + rulesetVolume.transform.localPosition = Vector3.zero; + rulesetVolume.transform.localScale = Vector3.one * size / 100f; + rulesetVolume.GetComponent().enabled = true; + } + + whiteHole.SetActive(true); + return whiteHole; + } + } +} diff --git a/NewHorizons/Builder/General/BaseBuilder.cs b/NewHorizons/Builder/General/BaseBuilder.cs index 6c895799..5033daab 100644 --- a/NewHorizons/Builder/General/BaseBuilder.cs +++ b/NewHorizons/Builder/General/BaseBuilder.cs @@ -12,6 +12,8 @@ namespace NewHorizons.Builder.General { public static Tuple Make(GameObject body, AstroObject primaryBody, IPlanetConfig config) { + body.AddComponent(); + Rigidbody rigidBody = body.AddComponent(); rigidBody.mass = 10000; rigidBody.drag = 0f; @@ -38,6 +40,7 @@ namespace NewHorizons.Builder.General var type = AstroObject.Type.Planet; if (config.Orbit.IsMoon) type = AstroObject.Type.Moon; + else if (config.Base.IsSatellite) type = AstroObject.Type.Satellite; else if (config.Base.HasCometTail) type = AstroObject.Type.Comet; else if (config.Star != null) type = AstroObject.Type.Star; else if (config.FocalPoint != null) type = AstroObject.Type.None; diff --git a/NewHorizons/Builder/General/MarkerBuilder.cs b/NewHorizons/Builder/General/MarkerBuilder.cs index cb51de61..f24cbdcf 100644 --- a/NewHorizons/Builder/General/MarkerBuilder.cs +++ b/NewHorizons/Builder/General/MarkerBuilder.cs @@ -13,22 +13,26 @@ namespace NewHorizons.Builder.General MapMarker mapMarker = body.AddComponent(); mapMarker.SetValue("_labelID", (UITextType)Utility.AddToUITable.Add(name.ToUpper())); - var markerType = "Planet"; + var markerType = MapMarker.MarkerType.Planet; if (config.Orbit.IsMoon) { - markerType = "Moon"; + markerType = MapMarker.MarkerType.Moon; } else if (config.Star != null) { - markerType = "Sun"; + markerType = MapMarker.MarkerType.Sun; } else if (config.FocalPoint != null) { - markerType = "HourglassTwins"; + markerType = MapMarker.MarkerType.HourglassTwins; + } + else if(config.Base.IsSatellite) + { + markerType = MapMarker.MarkerType.Probe; } - mapMarker.SetValue("_markerType", mapMarker.GetType().GetNestedType("MarkerType", BindingFlags.NonPublic).GetField(markerType).GetValue(mapMarker)); + mapMarker._markerType = markerType; } } } diff --git a/NewHorizons/Builder/General/ShipLogBuilder.cs b/NewHorizons/Builder/General/ShipLogBuilder.cs new file mode 100644 index 00000000..1502b5e6 --- /dev/null +++ b/NewHorizons/Builder/General/ShipLogBuilder.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Builder.General +{ + public static class ShipLogBuilder + { + public static ShipLogDetectiveMode StarChartMode; + + public static void Init() + { + /* + var shipLogRoot = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas"); + var starChartLog = GameObject.Instantiate(shipLogRoot.transform.Find("DetectiveMode"), shipLogRoot.transform); + starChartLog.transform.name = "StarChartMode"; + + var cardRoot = starChartLog.transform.Find("ScaleRoot").Find("PanRoot"); + foreach(Transform child in cardRoot) + { + GameObject.Destroy(child.gameObject); + } + + var cardPrefab = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/DetectiveMode/ScaleRoot/PanRoot/TH_VILLAGE"); + + var detectiveMode = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/DetectiveMode/"); + var mapMode = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/MapMode/"); + + StarChartMode = starChartLog.GetComponent(); + + StarChartMode._cardDict = new Dictionary(); + StarChartMode._cardList = new List(); + StarChartMode._centerPromptList = detectiveMode.GetComponent()._centerPromptList; + */ + } + } +} diff --git a/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs b/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs index 13304cf7..b41e196f 100644 --- a/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs +++ b/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs @@ -32,13 +32,24 @@ namespace NewHorizons.Builder.Orbital if (config.Orbit.Tint != null) color = config.Orbit.Tint.ToColor32(); else if (config.Star != null) color = config.Star.Tint.ToColor32(); else if (config.Atmosphere != null && config.Atmosphere.CloudTint != null) color = config.Atmosphere.CloudTint.ToColor32(); - else if (config.Base.BlackHoleSize != 0) color = new Color(1f, 0.5f, 1f); + else if (config.Base.BlackHoleSize != 0 || config.Singularity != null) color = new Color(1f, 0.5f, 1f); else if (config.Base.WaterSize != 0) color = new Color(0.5f, 0.5f, 1f); else if (config.Base.LavaSize != 0) color = new Color(1f, 0.5f, 0.5f); + else if (config.Atmosphere != null && config.Atmosphere.FogTint != null) color = config.Atmosphere.FogTint.ToColor32(); + + var fade = isMoon; + if (config.Base.IsSatellite) + { + if(config.Orbit.Tint != null) color = new Color(0.4082f, 0.516f, 0.4469f, 1f); + fade = true; + orbitLine._fadeEndDist = 5000; + orbitLine._fadeStartDist = 3000; + } + orbitLine.SetValue("_color", color); orbitLine.SetValue("_astroObject", astroobject); - orbitLine.SetValue("_fade", isMoon); + orbitLine.SetValue("_fade", fade); orbitLine.SetValue("_lineWidth", 2f); Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => diff --git a/NewHorizons/Builder/Props/PropBuilder.cs b/NewHorizons/Builder/Props/PropBuilder.cs index 823e3d4c..c3707beb 100644 --- a/NewHorizons/Builder/Props/PropBuilder.cs +++ b/NewHorizons/Builder/Props/PropBuilder.cs @@ -9,39 +9,60 @@ using Random = UnityEngine.Random; using Logger = NewHorizons.Utility.Logger; using System.Reflection; using NewHorizons.Utility; +using OWML.Common; namespace NewHorizons.Builder.Props { public static class PropBuilder { - public static void Make(GameObject go, Sector sector, IPlanetConfig config) + public static void Make(GameObject go, Sector sector, IPlanetConfig config, IModAssets assets, string uniqueModName) { - if (config.Props.Scatter != null) PropBuilder.Scatter(go, config.Props.Scatter, config.Base.SurfaceSize, sector); + if (config.Props.Scatter != null) + { + PropBuilder.MakeScatter(go, config.Props.Scatter, config.Base.SurfaceSize, sector, assets, uniqueModName); + } if(config.Props.Details != null) { foreach(var detail in config.Props.Details) { - MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale); + if(detail.assetBundle != null) + { + var prefab = LoadPrefab(detail.assetBundle, detail.path, uniqueModName, assets); + MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal); + } + else if(detail.objFilePath != null) + { + try + { + var prefab = assets.Get3DObject(detail.objFilePath, detail.mtlFilePath); + prefab.SetActive(false); + MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal); + } + catch(Exception e) + { + Logger.LogError($"Could not load 3d object {detail.objFilePath} with texture {detail.mtlFilePath} : {e.Message}"); + } + } + else MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal); } } } - public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale) + public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) { var prefab = GameObject.Find(propToClone); - return MakeDetail(go, sector, prefab, position, rotation, scale); + + //TODO: this is super costly + if (prefab == null) prefab = SearchUtilities.FindObjectOfTypeAndName(propToClone.Split(new char[] { '\\', '/' }).Last()); + if (prefab == null) Logger.LogError($"Couldn't find detail {propToClone}"); + return MakeDetail(go, sector, prefab, position, rotation, scale, alignWithNormal); } - public static GameObject MakeDetail(GameObject go, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal = false) + public static GameObject MakeDetail(GameObject go, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal, bool snapToSurface = false) { if (prefab == null) return null; GameObject prop = GameObject.Instantiate(prefab, sector.transform); - prop.transform.localPosition = position == null ? prefab.transform.localPosition : (Vector3)position; - Quaternion rot = rotation == null ? prefab.transform.localRotation : Quaternion.Euler((Vector3)rotation); - if (alignWithNormal) rot = Quaternion.FromToRotation(prop.transform.TransformDirection(Vector3.up), ((Vector3)position).normalized); - prop.transform.rotation = rot; - prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale; prop.SetActive(false); List assetBundles = new List(); @@ -59,45 +80,54 @@ namespace NewHorizons.Builder.Props sector.OnOccupantEnterSector += ((SectorDetector sd) => StreamingManager.LoadStreamingAssets(assetBundle)); } - foreach(var component in prop.GetComponentsInChildren()) + foreach (var component in prop.GetComponentsInChildren()) { - try - { - var setSectorMethod = component.GetType().GetMethod("SetSector"); - var sectorField = component.GetType().GetField("_sector"); + // TODO: Make this work or smthng + if (component is GhostIK) (component as GhostIK).enabled = false; + if(component is GhostEffects) (component as GhostEffects).enabled = false; + - if (setSectorMethod != null) - { - Logger.Log($"Found a SetSector method in {prop}.{component}"); - setSectorMethod.Invoke(component, new object[] { sector }); - } - else if (sectorField != null) - { - Logger.Log($"Found a _sector field in {component}"); - sectorField.SetValue(component, sector); - } - } - catch (Exception e) { Logger.Log($"{e.Message}, {e.StackTrace}"); } + var enabledField = component.GetType().GetField("enabled"); + if(enabledField != null && enabledField.FieldType == typeof(bool)) enabledField.SetValue(component, true); } + prop.transform.parent = go.transform; + prop.transform.localPosition = position == null ? Vector3.zero : (Vector3)position; + + Quaternion rot = rotation == null ? prefab.transform.rotation : Quaternion.Euler((Vector3)rotation); + prop.transform.rotation = rot; + if (alignWithNormal) + { + var up = prop.transform.localPosition.normalized; + var front = Vector3.Cross(up, Vector3.left); + if (front.sqrMagnitude == 0f) front = Vector3.Cross(up, Vector3.forward); + if (front.sqrMagnitude == 0f) front = Vector3.Cross(up, Vector3.up); + + prop.transform.LookAt(prop.transform.position + front, up); + } + + prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale; + prop.SetActive(true); return prop; } - private static void Scatter(GameObject go, PropModule.ScatterInfo[] scatterInfo, float radius, Sector sector) + private static void MakeScatter(GameObject go, PropModule.ScatterInfo[] scatterInfo, float radius, Sector sector, IModAssets assets, string uniqueModName) { var area = 4f * Mathf.PI * radius * radius; var points = FibonacciSphere((int)area); foreach (var propInfo in scatterInfo) { - var prefab = GameObject.Find(propInfo.path); + GameObject prefab; + if (propInfo.assetBundle != null) prefab = LoadPrefab(propInfo.assetBundle, propInfo.path, uniqueModName, assets); + else prefab = GameObject.Find(propInfo.path); for(int i = 0; i < propInfo.count; i++) { var randomInd = (int)Random.Range(0, points.Count); var point = points[randomInd]; - var prop = MakeDetail(go, sector, prefab, (MVector3)(point.normalized * radius), null, 0f, true); + var prop = MakeDetail(go, sector, prefab, (MVector3)(point.normalized * radius), null, propInfo.scale, true, true); if(propInfo.offset != null) prop.transform.localPosition += prop.transform.TransformVector(propInfo.offset); if(propInfo.rotation != null) prop.transform.rotation *= Quaternion.Euler(propInfo.rotation); points.RemoveAt(randomInd); @@ -126,5 +156,40 @@ namespace NewHorizons.Builder.Props } return points; } + + private static GameObject LoadPrefab(string assetBundle, string path, string uniqueModName, IModAssets assets) + { + string key = uniqueModName + "." + assetBundle; + AssetBundle bundle; + GameObject prefab; + + try + { + if (Main.AssetBundles.ContainsKey(key)) bundle = Main.AssetBundles[key]; + else + { + bundle = assets.LoadBundle(assetBundle); + Main.AssetBundles[key] = bundle; + } + } + catch (Exception e) + { + Logger.LogError($"Couldn't load AssetBundle {assetBundle} : {e.Message}"); + return null; + } + + try + { + prefab = bundle.LoadAsset(path); + prefab.SetActive(false); + } + catch (Exception e) + { + Logger.Log($"Couldn't load asset {path} from AssetBundle {assetBundle} : {e.Message}"); + return null; + } + + return prefab; + } } } diff --git a/NewHorizons/Builder/Props/SignalBuilder.cs b/NewHorizons/Builder/Props/SignalBuilder.cs index f97ea0da..a028d5fe 100644 --- a/NewHorizons/Builder/Props/SignalBuilder.cs +++ b/NewHorizons/Builder/Props/SignalBuilder.cs @@ -1,6 +1,7 @@ using NewHorizons.Components; using NewHorizons.External; using NewHorizons.Utility; +using OWML.Common; using System; using System.Collections.Generic; using System.Linq; @@ -83,20 +84,19 @@ namespace NewHorizons.Builder.Props public static string GetCustomSignalName(SignalName signalName) { - string name = null; - _customSignalNames.TryGetValue(signalName, out name); + _customSignalNames.TryGetValue(signalName, out string name); return name; } - public static void Make(GameObject body, Sector sector, SignalModule module) + public static void Make(GameObject body, Sector sector, SignalModule module, IModAssets assets) { foreach(var info in module.Signals) { - Make(body, sector, info); + Make(body, sector, info, assets); } } - public static void Make(GameObject body, Sector sector, SignalModule.SignalInfo info) + public static void Make(GameObject body, Sector sector, SignalModule.SignalInfo info, IModAssets assets) { var signalGO = new GameObject($"Signal_{info.Name}"); signalGO.SetActive(false); @@ -107,15 +107,32 @@ namespace NewHorizons.Builder.Props var source = signalGO.AddComponent(); var owAudioSource = signalGO.AddComponent(); - AudioSignal audioSignal = null; + AudioSignal audioSignal; if (info.InsideCloak) audioSignal = signalGO.AddComponent(); else audioSignal = signalGO.AddComponent(); var frequency = StringToFrequency(info.Frequency); var name = StringToSignalName(info.Name); - AudioClip clip = SearchUtilities.FindResourceOfTypeAndName(info.AudioClip); - if (clip == null) return; + AudioClip clip = null; + if(info.AudioClip != null) clip = SearchUtilities.FindResourceOfTypeAndName(info.AudioClip); + else if (info.AudioFilePath != null) + { + try + { + clip = assets.GetAudio(info.AudioFilePath); + } + catch(Exception e) + { + Logger.LogError($"Couldn't load audio file {info.AudioFilePath} : {e.Message}"); + } + } + + if (clip == null) + { + Logger.LogError($"Couldn't find AudioClip {info.AudioClip} or AudioFile {info.AudioFilePath}"); + return; + } audioSignal.SetSector(sector); audioSignal._frequency = frequency; diff --git a/NewHorizons/Components/BlackHoleDestructionVolume.cs b/NewHorizons/Components/BlackHoleDestructionVolume.cs new file mode 100644 index 00000000..8c2d9ffc --- /dev/null +++ b/NewHorizons/Components/BlackHoleDestructionVolume.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Components +{ + public class BlackHoleDestructionVolume : DestructionVolume + { + public override void Awake() + { + base.Awake(); + _deathType = DeathType.BlackHole; + } + + public override void VanishProbe(OWRigidbody probeBody, RelativeLocationData entryLocation) + { + SurveyorProbe requiredComponent = probeBody.GetRequiredComponent(); + if (requiredComponent.IsLaunched()) + { + UnityEngine.Object.Destroy(requiredComponent.gameObject); + } + } + } +} + diff --git a/NewHorizons/Components/ChangeStarSystemVolume.cs b/NewHorizons/Components/ChangeStarSystemVolume.cs new file mode 100644 index 00000000..3a754057 --- /dev/null +++ b/NewHorizons/Components/ChangeStarSystemVolume.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.Components +{ + public class ChangeStarSystemVolume : BlackHoleDestructionVolume + { + public string TargetSolarSystem { get; set; } + + public override void VanishPlayer(OWRigidbody playerBody, RelativeLocationData entryLocation) + { + Main.Instance.ChangeCurrentStarSystem(TargetSolarSystem); + } + } +} diff --git a/NewHorizons/External/AsteroidBeltModule.cs b/NewHorizons/External/AsteroidBeltModule.cs index b2edb237..c275b376 100644 --- a/NewHorizons/External/AsteroidBeltModule.cs +++ b/NewHorizons/External/AsteroidBeltModule.cs @@ -13,5 +13,6 @@ namespace NewHorizons.External public float Inclination { get; set; } public float LongitudeOfAscendingNode { get; set; } public int RandomSeed { get; set; } + public ProcGenModule ProcGen { get; set; } } } diff --git a/NewHorizons/External/BaseModule.cs b/NewHorizons/External/BaseModule.cs index 8acbbd84..f382d9c6 100644 --- a/NewHorizons/External/BaseModule.cs +++ b/NewHorizons/External/BaseModule.cs @@ -16,10 +16,13 @@ namespace NewHorizons.External public float SurfaceSize { get; set; } public float WaterSize { get; set; } public float GroundSize { get; set; } - public float BlackHoleSize { get; set; } public float LavaSize { get; set; } public bool HasCometTail { get; set; } public bool HasReferenceFrame { get; set; } = true; public bool CenterOfSolarSystem { get; set; } = false; + public bool IsSatellite { get; set; } + + // Old, see SingularityModule instead + public float BlackHoleSize { get; set; } } } diff --git a/NewHorizons/External/IPlanetConfig.cs b/NewHorizons/External/IPlanetConfig.cs index 5f726a2a..db8f9af4 100644 --- a/NewHorizons/External/IPlanetConfig.cs +++ b/NewHorizons/External/IPlanetConfig.cs @@ -5,6 +5,7 @@ namespace NewHorizons.External public interface IPlanetConfig { string Name { get; } + string StarSystem { get; } bool Destroy { get; } int BuildPriority { get; } BaseModule Base {get;} @@ -19,5 +20,6 @@ namespace NewHorizons.External PropModule Props { get; } SpawnModule Spawn { get; } SignalModule Signal { get; } + SingularityModule Singularity { get; } } } diff --git a/NewHorizons/External/PlanetConfig.cs b/NewHorizons/External/PlanetConfig.cs index 1cefbd2f..357db378 100644 --- a/NewHorizons/External/PlanetConfig.cs +++ b/NewHorizons/External/PlanetConfig.cs @@ -8,6 +8,7 @@ namespace NewHorizons.External public class PlanetConfig : IPlanetConfig { public string Name { get; set; } + public string StarSystem { get; set; } = "SolarSystem"; public bool Destroy { get; set; } public int BuildPriority { get; set; } = -1; public MVector3 SpawnPoint { get; set; } @@ -23,6 +24,7 @@ namespace NewHorizons.External public PropModule Props { get; set; } public SpawnModule Spawn { get; set; } public SignalModule Signal { get; set; } + public SingularityModule Singularity { get; set; } public PlanetConfig(Dictionary dict) { diff --git a/NewHorizons/External/PropModule.cs b/NewHorizons/External/PropModule.cs index fee29eaa..7edc9cb9 100644 --- a/NewHorizons/External/PropModule.cs +++ b/NewHorizons/External/PropModule.cs @@ -15,18 +15,24 @@ namespace NewHorizons.External public class ScatterInfo { - public string path; public int count; + public string path; + public string assetBundle; public MVector3 offset; public MVector3 rotation; + public float scale { get; set; } = 1f; } public class DetailInfo { public string path; + public string objFilePath; + public string mtlFilePath; + public string assetBundle; public MVector3 position; public MVector3 rotation; - public float scale; + public float scale { get; set; } = 1f; + public bool alignToNormal; } } } diff --git a/NewHorizons/External/RingModule.cs b/NewHorizons/External/RingModule.cs index 1be64325..bcb35531 100644 --- a/NewHorizons/External/RingModule.cs +++ b/NewHorizons/External/RingModule.cs @@ -13,5 +13,6 @@ namespace NewHorizons.External public float Inclination { get; set; } public float LongitudeOfAscendingNode { get; set; } public string Texture { get; set; } + public bool Unlit { get; set; } = true; } } diff --git a/NewHorizons/External/SignalModule.cs b/NewHorizons/External/SignalModule.cs index ea4298c0..07a72252 100644 --- a/NewHorizons/External/SignalModule.cs +++ b/NewHorizons/External/SignalModule.cs @@ -16,7 +16,8 @@ namespace NewHorizons.External public MVector3 Position; public string Frequency; public string Name; - public string AudioClip; + public string AudioClip = null; + public string AudioFilePath = null; public float SourceRadius = 1f; public float DetectionRadius = 0f; public float IdentificationRadius = 10f; diff --git a/NewHorizons/External/SingularityModule.cs b/NewHorizons/External/SingularityModule.cs new file mode 100644 index 00000000..42fae1aa --- /dev/null +++ b/NewHorizons/External/SingularityModule.cs @@ -0,0 +1,18 @@ +using NewHorizons.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.External +{ + public class SingularityModule : Module + { + public float Size; + public string PairedSingularity; + public string TargetStarSystem; + public string Type; //BlackHole or WhiteHole + public MVector3 Position; + } +} diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index fdd0d363..50194d87 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -17,6 +17,7 @@ using System.Linq; using System.Reflection; using UnityEngine; using UnityEngine.SceneManagement; +using UnityEngine.UI; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons @@ -29,11 +30,12 @@ namespace NewHorizons public static List BodyList = new List(); public static List NextPassBodies = new List(); - + public static Dictionary AssetBundles = new Dictionary(); public static float FurthestOrbit { get; set; } = 50000f; - public StarLightController StarLightController { get; private set; } + private static string _currentStarSystem = "SolarSystem"; + public override object GetApi() { return new NewHorizonsApi(); @@ -57,6 +59,9 @@ namespace NewHorizons { Logger.LogWarning("Couldn't find planets folder"); } + + //UnityEngine.Random.InitState(); + Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => OnSceneLoaded(SceneManager.GetActiveScene(), LoadSceneMode.Single)); } public void OnDestroy() @@ -71,10 +76,14 @@ namespace NewHorizons HeavenlyBodyBuilder.Reset(); - if (scene.name != "SolarSystem") { return; } + if (scene.name.Equals("TitleScreen")) DisplayBodyOnTitleScreen(); + + if (scene.name != "SolarSystem") return; NewHorizonsData.Load(); + Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => ShipLogBuilder.Init()); + // Need to manage this when there are multiple stars var sun = GameObject.Find("Sun_Body"); var starController = sun.AddComponent(); @@ -99,7 +108,7 @@ namespace NewHorizons StarLightController = starLightGO.AddComponent(); StarLightController.AddStar(starController); - + starLightGO.SetActive(true); // TODO: Make this configurable probably @@ -115,8 +124,10 @@ namespace NewHorizons AstroObjectLocator.AddAstroObject(ao); } - // Stars then planets then moons (not necessary but probably speeds things up, maybe) - var toLoad = BodyList.OrderBy(b => + // Order by stars then planets then moons (not necessary but probably speeds things up, maybe) ALSO only include current star system + var toLoad = BodyList + .Where(b => b.Config.StarSystem.Equals(_currentStarSystem)) + .OrderBy(b => (b.Config.BuildPriority != -1 ? b.Config.BuildPriority : (b.Config.FocalPoint != null ? 0 : (b.Config.Star != null) ? 0 : @@ -174,6 +185,65 @@ namespace NewHorizons */ } + public void DisplayBodyOnTitleScreen() + { + //Try loading one planet why not + GameObject titleScreenGO = new GameObject("TitleScreenPlanet"); + var eligible = BodyList.Where(b => b.Config.Ring != null && (b.Config.HeightMap != null || (b.Config.Atmosphere?.Cloud != null))).ToArray(); + var body = eligible[UnityEngine.Random.Range(0, eligible.Count())]; + + Logger.Log($"Displaying {body.Config.Name} on the title screen"); + + var flag = false; + HeightMapModule heightMap = new HeightMapModule(); + var minSize = 20; + var maxSize = 35; + float size = minSize; + if (body.Config.HeightMap != null) + { + size = Mathf.Clamp(body.Config.HeightMap.MaxHeight / 10, minSize, maxSize); + heightMap.TextureMap = body.Config.HeightMap.TextureMap; + heightMap.HeightMap = body.Config.HeightMap.HeightMap; + heightMap.MaxHeight = size; + heightMap.MinHeight = body.Config.HeightMap.MinHeight * size / body.Config.HeightMap.MaxHeight; + flag = true; + } + if (body.Config.Atmosphere != null && body.Config.Atmosphere.Cloud != null) + { + // Hacky but whatever I just want a sphere + size = Mathf.Clamp(body.Config.Atmosphere.Size / 10, minSize, maxSize); + heightMap.MaxHeight = heightMap.MinHeight = size+1; + heightMap.TextureMap = body.Config.Atmosphere.Cloud; + flag = true; + } + + if (flag) + { + HeightMapBuilder.Make(titleScreenGO, heightMap, body.Assets); + if (body.Config.Ring != null) + { + RingModule newRing = new RingModule(); + newRing.InnerRadius = size * 1.2f; + newRing.OuterRadius = size * 2f; + newRing.Texture = body.Config.Ring.Texture; + RingBuilder.Make(titleScreenGO, newRing, body.Assets); + titleScreenGO.transform.localScale = Vector3.one * 0.8f; + } + GameObject.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire").SetActive(false); + GameObject.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false); + titleScreenGO.transform.parent = GameObject.Find("Scene/Background/PlanetPivot/").transform; + titleScreenGO.transform.localPosition = Vector3.zero; + + var lightGO = new GameObject("Light"); + lightGO.transform.parent = titleScreenGO.transform.parent.parent; + lightGO.transform.localPosition = new Vector3(-47.9203f, 145.7596f, 43.1802f); + var light = lightGO.AddComponent(); + light.color = new Color(1f, 1f, 1f, 1f); + light.range = 100; + light.intensity = 0.8f; + } + } + private bool LoadBody(NewHorizonsBody body, bool defaultPrimaryToSun = false) { var stringID = body.Config.Name.ToUpper().Replace(" ", "_").Replace("'", ""); @@ -238,7 +308,7 @@ namespace NewHorizons { var config = mod.ModHelper.Storage.Load(file.Replace(folder, "")); Logger.Log($"Loaded {config.Name}"); - BodyList.Add(new NewHorizonsBody(config, mod.ModHelper.Assets)); + BodyList.Add(new NewHorizonsBody(config, mod.ModHelper.Assets, mod.ModHelper.Manifest.UniqueName)); } catch (Exception e) { @@ -291,7 +361,7 @@ namespace NewHorizons if (body.Config.Base.GroundSize != 0) GeometryBuilder.Make(go, body.Config.Base.GroundSize); var atmoSize = body.Config.Atmosphere != null ? body.Config.Atmosphere.Size : 0f; - float sphereOfInfluence = Mathf.Max(atmoSize, body.Config.Base.SurfaceSize * 2f); + float sphereOfInfluence = Mathf.Max(Mathf.Max(atmoSize, 50), body.Config.Base.SurfaceSize * 2f); var outputTuple = BaseBuilder.Make(go, primaryBody, body.Config); var ao = (AstroObject)outputTuple.Item1; @@ -321,9 +391,6 @@ namespace NewHorizons if (body.Config.ProcGen != null) ProcGenBuilder.Make(go, body.Config.ProcGen); - if (body.Config.Base.BlackHoleSize != 0) - BlackHoleBuilder.Make(go, body.Config.Base, sector); - if (body.Config.Star != null) StarLightController.AddStar(StarBuilder.Make(go, sector, body.Config.Star)); if (body.Config.FocalPoint != null) @@ -369,7 +436,7 @@ namespace NewHorizons RingBuilder.Make(go, body.Config.Ring, body.Assets); if (body.Config.AsteroidBelt != null) - AsteroidBeltBuilder.Make(body.Config.Name, body.Config.AsteroidBelt, body.Assets); + AsteroidBeltBuilder.Make(body.Config.Name, body.Config, body.Assets, body.ModUniqueName); if (body.Config.Base.HasCometTail) CometTailBuilder.Make(go, body.Config.Base, go.GetComponent().GetPrimaryBody()); @@ -399,13 +466,22 @@ namespace NewHorizons } if (body.Config.Props != null) - PropBuilder.Make(go, sector, body.Config); + PropBuilder.Make(go, sector, body.Config, body.Assets, body.ModUniqueName); if (body.Config.Signal != null) - SignalBuilder.Make(go, sector, body.Config.Signal); + SignalBuilder.Make(go, sector, body.Config.Signal, body.Assets); + + if (body.Config.Base.BlackHoleSize != 0 || body.Config.Singularity != null) + SingularityBuilder.Make(go, sector, rb, body.Config); return go; } + + public void ChangeCurrentStarSystem(string newStarSystem) + { + _currentStarSystem = newStarSystem; + LoadManager.LoadSceneAsync(OWScene.SolarSystem, true, LoadManager.FadeType.ToBlack, 0.1f, true); + } } public class NewHorizonsApi @@ -421,7 +497,7 @@ namespace NewHorizons Logger.Log("Recieved API request to create planet " + (string)config["Name"], Logger.LogType.Log); var planetConfig = new PlanetConfig(config); - var body = new NewHorizonsBody(planetConfig, mod != null ? mod.ModHelper.Assets : Main.Instance.ModHelper.Assets); + var body = new NewHorizonsBody(planetConfig, mod != null ? mod.ModHelper.Assets : Main.Instance.ModHelper.Assets, mod.ModHelper.Manifest.UniqueName); Main.BodyList.Add(body); } diff --git a/NewHorizons/NewHorizons.csproj b/NewHorizons/NewHorizons.csproj index 24dfca23..ac738e27 100644 --- a/NewHorizons/NewHorizons.csproj +++ b/NewHorizons/NewHorizons.csproj @@ -25,6 +25,9 @@ Always + + + Always diff --git a/NewHorizons/Utility/DebugRaycaster.cs b/NewHorizons/Utility/DebugRaycaster.cs index 387d78f0..39537d07 100644 --- a/NewHorizons/Utility/DebugRaycaster.cs +++ b/NewHorizons/Utility/DebugRaycaster.cs @@ -1,4 +1,5 @@ -using System; +using NewHorizons.Builder.Body; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -13,6 +14,9 @@ namespace NewHorizons.Utility { private OWRigidbody _rb; + private GameObject blackHole; + private GameObject whiteHole; + private void Awake() { _rb = this.GetRequiredComponent(); @@ -34,6 +38,48 @@ namespace NewHorizons.Utility } _rb.EnableCollisionDetection(); } + + /* + // Portal Gun: + if (Keyboard.current == null) return; + var fireBlackHole = Keyboard.current[Key.B].wasReleasedThisFrame; + var fireWhiteHole = Keyboard.current[Key.N].wasReleasedThisFrame; + if (fireBlackHole || fireWhiteHole) + { + // Raycast + _rb.DisableCollisionDetection(); + int layerMask = OWLayerMask.physicalMask; + var origin = Locator.GetActiveCamera().transform.position; + var direction = Locator.GetActiveCamera().transform.TransformDirection(Vector3.forward); + if (Physics.Raycast(origin, direction, out RaycastHit hitInfo, Mathf.Infinity, OWLayerMask.physicalMask)) + { + var pos = hitInfo.transform.InverseTransformPoint(hitInfo.point + hitInfo.normal); + var hitBody = hitInfo.transform.gameObject; + var sector = hitBody.GetComponent()?.GetRootSector(); + + if (hitBody == null || sector == null) return; + Logger.Log($"{hitBody}"); + if (fireBlackHole) + { + if (blackHole != null) GameObject.Destroy(blackHole); + blackHole = SingularityBuilder.MakeBlackHole(hitBody, sector, pos, 2, false, null, false); + Logger.Log("Make black hole"); + } + else + { + if (whiteHole != null) GameObject.Destroy(whiteHole); + whiteHole = SingularityBuilder.MakeWhiteHole(hitBody, sector, hitBody.GetAttachedOWRigidbody(), pos, 2, false); + Logger.Log("Make white hole"); + } + + if(blackHole && whiteHole) + { + SingularityBuilder.PairSingularities(blackHole, whiteHole); + } + } + _rb.EnableCollisionDetection(); + } + */ } } } diff --git a/NewHorizons/Utility/NewHorizonBody.cs b/NewHorizons/Utility/NewHorizonBody.cs index 39bb008b..73e494c1 100644 --- a/NewHorizons/Utility/NewHorizonBody.cs +++ b/NewHorizons/Utility/NewHorizonBody.cs @@ -6,14 +6,16 @@ namespace NewHorizons.Utility { public class NewHorizonsBody { - public NewHorizonsBody(IPlanetConfig config, IModAssets assets) + public NewHorizonsBody(IPlanetConfig config, IModAssets assets, string modUniqueName) { Config = config; Assets = assets; + ModUniqueName = modUniqueName; } public IPlanetConfig Config; public IModAssets Assets; + public string ModUniqueName; public GameObject Object; } diff --git a/NewHorizons/Utility/Patches.cs b/NewHorizons/Utility/Patches.cs index 8742b1be..3f3a6532 100644 --- a/NewHorizons/Utility/Patches.cs +++ b/NewHorizons/Utility/Patches.cs @@ -1,4 +1,5 @@ -using NewHorizons.Builder.Props; +using NewHorizons.Builder.General; +using NewHorizons.Builder.Props; using NewHorizons.Components; using NewHorizons.External; using OWML.Common; @@ -43,6 +44,12 @@ namespace NewHorizons.Utility var playerDataResetGame = typeof(PlayerData).GetMethod("ResetGame"); Main.Instance.ModHelper.HarmonyHelper.AddPostfix(playerDataResetGame, typeof(Patches), nameof(Patches.OnPlayerDataResetGame)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Start", typeof(Patches), nameof(Patches.OnBlackHoleVolumeStart)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Awake", typeof(Patches), nameof(Patches.OnWhiteHoleVolumeAwake)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("UpdateOrbitalLaunchValues", typeof(Patches), nameof(Patches.OnProbeLauncherUpdateOrbitalLaunchValues)); + + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Update", typeof(Patches), nameof(Patches.OnShipLogControllerUpdate)); + // Postfixes Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Awake", typeof(Patches), nameof(Patches.OnMapControllerAwake)); Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Awake", typeof(Patches), nameof(Patches.OnOWCameraAwake)); @@ -306,5 +313,61 @@ namespace NewHorizons.Utility NewHorizonsData.Reset(); } #endregion + + public static bool OnBlackHoleVolumeStart(BlackHoleVolume __instance) + { + return __instance._whiteHole == null; + } + + public static bool OnWhiteHoleVolumeAwake(WhiteHoleVolume __instance) + { + __instance._growQueue = new List(8); + __instance._growQueueLocationData = new List(8); + __instance._ejectedBodyList = new List(64); + try + { + __instance._whiteHoleBody = __instance.gameObject.GetAttachedOWRigidbody(false); + __instance._whiteHoleProxyShadowSuperGroup = __instance._whiteHoleBody.GetComponentInChildren(); + __instance._fluidVolume = __instance.gameObject.GetRequiredComponent(); + } + catch (Exception) { } + return false; + } + + public static bool OnProbeLauncherUpdateOrbitalLaunchValues(ProbeLauncher __instance) + { + return (Locator.GetPlayerRulesetDetector()?.GetPlanetoidRuleset()?.GetGravityVolume() != null); + } + + public static bool OnShipLogControllerUpdate(ShipLogController __instance) + { + if (__instance._exiting + || OWInput.GetInputMode() != InputMode.ShipComputer + || __instance._currentMode.AllowCancelInput() && OWInput.IsNewlyPressed(InputLibrary.cancel, InputMode.All) + || ShipLogBuilder.StarChartMode == null) + return true; + + __instance._exitPrompt.SetVisibility(__instance._currentMode.AllowCancelInput()); + __instance._currentMode.UpdateMode(); + if (__instance._currentMode.AllowModeSwap() && OWInput.IsNewlyPressed(InputLibrary.swapShipLogMode, InputMode.All)) + { + ShipLogMode currentMode = __instance._currentMode; + string focusedEntryID = currentMode.GetFocusedEntryID(); + bool flag = currentMode.Equals(__instance._mapMode); + __instance._currentMode = (flag ? __instance._detectiveMode : __instance._mapMode); + + if (currentMode.Equals(__instance._mapMode)) + __instance._currentMode = ShipLogBuilder.StarChartMode; + else if (currentMode.Equals(ShipLogBuilder.StarChartMode)) + __instance._currentMode = __instance._detectiveMode; + else + __instance._currentMode = __instance._mapMode; + + currentMode.ExitMode(); + __instance._currentMode.EnterMode(focusedEntryID, null); + __instance._oneShotSource.PlayOneShot(flag ? global::AudioType.ShipLogEnterDetectiveMode : global::AudioType.ShipLogEnterMapMode, 1f); + } + return false; + } } } diff --git a/NewHorizons/Utility/SearchUtilities.cs b/NewHorizons/Utility/SearchUtilities.cs index a211fba9..7eee7333 100644 --- a/NewHorizons/Utility/SearchUtilities.cs +++ b/NewHorizons/Utility/SearchUtilities.cs @@ -10,7 +10,7 @@ namespace NewHorizons.Utility { public static class SearchUtilities { - public static List FindObjectsOfTypeAndName(string name) where T : MonoBehaviour + public static List FindObjectsOfTypeAndName(string name) where T : Object { T[] firstList = GameObject.FindObjectsOfType(); List finalList = new List(); @@ -26,6 +26,22 @@ namespace NewHorizons.Utility return finalList; } + public static T FindObjectOfTypeAndName(string name) where T : Object + { + T[] firstList = GameObject.FindObjectsOfType(); + List finalList = new List(); + + for (var i = 0; i < firstList.Length; i++) + { + if (firstList[i].name == name) + { + return firstList[i]; + } + } + + return null; + } + public static List FindResourcesOfTypeAndName(string name) where T : Object { T[] firstList = Resources.FindObjectsOfTypeAll(); diff --git a/NewHorizons/manifest.json b/NewHorizons/manifest.json index 60683163..6cbdf713 100644 --- a/NewHorizons/manifest.json +++ b/NewHorizons/manifest.json @@ -3,7 +3,7 @@ "author": "xen", "name": "New Horizons", "uniqueName": "xen.NewHorizons", - "version": "0.3.1", + "version": "0.4.0", "owmlVersion": "2.1.0", "dependencies": [ "PacificEngine.OW_CommonResources" ] } diff --git a/README.md b/README.md index bba84705..b43f49a0 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,15 @@ ![new horizons thumbnail](https://user-images.githubusercontent.com/22628069/146680547-bd815057-9f4e-42da-a6c4-84d3ff82ff2c.png) +![Current version](https://img.shields.io/github/manifest-json/v/xen-42/outer-wilds-new-horizons?color=gree&filename=NewHorizons%2Fmanifest.json) +![Downloads](https://img.shields.io/github/downloads/xen-42/outer-wilds-new-horizons/total) +![Downloads of newest version](https://img.shields.io/github/downloads/xen-42/outer-wilds-new-horizons/latest/total) A planet creator for Outer Wilds. -Planets are created using a JSON file format structure, and placed in the `planets` folder. +You can view the addons creators have made [here](https://outerwildsmods.com/mods/newhorizons/addons/)! + +Planets are created using a JSON file format structure, and placed in the `planets` folder (or in any sub-directory of it). + +NOTE: Any mod that requires PacificEngine's CommonResources is not compatible with New Horizons currently. Both mods mess with planets and orbits and end up clashing. We're currently working on a solution. @@ -15,9 +22,14 @@ Planets are created using a JSON file format structure, and placed in the `plane - [AsteroidBelt](#asteroidbelt) - [FocalPoint](#focalpoint) - [Props](#props) + - [Asset Bundles](#asset-bundles) + - [Ring](#ring) - [Spawn](#spawn) - [Star](#star) + - [Signal](#signal) + - [Singularity](#singularity) - [How to destroy existing planets](#how-to-destroy-existing-planets) + - [How to update existing planets](#how-to-update-existing-planets) - [How to use New Horizons in other mods](#how-to-use-new-horizons-in-other-mods) - [Credits](#credits) @@ -31,14 +43,14 @@ Planets are created using a JSON file format structure, and placed in the `plane - Comets (Done) - Signalscope signals (Done) - Asteroid belts (Done) +- Support satellites (Done) +- Surface scatter: rocks, trees, etc, using in-game models (done) or custom ones (done) +- Load planet meshes from asset bundle (technically done) +- Black hole / white hole pairs (done) - Procedurally terrain generation (started) -- Support satellites (using custom models in the assets folder or in-game ones) -- Surface scatter: rocks, trees, etc, using in-game models (done) or custom ones -- Load planet meshes from asset bundle - "Quantum" planet parameters - Better terrain and water LOD - Edit existing planet orbits -- Black hole / white hole pairs - Separate solar system scenes accessible via wormhole - Implement all planet features: - Tornados @@ -177,7 +189,7 @@ Some of these I don't explain since they are just orbital parameters. If you don - "longitudeOfAscendingNode" : (decimal number) - "argumentOfPeriapsis" : (decimal number) - "eccentricity" : (decimal number from 0 to < 1) The closer to 1 it is, the more oval-shaped the orbit is. -- "trueAnomaly" : (decimal number) Where the planet should start off in its orbit in terms of the central angle. From 0 to 360. +- "trueAnomaly" : (decimal number) Where the planet should start off in its orbit in terms of the central angle. From 0 to 360. NOTE: This is currently broken for eccentric orbits which (for now) always start at periapsis. If you want to move the starting point, set argument of periapsis instead. - "axialTilt" : (decimal number) - "siderealPeriod" : (decimal number) - "isTidallyLocked" : (true/false) @@ -282,9 +294,9 @@ and The positions of the binaries will be based off of their masses (as determined by the "surfaceGravity" parameter). However, one of them must have a non-zero semiMajorAxis field else the mod gets confused. This example uses stars, but it will also work for planets. If you want to have other planets orbiting the center of mass, just put the focal point body as the primary body. ### Props -Lets you place items on the surface of the planet. Currently this is a very early release version. +Lets you place items on the surface of the planet. --scatter : (list) I'll just give an example. +- "scatter" : (list) I'll just give an example. ``` "scatter" : [ @@ -294,6 +306,49 @@ Lets you place items on the surface of the planet. Currently this is a very earl The path is in the hierarchy of the solar system. Use the [Unity Explorer](https://outerwildsmods.com/mods/unityexplorer) mod to find an object you want to copy onto your new body. Some objects work better than others for this. Good luck. +- "details" : (list of detail info objects) + +A detail info object can have the following parameters: +- "path" : (string) either the location of it in the scene hierarchy or in the asset bundle provided +- "assetBundle" : (string) the asset bundle containing the object +- "objFilePath" : (string) the file path to a .obj 3d model +- "mtlFilePath" : (string) the file path to the material for the .obj model +- "position" : (x, y, z) +- "rotation" : (x, y, z) the euler angle rotation from a 3d vector +- "scale" : (decimal number) +- "alignToNormal" : (true/false) If it should align with the normal vector of the surface its own (overwrites rotation) + +You have three options: Load from the scene hierarchy by setting "path", load from an asset bundle by setting "path" and "assetBundle", or load an obj file by setting "objFilePath" and "mtlFilePath". Asset bundles give much better results than .obj's. + +#### Asset Bundles +1. Start up a Unity 2017 project (I use Unity 2017.4.40f1 (64-bit), so if you use something else I can't guarantee it will work). +2. In the root directory create a folder called "Editor". In it create a file called "CreateAssetBundle.cs" with the following code in it: +``` +using UnityEditor; +using UnityEngine; +using System.IO; + +public class CreateAssetBundles +{ + [MenuItem("Assets/Build AssetBundles")] + static void BuildAllAssetBundles() + { + string assetBundleDirectory = "Assets/StreamingAssets"; + if (!Directory.Exists(Application.streamingAssetsPath)) + { + Directory.CreateDirectory(assetBundleDirectory); + } + BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64); + } +} +``` +3. Create your object in the Unity scene and save it as a prefab. +4. Add all files used (models, prefabs, textures, materials, etc) to an asset bundle by selecting them and using the drop down in the bottom right. Here I am adding a rover model to my "rss" asset bundle for the Real Solar System add-on. +![setting asset bundle](https://user-images.githubusercontent.com/22628069/147954146-e1d610c0-0336-428f-8b32-bfc01090061c.png) + +5. In the top left click the "Assets" drop-down and select "Build AssetBundles". This should create your asset bundle in a folder in the root directory called "StreamingAssets". +6. Copy the asset bundle and asset bundle .manifest files from StreamingAssets into your mod's "planets" folder. If you did everything properly they should work in game. To double check everything is included, open the .manifest file in a text editor to see the files included and their paths. + ### Ring - "innerRadius" : (decimal number) - "outerRadius" : (decimal number) @@ -312,6 +367,47 @@ Use this if you are creating a star. - "tint" : (colour) - "solarFlareTint" : (colour) The flares are tinted weirdly so this won't make the actual colour of the star. You'll want to use trial and error to find something that matches. +### Signal +- "signals" : (list of signal info objects) + +Signal info objects can then have the following values set: +- "position" : (position) To find a good value for this, fly to the planet, look directly at where you want the signal to come from, and press "P" to have the game log the position you're looking at. +- "frequency" : (string) There are 7 acceptible values for this: + - "Default" : appears in game as ??? + - "Traveler" : appears in game as "Outer Wilds Ventures" + - "Quantum" : appears in game as "Quantum Fluctuations" + - "EscapePod" : appears in game as "Distress Signal" + - "Statue" : appears in game as "Nomai Statue" + - "WarpCore" : appears in game as "Anti-Graviton Flux" + - "HideAndSeek" : appears in game as "Hide and Seek" + - "Radio" : appears in game as "Deep Space Radio" +- "name" : (string) The name as it will appear in game +- "audioClip" : (string) The audio clip from the game you want to use (can find these using Unity Explorer or by datamining) +- "audioFilePath" : (string) The file path to a .wav you want to use as the audio clip +- "sourceRadius" : (decimal number) The radius of the spherical volume the signal appears to come from +- "detectionRadius" : (decimal number) How close you must be to get the "Unidentified signal detected" pop-up +- "identiicationRadius" : (decimal number) How close you must get to identify the signal +- "onlyAudibleToScope" : (true/false) +- "insideCloak" : (true/false) You have to set this to true if the signal is inside a cloaking field + +Here's an example of what all this looks like, for more check my [Signals+](https://github.com/xen-42/outer-wilds-signals-plus) add-on: +``` +"Signal" : +{ + "Signals" : + [ + { "Frequency" : "Statue", "Name" : "Museum Statue", "AudioClip" : "OW NM Flashback 082818 AP loop", "SourceRadius" : 1, "Position" : {"x": -76.35, "y": 12, "z": 214.7 } }, + { "Frequency" : "WarpCore", "Name" : "Timber Hearth Receiver", "AudioClip" : "OW_NM_WhiteHoleAmbienceL", "SourceRadius" : 0.5, "Position" : {"x": -237.8, "y": -50.8, "z": -59.2 } } + ] +} +``` + +### Singularity +This allows you to make black holes and white holes, and to pair them. +- "size" : (decimal number) +- "pairedSingularity" : (string) The singularity you want this one to pair to. Must be the opposite type. If you don't set this, the singularity will not transport you, and if it is a black hole it will kill you on entry. +- "type" : (string) Put either "BlackHole" or "WhiteHole". + ### How to destroy existing planets You do this (but with the appropriate name) as it's own config. @@ -322,7 +418,13 @@ You do this (but with the appropriate name) as it's own config. } ``` -Remember that if you destroy Timber Hearth you better put a [Spawn](#spawn) module on another planet. I haven't tried destroying the sun. Probably don't do that, it will break everything. Probably. +Remember that if you destroy Timber Hearth you better put a [Spawn](#spawn) module on another planet. If you want to entirely replace the solar system you can restroy everything, including the sun. You can use the prefabs from my [Real Solar System](https://github.com/xen-42/outer-wilds-real-solar-system) addon, in the `planets/0 - original planets` folder. Also, deleting a planet destroys anything orbiting it, so if you want to replace the solar system you can just destroy the sun. + +### How to update existing planets + +Similar to above, make a config where "Name" is the name of the planet. The name should be able to just match their in-game english names, however if you encounter any issues with that here are the in-code names for planets that are guaranteed to work: `Sun`, `CaveTwin` (Ember Twin), `TowerTwin` (Ash Twin), `TimberHearth`, `BrittleHollow`, `GiantsDeep`, `DarkBramble`, `Comet` (Interloper), `WhiteHole`, `WhiteHoleTarget` (Whitehole station I believe), `QuantumMoon`, `ProbeCannon`, `TimberMoon` (Attlerock), `VolcanicMoon` (Hollow's Lantern), `DreamWorld`, `MapSatellite`, `RingWorld` (the Stranger). + +Only some of the above modules are supported (currently) for existing planets. Things you cannot modify for existing planets include: heightmaps, procedural generation, gravity, or their orbits. You also can't make them into stars or binary focal points (but why would you want to, just delete them and replace them entirely). However this still means there are many things you can do: completely change their atmospheres, give them rings, asteroid belts, comet tails, lava, water, prop details, or signals. ## How to use New Horizons in other mods