diff --git a/NewHorizons/AchievementsPlus/AchievementHandler.cs b/NewHorizons/AchievementsPlus/AchievementHandler.cs index 0a6938a4..da9014f8 100644 --- a/NewHorizons/AchievementsPlus/AchievementHandler.cs +++ b/NewHorizons/AchievementsPlus/AchievementHandler.cs @@ -1,7 +1,6 @@ using NewHorizons.External.Configs; using NewHorizons.Utility; using OWML.ModHelper; -using System; using System.Collections.Generic; using System.Linq; diff --git a/NewHorizons/Builder/Atmosphere/EffectsBuilder.cs b/NewHorizons/Builder/Atmosphere/EffectsBuilder.cs index 6094f256..1ff3df9e 100644 --- a/NewHorizons/Builder/Atmosphere/EffectsBuilder.cs +++ b/NewHorizons/Builder/Atmosphere/EffectsBuilder.cs @@ -21,7 +21,7 @@ namespace NewHorizons.Builder.Atmosphere if (info.isRaining) { - var rainGO = GameObject.Instantiate(SearchUtilities.CachedFind("/GiantsDeep_Body/Sector_GD/Sector_GDInterior/Effects_GDInterior/Effects_GD_Rain"), effectsGO.transform); + var rainGO = GameObject.Instantiate(SearchUtilities.Find("GiantsDeep_Body/Sector_GD/Sector_GDInterior/Effects_GDInterior/Effects_GD_Rain"), effectsGO.transform); rainGO.transform.position = planetGO.transform.position; var pvc = rainGO.GetComponent(); @@ -44,7 +44,7 @@ namespace NewHorizons.Builder.Atmosphere snowGO.transform.position = planetGO.transform.position; for (int i = 0; i < 5; i++) { - var snowEmitter = GameObject.Instantiate(SearchUtilities.CachedFind("/BrittleHollow_Body/Sector_BH/Effects_BH/Effects_BH_Snowflakes"), snowGO.transform); + var snowEmitter = GameObject.Instantiate(SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Effects_BH/Effects_BH_Snowflakes"), snowGO.transform); snowEmitter.name = "SnowEmitter"; snowEmitter.transform.position = planetGO.transform.position; diff --git a/NewHorizons/Builder/Atmosphere/SunOverrideBuilder.cs b/NewHorizons/Builder/Atmosphere/SunOverrideBuilder.cs index 33ebcca3..df696f4d 100644 --- a/NewHorizons/Builder/Atmosphere/SunOverrideBuilder.cs +++ b/NewHorizons/Builder/Atmosphere/SunOverrideBuilder.cs @@ -1,21 +1,43 @@ -using NewHorizons.External.Modules; +using NewHorizons.External.Modules; +using NewHorizons.External.Modules.VariableSize; using UnityEngine; namespace NewHorizons.Builder.Atmosphere { public static class SunOverrideBuilder { - public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atmo, float surfaceSize) + public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atmo, WaterModule water, float surfaceSize) { GameObject overrideGO = new GameObject("SunOverride"); overrideGO.SetActive(false); overrideGO.transform.parent = sector?.transform ?? planetGO.transform; - GiantsDeepSunOverrideVolume GDSOV = overrideGO.AddComponent(); - GDSOV._sector = sector; - GDSOV._cloudsOuterRadius = atmo.size; - GDSOV._cloudsInnerRadius = atmo.size * 0.9f; - GDSOV._waterOuterRadius = surfaceSize; - GDSOV._waterInnerRadius = 0f; + if (water != null) + { + var GDSOV = overrideGO.AddComponent(); + GDSOV._sector = sector; + GDSOV._cloudsOuterRadius = atmo.clouds.outerCloudRadius; + GDSOV._cloudsInnerRadius = atmo.clouds.innerCloudRadius; + GDSOV._waterOuterRadius = water.size; + GDSOV._waterInnerRadius = 0f; + } + else + { + var sunOverride = overrideGO.AddComponent(); + sunOverride._sector = sector; + + sunOverride._overrideColor = true; + sunOverride._color = Color.black; + + sunOverride._overrideIntensity = true; + sunOverride._intensity = 0f; + + sunOverride._overrideShadowStrength = true; + sunOverride._shadowStrength = 1f; + + sunOverride.shape = SimpleVolume.Shape.Sphere; + sunOverride.height = 2; + sunOverride.radius = atmo.clouds.innerCloudRadius; + } overrideGO.transform.position = planetGO.transform.position; overrideGO.SetActive(true); diff --git a/NewHorizons/Builder/Body/ProxyBuilder.cs b/NewHorizons/Builder/Body/ProxyBuilder.cs index 1c8f08ab..817f57cf 100644 --- a/NewHorizons/Builder/Body/ProxyBuilder.cs +++ b/NewHorizons/Builder/Body/ProxyBuilder.cs @@ -62,7 +62,7 @@ namespace NewHorizons.Builder.Body } if (body.Config.Star != null) { - var starGO = StarBuilder.MakeStarProxy(planetGO, newProxy, body.Config.Star); + var starGO = StarBuilder.MakeStarProxy(planetGO, newProxy, body.Config.Star, body.Mod); if (realSize < body.Config.Star.size) realSize = body.Config.Star.size; } @@ -93,18 +93,21 @@ namespace NewHorizons.Builder.Body if (realSize < body.Config.Sand.size) realSize = body.Config.Sand.size; } // Could improve this to actually use the proper renders and materials - if (body.Config.Singularity != null) + if (body.Config.Props?.singularities != null) { - if (body.Config.Singularity.type == SingularityModule.SingularityType.BlackHole) + foreach(var singularity in body.Config.Props.singularities) { - MakeBlackHole(newProxy, body.Config.Singularity.size); - } - else - { - MakeWhiteHole(newProxy, body.Config.Singularity.size); - } + if (singularity.type == SingularityModule.SingularityType.BlackHole) + { + MakeBlackHole(newProxy, singularity.size); + } + else + { + MakeWhiteHole(newProxy, singularity.size); + } - if (realSize < body.Config.Singularity.size) realSize = body.Config.Singularity.size; + if (realSize < singularity.size) realSize = singularity.size; + } } if (body.Config.Base.hasCometTail) { diff --git a/NewHorizons/Builder/Body/RingBuilder.cs b/NewHorizons/Builder/Body/RingBuilder.cs index ff464bfc..55d84c04 100644 --- a/NewHorizons/Builder/Body/RingBuilder.cs +++ b/NewHorizons/Builder/Body/RingBuilder.cs @@ -1,4 +1,4 @@ -using NewHorizons.Components; +using NewHorizons.Components; using NewHorizons.Components.SizeControllers; using NewHorizons.Utility; using OWML.Common; @@ -45,7 +45,7 @@ namespace NewHorizons.Builder.Body var trigger = ringVolume.AddComponent(); trigger._shape = ringShape; - var sfv = ringVolume.AddComponent(); + var sfv = ringVolume.AddComponent(); var fluidType = FluidVolume.Type.NONE; try diff --git a/NewHorizons/Builder/Body/SingularityBuilder.cs b/NewHorizons/Builder/Body/SingularityBuilder.cs index b9a031f6..ef261d82 100644 --- a/NewHorizons/Builder/Body/SingularityBuilder.cs +++ b/NewHorizons/Builder/Body/SingularityBuilder.cs @@ -5,6 +5,9 @@ using System; using NewHorizons.External.Modules.VariableSize; using UnityEngine; using Logger = NewHorizons.Utility.Logger; +using System.Collections.Generic; +using System.Linq; + namespace NewHorizons.Builder.Body { public static class SingularityBuilder @@ -18,61 +21,73 @@ namespace NewHorizons.Builder.Body private static readonly int DistortFadeDist = Shader.PropertyToID("_DistortFadeDist"); private static readonly int Color1 = Shader.PropertyToID("_Color"); - public static void Make(GameObject go, Sector sector, OWRigidbody OWRB, PlanetConfig config) + private static Dictionary _singularitiesByID; + + public static void Make(GameObject go, Sector sector, OWRigidbody OWRB, PlanetConfig config, SingularityModule singularity) { - var size = config.Singularity.size; - var pairedSingularity = config.Singularity.pairedSingularity; + // If we've reloaded the first one will now be null so we have to refresh the list + if (_singularitiesByID?.Values?.FirstOrDefault() == null) _singularitiesByID = new Dictionary(); - var polarity = config.Singularity.type; + var size = singularity.size; + var pairedSingularity = singularity.pairedSingularity; - bool isWormHole = config.Singularity?.targetStarSystem != null; + var polarity = singularity.type; + + bool isWormHole = singularity?.targetStarSystem != null; bool hasHazardVolume = !isWormHole && (pairedSingularity == null); - bool makeZeroGVolume = config.Singularity == null ? true : config.Singularity.makeZeroGVolume; + bool makeZeroGVolume = singularity == null ? true : singularity.makeZeroGVolume; - Vector3 localPosition = config.Singularity?.position == null ? Vector3.zero : (Vector3)config.Singularity.position; + Vector3 localPosition = singularity?.position == null ? Vector3.zero : singularity.position; GameObject newSingularity = null; switch (polarity) { case SingularityModule.SingularityType.BlackHole: - newSingularity = MakeBlackHole(go, sector, localPosition, size, hasHazardVolume, config.Singularity.targetStarSystem); + newSingularity = MakeBlackHole(go, sector, localPosition, size, hasHazardVolume, singularity.targetStarSystem); break; case SingularityModule.SingularityType.WhiteHole: newSingularity = MakeWhiteHole(go, sector, OWRB, localPosition, size, makeZeroGVolume); break; } + var uniqueID = string.IsNullOrEmpty(singularity.uniqueID) ? config.name : singularity.uniqueID; + _singularitiesByID.Add(uniqueID, newSingularity); + // Try to pair them - if (pairedSingularity != null && newSingularity != null) + if (!string.IsNullOrEmpty(pairedSingularity) && newSingularity != null) { - var pairedSingularityAO = AstroObjectLocator.GetAstroObject(pairedSingularity); - if (pairedSingularityAO != null) + if (_singularitiesByID.TryGetValue(pairedSingularity, out var pairedSingularityGO)) { switch (polarity) { case SingularityModule.SingularityType.BlackHole: - PairSingularities(newSingularity, pairedSingularityAO.gameObject); + PairSingularities(uniqueID, pairedSingularity, newSingularity, pairedSingularityGO); break; case SingularityModule.SingularityType.WhiteHole: - PairSingularities(pairedSingularityAO.gameObject, newSingularity); + PairSingularities(pairedSingularity, uniqueID, pairedSingularityGO, newSingularity); break; } } } } - public static void PairSingularities(GameObject blackHole, GameObject whiteHole) + public static void PairSingularities(string blackHoleID, string whiteHoleID, GameObject blackHole, GameObject whiteHole) { - Logger.Log($"Pairing singularities {blackHole?.name}, {whiteHole?.name}"); - try + if (blackHole == null || whiteHole == null) return; + + Logger.Log($"Pairing singularities [{blackHoleID}], [{whiteHoleID}]"); + + var whiteHoleVolume = whiteHole.GetComponentInChildren(); + var blackHoleVolume = blackHole.GetComponentInChildren(); + + if (whiteHoleVolume == null || blackHoleVolume == null) { - blackHole.GetComponentInChildren()._whiteHole = whiteHole.GetComponentInChildren(); - } - catch (Exception) - { - Logger.LogError($"Couldn't pair singularities"); + Logger.Log($"[{blackHoleID}] and [{whiteHoleID}] do not have compatible polarities"); + return; } + + blackHoleVolume._whiteHole = whiteHoleVolume; } public static GameObject MakeBlackHole(GameObject planetGO, Sector sector, Vector3 localPosition, float size, bool hasDestructionVolume, string targetSolarSystem, bool makeAudio = true) diff --git a/NewHorizons/Builder/Body/StarBuilder.cs b/NewHorizons/Builder/Body/StarBuilder.cs index ec728ead..05fcaa35 100644 --- a/NewHorizons/Builder/Body/StarBuilder.cs +++ b/NewHorizons/Builder/Body/StarBuilder.cs @@ -5,6 +5,8 @@ using OWML.Utils; using UnityEngine; using NewHorizons.External.Modules.VariableSize; using Logger = NewHorizons.Utility.Logger; +using OWML.ModHelper; +using OWML.Common; namespace NewHorizons.Builder.Body { @@ -19,9 +21,9 @@ namespace NewHorizons.Builder.Body private static readonly int InnerRadius = Shader.PropertyToID("_InnerRadius"); private static readonly int OuterRadius = Shader.PropertyToID("_OuterRadius"); - public static StarController Make(GameObject planetGO, Sector sector, StarModule starModule) + public static StarController Make(GameObject planetGO, Sector sector, StarModule starModule, IModBehaviour mod) { - var starGO = MakeStarGraphics(planetGO, sector, starModule); + var starGO = MakeStarGraphics(planetGO, sector, starModule, mod); var sunAudio = Object.Instantiate(SearchUtilities.Find("Sun_Body/Sector_SUN/Audio_SUN"), starGO.transform); sunAudio.transform.localPosition = Vector3.zero; @@ -152,9 +154,9 @@ namespace NewHorizons.Builder.Body return starController; } - public static GameObject MakeStarProxy(GameObject planet, GameObject proxyGO, StarModule starModule) + public static GameObject MakeStarProxy(GameObject planet, GameObject proxyGO, StarModule starModule, IModBehaviour mod) { - var starGO = MakeStarGraphics(proxyGO, null, starModule); + var starGO = MakeStarGraphics(proxyGO, null, starModule, mod); var supernova = MakeSupernova(starGO, starModule); @@ -175,7 +177,7 @@ namespace NewHorizons.Builder.Body return proxyGO; } - public static GameObject MakeStarGraphics(GameObject rootObject, Sector sector, StarModule starModule) + public static GameObject MakeStarGraphics(GameObject rootObject, Sector sector, StarModule starModule, IModBehaviour mod) { if (_colorOverTime == null) _colorOverTime = ImageUtilities.GetTexture(Main.Instance, "Assets/textures/StarColorOverTime.png"); @@ -208,10 +210,10 @@ namespace NewHorizons.Builder.Body starGO.transform.position = rootObject.transform.position; starGO.transform.localScale = starModule.size * Vector3.one; + TessellatedSphereRenderer surface = sunSurface.GetComponent(); + if (starModule.tint != null) { - TessellatedSphereRenderer surface = sunSurface.GetComponent(); - var colour = starModule.tint.ToColor(); var sun = SearchUtilities.Find("Sun_Body"); @@ -219,8 +221,8 @@ namespace NewHorizons.Builder.Body var giantMaterial = sun.GetComponent()._endSurfaceMaterial; surface.sharedMaterial = new Material(starModule.size >= 3000 ? giantMaterial : mainSequenceMaterial); - var mod = Mathf.Max(1f, 2f * Mathf.Sqrt(starModule.solarLuminosity)); - var adjustedColour = new Color(colour.r * mod, colour.g * mod, colour.b * mod); + var modifier = Mathf.Max(1f, 2f * Mathf.Sqrt(starModule.solarLuminosity)); + var adjustedColour = new Color(colour.r * modifier, colour.g * modifier, colour.b * modifier); surface.sharedMaterial.color = adjustedColour; Color.RGBToHSV(adjustedColour, out var h, out var s, out var v); @@ -229,12 +231,21 @@ namespace NewHorizons.Builder.Body if (starModule.endTint != null) { var endColour = starModule.endTint.ToColor(); - darkenedColor = new Color(endColour.r * mod, endColour.g * mod, endColour.b * mod); + darkenedColor = new Color(endColour.r * modifier, endColour.g * modifier, endColour.b * modifier); } surface.sharedMaterial.SetTexture(ColorRamp, ImageUtilities.LerpGreyscaleImage(_colorOverTime, adjustedColour, darkenedColor)); } + if (!string.IsNullOrEmpty(starModule.starRampTexture)) + { + var ramp = ImageUtilities.GetTexture(mod, starModule.starRampTexture); + if (ramp != null) + { + surface.sharedMaterial.SetTexture(ColorRamp, ramp); + } + } + return starGO; } diff --git a/NewHorizons/Builder/General/GravityBuilder.cs b/NewHorizons/Builder/General/GravityBuilder.cs index 1a61f0f3..5fa6c33e 100644 --- a/NewHorizons/Builder/General/GravityBuilder.cs +++ b/NewHorizons/Builder/General/GravityBuilder.cs @@ -15,8 +15,8 @@ namespace NewHorizons.Builder.General var gravityRadius = GM / 0.1f; if (exponent == 2f) gravityRadius = Mathf.Sqrt(gravityRadius); - // To let you actually orbit things the way you would expect we cap this at 4x the diameter if its not a star or black hole (this is what giants deep has) - if (config.Star == null && config.Singularity == null) gravityRadius = Mathf.Min(gravityRadius, 4 * config.Base.surfaceSize); + // To let you actually orbit things the way you would expect we cap this at 4x the diameter if its not a star (this is what giants deep has) + if (config.Star == null) gravityRadius = Mathf.Min(gravityRadius, 4 * config.Base.surfaceSize); else gravityRadius = Mathf.Min(gravityRadius, 15 * config.Base.surfaceSize); if (config.Base.soiOverride != 0f) gravityRadius = config.Base.soiOverride; diff --git a/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs b/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs index 514d4898..d204e79f 100644 --- a/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs +++ b/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs @@ -1,5 +1,7 @@ using NewHorizons.Components.Orbital; using NewHorizons.External.Modules; +using NewHorizons.Utility; +using System.Linq; using UnityEngine; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Builder.Orbital @@ -13,7 +15,7 @@ namespace NewHorizons.Builder.Orbital return SetInitialMotionFromConfig(initialMotion, primaryBody, secondaryBody, orbit); } - public static InitialMotion SetInitialMotionFromConfig(InitialMotion initialMotion, AstroObject primaryBody, AstroObject secondaryBody, OrbitModule orbit) + public static InitialMotion SetInitialMotionFromConfig(InitialMotion initialMotion, AstroObject primaryBody, AstroObject secondaryBody, OrbitModule orbit, bool isCustom = true) { // This bit makes the initial motion not try to calculate the orbit velocity itself for reasons initialMotion._orbitImpulseScalar = 0f; @@ -21,7 +23,12 @@ namespace NewHorizons.Builder.Orbital // Rotation initialMotion._initAngularSpeed = orbit.siderealPeriod == 0 ? 0f : 2f * Mathf.PI / (orbit.siderealPeriod * 60f); var rotationAxis = Quaternion.AngleAxis(orbit.axialTilt, Vector3.right) * Vector3.up; - secondaryBody.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis); + + // For things with children this is broken + if (AstroObjectLocator.GetChildren(secondaryBody).Length == 0) + { + secondaryBody.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis); + } if (!orbit.isStatic && primaryBody != null) { diff --git a/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs b/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs index e6ad0a53..006b63c0 100644 --- a/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs +++ b/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs @@ -52,7 +52,6 @@ namespace NewHorizons.Builder.Orbital if (config.Orbit.tint != null) color = config.Orbit.tint.ToColor(); else if (config.Star?.tint != null) color = config.Star.tint.ToColor(); else if (config.Atmosphere?.clouds?.tint != null) color = config.Atmosphere.clouds.tint.ToColor(); - else if (config.Singularity != null) color = new Color(1f, 0.5f, 1f); else if (config.Water != null) color = new Color(0.5f, 0.5f, 1f); else if (config.Lava != null) color = new Color(1f, 0.5f, 0.5f); else if (config.Atmosphere != null && config.Atmosphere.fogTint != null) color = config.Atmosphere.fogTint.ToColor(); diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index 99952903..fdbe5256 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -30,19 +30,27 @@ namespace NewHorizons.Builder.Props detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal); } - else detailGO = MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal); - - if (detailGO != null && detail.removeChildren != null) + else { + detailGO = MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal); + } + + if (detailGO == null) return; + + if (detail.removeChildren != null) + { + var detailPath = detailGO.transform.GetPath(); foreach (var childPath in detail.removeChildren) { - var childObj = detailGO.transform.Find(childPath); + // We purposefully use GameObject.Find here because we don't want to find inactive things. + // If you were to try and disable two children with the same name, if we were finding inactive then we'd disable the first one twice + var childObj = GameObject.Find($"{detailPath}/{childPath}"); if (childObj != null) childObj.gameObject.SetActive(false); else Logger.LogWarning($"Couldn't find {childPath}"); } } - if (detailGO != null && detail.removeComponents) + if (detail.removeComponents) { // Just swap all the children to a new game object var newDetailGO = new GameObject(detailGO.name); @@ -67,6 +75,15 @@ namespace NewHorizons.Builder.Props detailGO.name = detail.rename; } + if (!string.IsNullOrEmpty(detail.parentPath)) + { + var newParent = go.transform.Find(detail.parentPath); + if (newParent != null) + { + detailGO.transform.parent = newParent.transform; + } + } + detailInfoToCorrespondingSpawnedGameObject[detail] = detailGO; } diff --git a/NewHorizons/Builder/Props/DialogueBuilder.cs b/NewHorizons/Builder/Props/DialogueBuilder.cs index aeaf2741..3e5e75e7 100644 --- a/NewHorizons/Builder/Props/DialogueBuilder.cs +++ b/NewHorizons/Builder/Props/DialogueBuilder.cs @@ -1,6 +1,7 @@ using NewHorizons.External.Modules; using NewHorizons.Handlers; using OWML.Common; +using System.IO; using System.Xml; using UnityEngine; namespace NewHorizons.Builder.Props @@ -76,8 +77,9 @@ namespace NewHorizons.Builder.Props var dialogueTree = conversationZone.AddComponent(); - var xml = System.IO.File.ReadAllText(mod.Manifest.ModFolderPath + info.xmlFile); + var xml = File.ReadAllText(mod.Manifest.ModFolderPath + info.xmlFile); var text = new TextAsset(xml); + text.name = Path.GetFileNameWithoutExtension(info.xmlFile); dialogueTree.SetTextXml(text); AddTranslation(xml); diff --git a/NewHorizons/Builder/Props/NomaiTextBuilder.cs b/NewHorizons/Builder/Props/NomaiTextBuilder.cs index 349c45bf..6ade077e 100644 --- a/NewHorizons/Builder/Props/NomaiTextBuilder.cs +++ b/NewHorizons/Builder/Props/NomaiTextBuilder.cs @@ -3,6 +3,7 @@ using NewHorizons.Handlers; using NewHorizons.Utility; using OWML.Common; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Xml; using UnityEngine; @@ -20,14 +21,14 @@ namespace NewHorizons.Builder.Props private static GameObject _cairnPrefab; private static GameObject _recorderPrefab; private static GameObject _preCrashRecorderPrefab; - + private static Dictionary arcInfoToCorrespondingSpawnedGameObject = new Dictionary(); public static GameObject GetSpawnedGameObjectByNomaiTextArcInfo(PropModule.NomaiTextArcInfo arc) { if (!arcInfoToCorrespondingSpawnedGameObject.ContainsKey(arc)) return null; return arcInfoToCorrespondingSpawnedGameObject[arc]; } - + private static Dictionary conversationInfoToCorrespondingSpawnedGameObject = new Dictionary(); public static GameObject GetSpawnedGameObjectByNomaiTextInfo(PropModule.NomaiTextInfo convo) { @@ -85,7 +86,7 @@ namespace NewHorizons.Builder.Props _recorderPrefab = SearchUtilities.Find("Comet_Body/Prefab_NOM_Shuttle/Sector_NomaiShuttleInterior/Interactibles_NomaiShuttleInterior/Prefab_NOM_Recorder").InstantiateInactive(); _recorderPrefab.name = "Prefab_NOM_Recorder"; _recorderPrefab.transform.rotation = Quaternion.identity; - + _preCrashRecorderPrefab = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_EscapePodCrashSite/Sector_CrashFragment/Interactables_CrashFragment/Prefab_NOM_Recorder").InstantiateInactive(); _preCrashRecorderPrefab.name = "Prefab_NOM_Recorder_Vessel"; _preCrashRecorderPrefab.transform.rotation = Quaternion.identity; @@ -100,191 +101,194 @@ namespace NewHorizons.Builder.Props switch (info.type) { case PropModule.NomaiTextInfo.NomaiTextType.Wall: - { - var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlPath).gameObject; - - nomaiWallTextObj.transform.parent = sector?.transform ?? planetGO.transform; - nomaiWallTextObj.transform.position = planetGO.transform.TransformPoint(info.position); - if (info.normal != null) { - // In global coordinates (normal was in local coordinates) - var up = (nomaiWallTextObj.transform.position - planetGO.transform.position).normalized; - var forward = planetGO.transform.TransformDirection(info.normal).normalized; + var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlPath).gameObject; - nomaiWallTextObj.transform.up = up; - nomaiWallTextObj.transform.forward = forward; - } - if (info.rotation != null) - { - nomaiWallTextObj.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); - } - - nomaiWallTextObj.SetActive(true); - conversationInfoToCorrespondingSpawnedGameObject[info] = nomaiWallTextObj; - break; - } - case PropModule.NomaiTextInfo.NomaiTextType.Scroll: - { - var customScroll = _scrollPrefab.InstantiateInactive(); - - var nomaiWallText = MakeWallText(planetGO, sector, info, xmlPath); - nomaiWallText.transform.parent = customScroll.transform; - nomaiWallText.transform.localPosition = Vector3.zero; - nomaiWallText.transform.localRotation = Quaternion.identity; - - nomaiWallText._showTextOnStart = false; - - // Don't want to be able to translate until its in a socket - nomaiWallText.GetComponent().enabled = false; - - nomaiWallText.gameObject.SetActive(true); - - var scrollItem = customScroll.GetComponent(); - - // Idk why this thing is always around - GameObject.Destroy(customScroll.transform.Find("Arc_BH_City_Forum_2").gameObject); - - // This variable is the bane of my existence i dont get it - scrollItem._nomaiWallText = nomaiWallText; - - // Because the scroll was already awake it does weird shit in Awake and makes some of the entries in this array be null - scrollItem._colliders = new OWCollider[] { scrollItem.GetComponent() }; - - // Else when you put them down you can't pick them back up - customScroll.GetComponent()._physicsRemoved = false; - - // Place scroll - customScroll.transform.parent = sector?.transform ?? planetGO.transform; - customScroll.transform.position = planetGO.transform.TransformPoint(info.position ?? Vector3.zero); - - var up = planetGO.transform.InverseTransformPoint(customScroll.transform.position).normalized; - customScroll.transform.rotation = Quaternion.FromToRotation(customScroll.transform.up, up) * customScroll.transform.rotation; - - customScroll.SetActive(true); - - // Enable the collider and renderer - Main.Instance.ModHelper.Events.Unity.RunWhen( - () => Main.IsSystemReady, - () => + nomaiWallTextObj.transform.parent = sector?.transform ?? planetGO.transform; + nomaiWallTextObj.transform.position = planetGO.transform.TransformPoint(info.position); + if (info.normal != null) { - Logger.Log("Fixing scroll!"); - scrollItem._nomaiWallText = nomaiWallText; - scrollItem.SetSector(sector); - customScroll.transform.Find("Props_NOM_Scroll/Props_NOM_Scroll_Geo").GetComponent().enabled = true; - customScroll.transform.Find("Props_NOM_Scroll/Props_NOM_Scroll_Collider").gameObject.SetActive(true); - nomaiWallText.gameObject.GetComponent().enabled = false; - customScroll.GetComponent().enabled = true; + // In global coordinates (normal was in local coordinates) + var up = (nomaiWallTextObj.transform.position - planetGO.transform.position).normalized; + var forward = planetGO.transform.TransformDirection(info.normal).normalized; + + nomaiWallTextObj.transform.up = up; + nomaiWallTextObj.transform.forward = forward; } - ); - conversationInfoToCorrespondingSpawnedGameObject[info] = customScroll; - break; - } + if (info.rotation != null) + { + nomaiWallTextObj.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); + } + + nomaiWallTextObj.SetActive(true); + conversationInfoToCorrespondingSpawnedGameObject[info] = nomaiWallTextObj; + break; + } + case PropModule.NomaiTextInfo.NomaiTextType.Scroll: + { + var customScroll = _scrollPrefab.InstantiateInactive(); + + var nomaiWallText = MakeWallText(planetGO, sector, info, xmlPath); + nomaiWallText.transform.parent = customScroll.transform; + nomaiWallText.transform.localPosition = Vector3.zero; + nomaiWallText.transform.localRotation = Quaternion.identity; + + nomaiWallText._showTextOnStart = false; + + // Don't want to be able to translate until its in a socket + nomaiWallText.GetComponent().enabled = false; + + nomaiWallText.gameObject.SetActive(true); + + var scrollItem = customScroll.GetComponent(); + + // Idk why this thing is always around + GameObject.Destroy(customScroll.transform.Find("Arc_BH_City_Forum_2").gameObject); + + // This variable is the bane of my existence i dont get it + scrollItem._nomaiWallText = nomaiWallText; + + // Because the scroll was already awake it does weird shit in Awake and makes some of the entries in this array be null + scrollItem._colliders = new OWCollider[] { scrollItem.GetComponent() }; + + // Else when you put them down you can't pick them back up + customScroll.GetComponent()._physicsRemoved = false; + + // Place scroll + customScroll.transform.parent = sector?.transform ?? planetGO.transform; + customScroll.transform.position = planetGO.transform.TransformPoint(info.position ?? Vector3.zero); + + var up = planetGO.transform.InverseTransformPoint(customScroll.transform.position).normalized; + customScroll.transform.rotation = Quaternion.FromToRotation(customScroll.transform.up, up) * customScroll.transform.rotation; + + customScroll.SetActive(true); + + // Enable the collider and renderer + Main.Instance.ModHelper.Events.Unity.RunWhen( + () => Main.IsSystemReady, + () => + { + Logger.Log("Fixing scroll!"); + scrollItem._nomaiWallText = nomaiWallText; + scrollItem.SetSector(sector); + customScroll.transform.Find("Props_NOM_Scroll/Props_NOM_Scroll_Geo").GetComponent().enabled = true; + customScroll.transform.Find("Props_NOM_Scroll/Props_NOM_Scroll_Collider").gameObject.SetActive(true); + nomaiWallText.gameObject.GetComponent().enabled = false; + customScroll.GetComponent().enabled = true; + } + ); + conversationInfoToCorrespondingSpawnedGameObject[info] = customScroll; + break; + } case PropModule.NomaiTextInfo.NomaiTextType.Computer: - { - var computerObject = _computerPrefab.InstantiateInactive(); + { + var computerObject = _computerPrefab.InstantiateInactive(); - computerObject.transform.parent = sector?.transform ?? planetGO.transform; - computerObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); + computerObject.transform.parent = sector?.transform ?? planetGO.transform; + computerObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); - var up = computerObject.transform.position - planetGO.transform.position; - if (info.normal != null) up = planetGO.transform.TransformDirection(info.normal); - computerObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * computerObject.transform.rotation; + var up = computerObject.transform.position - planetGO.transform.position; + if (info.normal != null) up = planetGO.transform.TransformDirection(info.normal); + computerObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * computerObject.transform.rotation; - var computer = computerObject.GetComponent(); - computer.SetSector(sector); + var computer = computerObject.GetComponent(); + computer.SetSector(sector); - computer._dictNomaiTextData = MakeNomaiTextDict(xmlPath); - computer._nomaiTextAsset = new TextAsset(xmlPath); - AddTranslation(xmlPath); + computer._dictNomaiTextData = MakeNomaiTextDict(xmlPath); + computer._nomaiTextAsset = new TextAsset(xmlPath); + computer._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile); + AddTranslation(xmlPath); - // Make sure the computer model is loaded - OWAssetHandler.LoadObject(computerObject); - sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(computerObject)); + // Make sure the computer model is loaded + OWAssetHandler.LoadObject(computerObject); + sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(computerObject)); - computerObject.SetActive(true); - conversationInfoToCorrespondingSpawnedGameObject[info] = computerObject; - break; - } + computerObject.SetActive(true); + conversationInfoToCorrespondingSpawnedGameObject[info] = computerObject; + break; + } case PropModule.NomaiTextInfo.NomaiTextType.Cairn: - { - var cairnObject = _cairnPrefab.InstantiateInactive(); - - cairnObject.transform.parent = sector?.transform ?? planetGO.transform; - cairnObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); - - if (info.rotation != null) { - cairnObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); + var cairnObject = _cairnPrefab.InstantiateInactive(); + + cairnObject.transform.parent = sector?.transform ?? planetGO.transform; + cairnObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); + + if (info.rotation != null) + { + cairnObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); + } + else + { + // By default align it to normal + var up = (cairnObject.transform.position - planetGO.transform.position).normalized; + cairnObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * cairnObject.transform.rotation; + } + + // Idk do we have to set it active before finding things? + cairnObject.SetActive(true); + + // Make it do the thing when it finishes being knocked over + foreach (var rock in cairnObject.GetComponent()._rocks) + { + rock._returning = false; + rock._owCollider.SetActivation(true); + rock.enabled = false; + } + + // So we can actually knock it over + cairnObject.GetComponent().enabled = true; + + var nomaiWallText = cairnObject.transform.Find("Props_TH_ClutterSmall/Arc_Short").GetComponent(); + nomaiWallText.SetSector(sector); + + nomaiWallText._dictNomaiTextData = MakeNomaiTextDict(xmlPath); + nomaiWallText._nomaiTextAsset = new TextAsset(xmlPath); + nomaiWallText._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile); + AddTranslation(xmlPath); + + // Make sure the computer model is loaded + OWAssetHandler.LoadObject(cairnObject); + sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(cairnObject)); + conversationInfoToCorrespondingSpawnedGameObject[info] = cairnObject; + break; } - else - { - // By default align it to normal - var up = (cairnObject.transform.position - planetGO.transform.position).normalized; - cairnObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * cairnObject.transform.rotation; - } - - // Idk do we have to set it active before finding things? - cairnObject.SetActive(true); - - // Make it do the thing when it finishes being knocked over - foreach (var rock in cairnObject.GetComponent()._rocks) - { - rock._returning = false; - rock._owCollider.SetActivation(true); - rock.enabled = false; - } - - // So we can actually knock it over - cairnObject.GetComponent().enabled = true; - - var nomaiWallText = cairnObject.transform.Find("Props_TH_ClutterSmall/Arc_Short").GetComponent(); - nomaiWallText.SetSector(sector); - - nomaiWallText._dictNomaiTextData = MakeNomaiTextDict(xmlPath); - nomaiWallText._nomaiTextAsset = new TextAsset(xmlPath); - AddTranslation(xmlPath); - - // Make sure the computer model is loaded - OWAssetHandler.LoadObject(cairnObject); - sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(cairnObject)); - conversationInfoToCorrespondingSpawnedGameObject[info] = cairnObject; - break; - } case PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder: case PropModule.NomaiTextInfo.NomaiTextType.Recorder: - { - var recorderObject = (info.type == PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder? _preCrashRecorderPrefab : _recorderPrefab).InstantiateInactive(); - - recorderObject.transform.parent = sector?.transform ?? planetGO.transform; - recorderObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); - - if (info.rotation != null) { - recorderObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); + var recorderObject = (info.type == PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder ? _preCrashRecorderPrefab : _recorderPrefab).InstantiateInactive(); + + recorderObject.transform.parent = sector?.transform ?? planetGO.transform; + recorderObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); + + if (info.rotation != null) + { + recorderObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); + } + else + { + var up = recorderObject.transform.position - planetGO.transform.position; + recorderObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * recorderObject.transform.rotation; + } + + var nomaiText = recorderObject.GetComponentInChildren(); + nomaiText.SetSector(sector); + + nomaiText._dictNomaiTextData = MakeNomaiTextDict(xmlPath); + nomaiText._nomaiTextAsset = new TextAsset(xmlPath); + nomaiText._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile); + AddTranslation(xmlPath); + + // Make sure the recorder model is loaded + OWAssetHandler.LoadObject(recorderObject); + sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(recorderObject)); + + recorderObject.SetActive(true); + + recorderObject.transform.Find("InteractSphere").gameObject.GetComponent().enabled = true; + conversationInfoToCorrespondingSpawnedGameObject[info] = recorderObject; + break; } - else - { - var up = recorderObject.transform.position - planetGO.transform.position; - recorderObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * recorderObject.transform.rotation; - } - - var nomaiText = recorderObject.GetComponentInChildren(); - nomaiText.SetSector(sector); - - nomaiText._dictNomaiTextData = MakeNomaiTextDict(xmlPath); - nomaiText._nomaiTextAsset = new TextAsset(xmlPath); - AddTranslation(xmlPath); - - // Make sure the recorder model is loaded - OWAssetHandler.LoadObject(recorderObject); - sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(recorderObject)); - - recorderObject.SetActive(true); - - recorderObject.transform.Find("InteractSphere").gameObject.GetComponent().enabled = true; - conversationInfoToCorrespondingSpawnedGameObject[info] = recorderObject; - break; - } default: Logger.LogError($"Unsupported NomaiText type {info.type}"); break; @@ -306,6 +310,7 @@ namespace NewHorizons.Builder.Props var nomaiWallText = nomaiWallTextObj.AddComponent(); var text = new TextAsset(xmlPath); + text.name = Path.GetFileNameWithoutExtension(info.xmlFile); BuildArcs(xmlPath, nomaiWallText, nomaiWallTextObj, info); AddTranslation(xmlPath); @@ -325,7 +330,7 @@ namespace NewHorizons.Builder.Props RefreshArcs(nomaiWallText, conversationZone, info); } - internal static void RefreshArcs(NomaiWallText nomaiWallText, GameObject conversationZone, PropModule.NomaiTextInfo info) + internal static void RefreshArcs(NomaiWallText nomaiWallText, GameObject conversationZone, PropModule.NomaiTextInfo info) { var dict = nomaiWallText._dictNomaiTextData; Random.InitState(info.seed); @@ -349,7 +354,7 @@ namespace NewHorizons.Builder.Props GameObject arc = MakeArc(arcInfo, conversationZone, parent, textEntryID); arc.name = $"Arc {i} - Child of {parentID}"; - + arcsByID.Add(textEntryID, arc); i++; @@ -419,7 +424,7 @@ namespace NewHorizons.Builder.Props arc.GetComponent().enabled = false; arc.SetActive(true); - + arcInfoToCorrespondingSpawnedGameObject[arcInfo] = arc; return arc; diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 05eff66f..12d87696 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -265,7 +265,7 @@ namespace NewHorizons.Builder.Props // setup for visually supporting async texture loading mindSlideProjector.enabled = false; - var visionBeamEffect = SearchUtilities.FindChild(standingTorch, "VisionBeam"); + var visionBeamEffect = standingTorch.FindChild("VisionBeam"); visionBeamEffect.SetActive(false); // diff --git a/NewHorizons/Builder/Props/PropBuildManager.cs b/NewHorizons/Builder/Props/PropBuildManager.cs index 5f488529..76123765 100644 --- a/NewHorizons/Builder/Props/PropBuildManager.cs +++ b/NewHorizons/Builder/Props/PropBuildManager.cs @@ -1,3 +1,4 @@ +using NewHorizons.Builder.Body; using NewHorizons.Builder.ShipLog; using NewHorizons.External.Configs; using OWML.Common; @@ -190,6 +191,13 @@ namespace NewHorizons.Builder.Props Logger.LogError($"Couldn't make quantum group \"{quantumGroup.id}\" for [{go.name}] : {ex.Message}, {ex.StackTrace}"); } } + } + if (config.Props.singularities != null) + { + foreach (var singularity in config.Props.singularities) + { + SingularityBuilder.Make(go, sector, go.GetComponent(), config, singularity); + } } } } diff --git a/NewHorizons/Builder/ShipLog/MapModeBuilder.cs b/NewHorizons/Builder/ShipLog/MapModeBuilder.cs index 06be3068..c87438b0 100644 --- a/NewHorizons/Builder/ShipLog/MapModeBuilder.cs +++ b/NewHorizons/Builder/ShipLog/MapModeBuilder.cs @@ -101,7 +101,7 @@ namespace NewHorizons.Builder.ShipLog Logger.Log($"Adding ship log astro object for {body.Config.name}"); - GameObject unviewedReference = SearchUtilities.CachedFind(ShipLogHandler.PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon"); + GameObject unviewedReference = SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon"); ShipLogAstroObject astroObject = gameObject.AddComponent(); astroObject._id = ShipLogHandler.GetAstroObjectId(body); @@ -249,7 +249,7 @@ namespace NewHorizons.Builder.ShipLog } else if (Main.Instance.CurrentStarSystem == "SolarSystem") { - GameObject gameObject = SearchUtilities.CachedFind(ShipLogHandler.PAN_ROOT_PATH + "/" + name); + GameObject gameObject = SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + name); if (body.Config.destroy || (body.Config.ShipLog?.mapMode?.remove ?? false)) { ShipLogAstroObject astroObject = gameObject.GetComponent(); @@ -522,14 +522,6 @@ namespace NewHorizons.Builder.ShipLog { try { - switch (body.Config?.Singularity?.type) - { - case SingularityModule.SingularityType.BlackHole: - return Color.black; - case SingularityModule.SingularityType.WhiteHole: - return Color.white; - } - var starColor = body.Config?.Star?.tint; if (starColor != null) return starColor.ToColor(); @@ -555,6 +547,14 @@ namespace NewHorizons.Builder.ShipLog var sandColor = body.Config.Sand?.tint; if (sandColor != null) return sandColor.ToColor(); + + switch (body.Config?.Props?.singularities?.FirstOrDefault()?.type) + { + case SingularityModule.SingularityType.BlackHole: + return Color.black; + case SingularityModule.SingularityType.WhiteHole: + return Color.white; + } } catch (Exception) { diff --git a/NewHorizons/Components/RingFluidVolume.cs b/NewHorizons/Components/RingFluidVolume.cs new file mode 100644 index 00000000..76619ef7 --- /dev/null +++ b/NewHorizons/Components/RingFluidVolume.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace NewHorizons.Components +{ + public class RingFluidVolume : SimpleFluidVolume + { + public override void OnEffectVolumeEnter(GameObject hitObj) + { + FluidDetector fluidDetector = hitObj.GetComponent(); + if (fluidDetector == null) return; + + ForceDetector forceDetector = hitObj.GetComponent(); + if (forceDetector != null && forceDetector._activeVolumes != null && forceDetector._activeVolumes.Count > 0 && forceDetector._activeVolumes.Where(activeVolume => activeVolume is ForceVolume).Select(activeVolume => activeVolume as ForceVolume).Any(activeVolume => activeVolume.GetAffectsAlignment(forceDetector._attachedBody))) return; + + fluidDetector.AddVolume(this); + } + } +} diff --git a/NewHorizons/External/Configs/PlanetConfig.cs b/NewHorizons/External/Configs/PlanetConfig.cs index d01cc60a..c65c68c3 100644 --- a/NewHorizons/External/Configs/PlanetConfig.cs +++ b/NewHorizons/External/Configs/PlanetConfig.cs @@ -50,6 +50,9 @@ namespace NewHorizons.External.Configs [Obsolete("ChildrenToDestroy is deprecated, please use RemoveChildren instead")] public string[] childrenToDestroy; + [Obsolete("Singularity is deprecated, please use Props->singularities")] + public SingularityModule Singularity; + #endregion Obsolete /// @@ -138,11 +141,6 @@ namespace NewHorizons.External.Configs /// public SignalModule Signal; - /// - /// Add a black or white hole to this planet - /// - public SingularityModule Singularity; - /// /// Spawn the player at this planet /// @@ -329,6 +327,13 @@ namespace NewHorizons.External.Configs } } + // Singularity is now a list in props so you can have many per planet + if (Singularity != null) + { + if (Props == null) Props = new PropModule(); + if (Props.singularities == null) Props.singularities = new SingularityModule[0]; + Props.singularities = Props.singularities.Append(Singularity).ToArray(); + } } } } \ No newline at end of file diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index 4d3362cd..d0db2bf4 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -6,6 +6,7 @@ using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using System; +using NewHorizons.External.Modules.VariableSize; namespace NewHorizons.External.Modules { @@ -77,6 +78,11 @@ namespace NewHorizons.External.Modules /// public VolcanoInfo[] volcanoes; + /// + /// Add black/white-holes to this planet + /// + public SingularityModule[] singularities; + [JsonObject] public class ScatterInfo { @@ -169,6 +175,11 @@ namespace NewHorizons.External.Modules /// If this value is not null, this prop will be quantum. Assign this field to the id of the quantum group it should be a part of. The group it is assigned to determines what kind of quantum object it is /// public string quantumGroupID; + + /// + /// The path (not including the root planet object) of the parent of this game object. Optional (will default to the root sector). + /// + public string parentPath; } [JsonObject] diff --git a/NewHorizons/External/Modules/VariableSize/SingularityModule.cs b/NewHorizons/External/Modules/VariableSize/SingularityModule.cs index 001dcb56..6068907b 100644 --- a/NewHorizons/External/Modules/VariableSize/SingularityModule.cs +++ b/NewHorizons/External/Modules/VariableSize/SingularityModule.cs @@ -1,4 +1,4 @@ -using System.ComponentModel; +using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; using NewHorizons.Utility; @@ -24,11 +24,16 @@ namespace NewHorizons.External.Modules.VariableSize [DefaultValue(true)] public bool makeZeroGVolume = true; /// - /// The name of the white hole or black hole that is paired to this one. If you don't set a value, entering will kill + /// The uniqueID of the white hole or black hole that is paired to this one. If you don't set a value, entering will kill /// the player /// public string pairedSingularity; + /// + /// The uniqueID of this white hole or black hole. If not set it will default to the name of the planet + /// + public string uniqueID; + /// /// Position of the singularity /// diff --git a/NewHorizons/External/Modules/VariableSize/StarModule.cs b/NewHorizons/External/Modules/VariableSize/StarModule.cs index 201571e3..164d2575 100644 --- a/NewHorizons/External/Modules/VariableSize/StarModule.cs +++ b/NewHorizons/External/Modules/VariableSize/StarModule.cs @@ -56,6 +56,11 @@ namespace NewHorizons.External.Modules.VariableSize /// public MColor tint; + /// + /// Path to the texture to put as the star ramp. Optional. + /// + public string starRampTexture; + /// /// How far the light from the star can reach. /// diff --git a/NewHorizons/Handlers/PlanetCreationHandler.cs b/NewHorizons/Handlers/PlanetCreationHandler.cs index ce7feb7b..a7ba3baa 100644 --- a/NewHorizons/Handlers/PlanetCreationHandler.cs +++ b/NewHorizons/Handlers/PlanetCreationHandler.cs @@ -269,7 +269,9 @@ namespace NewHorizons.Handlers { foreach (var child in body.Config.removeChildren) { - Main.Instance.ModHelper.Events.Unity.FireInNUpdates(() => SearchUtilities.Find(go.name + "/" + child)?.SetActive(false), 2); + // We purposefully use GameObject.Find here because we don't want to find inactive things. + // If you were to try and disable two children with the same name, if we were finding inactive then we'd disable the first one twice + Main.Instance.ModHelper.Events.Unity.FireInNUpdates(() => GameObject.Find(go.name + "/" + child)?.SetActive(false), 2); } } @@ -456,7 +458,7 @@ namespace NewHorizons.Handlers if (body.Config.Star != null) { - StarLightController.AddStar(StarBuilder.Make(go, sector, body.Config.Star)); + StarLightController.AddStar(StarBuilder.Make(go, sector, body.Config.Star, body.Mod)); } if (body.Config?.Bramble?.nodes != null) @@ -516,7 +518,7 @@ namespace NewHorizons.Handlers if (!string.IsNullOrEmpty(body.Config.Atmosphere?.clouds?.texturePath)) { CloudsBuilder.Make(go, sector, body.Config.Atmosphere, body.Mod); - SunOverrideBuilder.Make(go, sector, body.Config.Atmosphere, surfaceSize); + SunOverrideBuilder.Make(go, sector, body.Config.Atmosphere, body.Config.Water, surfaceSize); } if (body.Config.Atmosphere.hasRain || body.Config.Atmosphere.hasSnow) @@ -538,11 +540,6 @@ namespace NewHorizons.Handlers SignalBuilder.Make(go, sector, body.Config.Signal, body.Mod); } - if (body.Config.Singularity != null) - { - SingularityBuilder.Make(go, sector, rb, body.Config); - } - if (body.Config.Funnel != null) { FunnelBuilder.Make(go, go.GetComponentInChildren(), rb, body.Config.Funnel); diff --git a/NewHorizons/Handlers/ShipLogHandler.cs b/NewHorizons/Handlers/ShipLogHandler.cs index 2ffb175f..3d3a3f6b 100644 --- a/NewHorizons/Handlers/ShipLogHandler.cs +++ b/NewHorizons/Handlers/ShipLogHandler.cs @@ -29,7 +29,7 @@ namespace NewHorizons.Handlers GameObject panRoot = SearchUtilities.Find(PAN_ROOT_PATH); if (panRoot != null) { - List gameObjects = SearchUtilities.GetAllChildren(panRoot); + List gameObjects = panRoot.GetAllChildren(); _vanillaBodies = gameObjects.ConvertAll(g => g.name).ToArray(); _vanillaBodyIDs = gameObjects.ConvertAll(g => g.GetComponent()?.GetID()).ToArray(); } diff --git a/NewHorizons/INewHorizons.cs b/NewHorizons/INewHorizons.cs new file mode 100644 index 00000000..fd10e7e6 --- /dev/null +++ b/NewHorizons/INewHorizons.cs @@ -0,0 +1,35 @@ +using OWML.Common; +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Events; + +namespace NewHorizons +{ + public interface INewHorizons + { + [Obsolete("Create(Dictionary config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")] + void Create(Dictionary config); + + [Obsolete("Create(Dictionary config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")] + void Create(Dictionary config, IModBehaviour mod); + + void LoadConfigs(IModBehaviour mod); + + GameObject GetPlanet(string name); + + string GetCurrentStarSystem(); + + UnityEvent GetChangeStarSystemEvent(); + + UnityEvent GetStarSystemLoadedEvent(); + + bool SetDefaultSystem(string name); + + bool ChangeCurrentStarSystem(string name); + + string[] GetInstalledAddons(); + + GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles, float scale, bool alignWithNormal); + } +} diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index dd54e53d..955b7cd5 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -8,6 +8,7 @@ using NewHorizons.Handlers; using NewHorizons.Utility; using NewHorizons.Utility.DebugMenu; using NewHorizons.Utility.DebugUtilities; +using NewHorizons.VoiceActing; using OWML.Common; using OWML.ModHelper; using System; @@ -183,6 +184,7 @@ namespace NewHorizons Instance.ModHelper.Menus.PauseMenu.OnInit += DebugReload.InitializePauseMenu; AchievementHandler.Init(); + VoiceHandler.Init(); } public void OnDestroy() @@ -198,15 +200,6 @@ namespace NewHorizons private static void OnWakeUp() { IsSystemReady = true; - try - { - Logger.Log($"Star system loaded [{Instance.CurrentStarSystem}]"); - Instance.OnStarSystemLoaded?.Invoke(Instance.CurrentStarSystem); - } - catch (Exception e) - { - Logger.LogError($"Exception thrown when invoking star system loaded event with parameter [{Instance.CurrentStarSystem}] : {e.GetType().FullName} {e.Message} {e.StackTrace}"); - } } private void OnSceneUnloaded(Scene scene) @@ -302,6 +295,16 @@ namespace NewHorizons // Fix the map satellite SearchUtilities.Find("HearthianMapSatellite_Body", false).AddComponent(); + + try + { + Logger.Log($"Star system loaded [{Instance.CurrentStarSystem}]"); + Instance.OnStarSystemLoaded?.Invoke(Instance.CurrentStarSystem); + } + catch (Exception e) + { + Logger.LogError($"Exception thrown when invoking star system loaded event with parameter [{Instance.CurrentStarSystem}] : {e.GetType().FullName} {e.Message} {e.StackTrace}"); + } } else { diff --git a/NewHorizons/NewHorizonsApi.cs b/NewHorizons/NewHorizonsApi.cs index 135579ac..191d87dd 100644 --- a/NewHorizons/NewHorizonsApi.cs +++ b/NewHorizons/NewHorizonsApi.cs @@ -9,9 +9,10 @@ using System.Linq; using UnityEngine; using UnityEngine.Events; using Logger = NewHorizons.Utility.Logger; + namespace NewHorizons { - public class NewHorizonsApi + public class NewHorizonsApi : INewHorizons { [Obsolete("Create(Dictionary config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")] public void Create(Dictionary config) diff --git a/NewHorizons/Patches/ShipLogPatches.cs b/NewHorizons/Patches/ShipLogPatches.cs index 00241e33..e61263be 100644 --- a/NewHorizons/Patches/ShipLogPatches.cs +++ b/NewHorizons/Patches/ShipLogPatches.cs @@ -145,7 +145,7 @@ namespace NewHorizons.Patches __instance._startingAstroObjectID = navMatrix[1][0].GetID(); if (Main.Instance.CurrentStarSystem != "SolarSystem") { - List delete = SearchUtilities.GetAllChildren(panRoot).Where(g => g.name.Contains("_ShipLog") == false).ToList(); + List delete = panRoot.GetAllChildren().Where(g => g.name.Contains("_ShipLog") == false).ToList(); foreach (GameObject gameObject in delete) { Object.Destroy(SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + gameObject.name)); @@ -182,7 +182,7 @@ namespace NewHorizons.Patches Transform detailsParent = __instance.transform.Find("Details"); if (detailsParent != null) { - foreach (GameObject child in SearchUtilities.GetAllChildren(detailsParent.gameObject)) + foreach (GameObject child in detailsParent.gameObject.GetAllChildren()) { if (child.TryGetComponent(typeof(ShipLogDetail), out Component detail)) { diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index 8540a9b5..bb04938c 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -102,10 +102,6 @@ "description": "Add signals that can be heard via the signal-scope to this planet", "$ref": "#/definitions/SignalModule" }, - "Singularity": { - "description": "Add a black or white hole to this planet", - "$ref": "#/definitions/SingularityModule" - }, "Spawn": { "description": "Spawn the player at this planet", "$ref": "#/definitions/SpawnModule" @@ -811,6 +807,13 @@ "items": { "$ref": "#/definitions/VolcanoInfo" } + }, + "singularities": { + "type": "array", + "description": "Add black/white-holes to this planet", + "items": { + "$ref": "#/definitions/SingularityModule" + } } } }, @@ -862,6 +865,10 @@ "quantumGroupID": { "type": "string", "description": "If this value is not null, this prop will be quantum. Assign this field to the id of the quantum group it should be a part of. The group it is assigned to determines what kind of quantum object it is" + }, + "parentPath": { + "type": "string", + "description": "The path (not including the root planet object) of the parent of this game object. Optional (will default to the root sector)." } } }, @@ -1447,6 +1454,62 @@ } } }, + "SingularityModule": { + "type": "object", + "additionalProperties": false, + "properties": { + "curve": { + "type": "array", + "description": "Scale this module over time", + "items": { + "$ref": "#/definitions/TimeValuePair" + } + }, + "makeZeroGVolume": { + "type": "boolean", + "description": "Only for White Holes. Should this white hole repel the player from it.", + "default": true + }, + "pairedSingularity": { + "type": "string", + "description": "The uniqueID of the white hole or black hole that is paired to this one. If you don't set a value, entering will kill\nthe player" + }, + "uniqueID": { + "type": "string", + "description": "The uniqueID of this white hole or black hole. If not set it will default to the name of the planet" + }, + "position": { + "description": "Position of the singularity", + "$ref": "#/definitions/MVector3" + }, + "size": { + "type": "number", + "description": "Radius of the singularity. Note that this isn't the same as the event horizon, but includes the entire volume that\nhas warped effects in it.", + "format": "float", + "minimum": 0.0 + }, + "targetStarSystem": { + "type": "string", + "description": "If you want a black hole to load a new star system scene, put its name here." + }, + "type": { + "description": "Type of singularity (white hole or black hole)", + "$ref": "#/definitions/SingularityType" + } + } + }, + "SingularityType": { + "type": "string", + "description": "", + "x-enumNames": [ + "BlackHole", + "WhiteHole" + ], + "enum": [ + "blackHole", + "whiteHole" + ] + }, "ReferenceFrameModule": { "type": "object", "additionalProperties": false, @@ -1725,58 +1788,6 @@ } } }, - "SingularityModule": { - "type": "object", - "additionalProperties": false, - "properties": { - "curve": { - "type": "array", - "description": "Scale this module over time", - "items": { - "$ref": "#/definitions/TimeValuePair" - } - }, - "makeZeroGVolume": { - "type": "boolean", - "description": "Only for White Holes. Should this white hole repel the player from it.", - "default": true - }, - "pairedSingularity": { - "type": "string", - "description": "The name of the white hole or black hole that is paired to this one. If you don't set a value, entering will kill\nthe player" - }, - "position": { - "description": "Position of the singularity", - "$ref": "#/definitions/MVector3" - }, - "size": { - "type": "number", - "description": "Radius of the singularity. Note that this isn't the same as the event horizon, but includes the entire volume that\nhas warped effects in it.", - "format": "float", - "minimum": 0.0 - }, - "targetStarSystem": { - "type": "string", - "description": "If you want a black hole to load a new star system scene, put its name here." - }, - "type": { - "description": "Type of singularity (white hole or black hole)", - "$ref": "#/definitions/SingularityType" - } - } - }, - "SingularityType": { - "type": "string", - "description": "", - "x-enumNames": [ - "BlackHole", - "WhiteHole" - ], - "enum": [ - "blackHole", - "whiteHole" - ] - }, "SpawnModule": { "type": "object", "additionalProperties": false, @@ -1859,6 +1870,10 @@ "description": "Colour of the star.", "$ref": "#/definitions/MColor" }, + "starRampTexture": { + "type": "string", + "description": "Path to the texture to put as the star ramp. Optional." + }, "lightRadius": { "type": "number", "description": "How far the light from the star can reach.", diff --git a/NewHorizons/Utility/AstroObjectLocator.cs b/NewHorizons/Utility/AstroObjectLocator.cs index 91d36f95..c03449b3 100644 --- a/NewHorizons/Utility/AstroObjectLocator.cs +++ b/NewHorizons/Utility/AstroObjectLocator.cs @@ -1,151 +1,160 @@ -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -namespace NewHorizons.Utility -{ - public static class AstroObjectLocator - { - private static Dictionary _customAstroObjectDictionary = new Dictionary(); - - public static void Init() - { - _customAstroObjectDictionary = new Dictionary(); - foreach (AstroObject ao in GameObject.FindObjectsOfType()) - { - // Ignore the sun station debris, we handle it as a child of the sun station - if (ao.gameObject.name == "SS_Debris_Body") continue; - - RegisterCustomAstroObject(ao); - } - } - - public static AstroObject GetAstroObject(string name, bool flag = false) - { - if (string.IsNullOrEmpty(name)) return null; - - if (_customAstroObjectDictionary.ContainsKey(name)) - { - return _customAstroObjectDictionary[name]; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +namespace NewHorizons.Utility +{ + public static class AstroObjectLocator + { + private static Dictionary _customAstroObjectDictionary = new Dictionary(); + + public static void Init() + { + _customAstroObjectDictionary = new Dictionary(); + foreach (AstroObject ao in GameObject.FindObjectsOfType()) + { + // Ignore the sun station debris, we handle it as a child of the sun station + if (ao.gameObject.name == "SS_Debris_Body") continue; + + RegisterCustomAstroObject(ao); } - - // Else check stock names - var stringID = name.ToUpper().Replace(" ", "_").Replace("'", ""); - if (stringID.Equals("ATTLEROCK")) stringID = "TIMBER_MOON"; - if (stringID.Equals("HOLLOWS_LANTERN")) stringID = "VOLCANIC_MOON"; - if (stringID.Equals("ASH_TWIN")) stringID = "TOWER_TWIN"; - if (stringID.Equals("EMBER_TWIN")) stringID = "CAVE_TWIN"; - if (stringID.Equals("INTERLOPER")) stringID = "COMET"; - - string key; - if (stringID.ToUpper().Replace("_", "").Equals("MAPSATELLITE")) - { - key = AstroObject.Name.MapSatellite.ToString(); - } - else - { - key = AstroObject.StringIDToAstroObjectName(stringID).ToString(); - } - - if (_customAstroObjectDictionary.ContainsKey(key)) - { - return _customAstroObjectDictionary[key]; - } - - // Try again - if (!flag) return GetAstroObject(name.Replace(" ", ""), true); - - return null; - } - - public static void RegisterCustomAstroObject(AstroObject ao) - { - var key = ao._name == AstroObject.Name.CustomString ? ao.GetCustomName() : ao._name.ToString(); - - if (_customAstroObjectDictionary.Keys.Contains(key)) - { - Logger.LogWarning($"Registering duplicate [{ao.name}] as [{key}]"); - _customAstroObjectDictionary[key] = ao; - } - else - { - Logger.Log($"Registering [{ao.name}] as [{key}]"); - _customAstroObjectDictionary.Add(key, ao); - } - } - - public static void DeregisterCustomAstroObject(AstroObject ao) - { - var key = ao._name == AstroObject.Name.CustomString ? ao.GetCustomName() : ao._name.ToString(); - _customAstroObjectDictionary.Remove(key); - } - - public static AstroObject[] GetAllAstroObjects() - { - return _customAstroObjectDictionary.Values.ToArray(); - } - - public static GameObject[] GetMoons(AstroObject primary) - { - return _customAstroObjectDictionary.Values.Where(x => x._primaryBody == primary).Select(x => x.gameObject).ToArray(); - } - - public static GameObject[] GetChildren(AstroObject primary) - { - if (primary == null) return new GameObject[0]; - - var otherChildren = new List(); - switch (primary._name) - { - case AstroObject.Name.TowerTwin: - otherChildren.Add(SearchUtilities.Find("TimeLoopRing_Body")); - break; - case AstroObject.Name.ProbeCannon: - otherChildren.Add(SearchUtilities.Find("NomaiProbe_Body")); - otherChildren.Add(SearchUtilities.Find("CannonMuzzle_Body")); - otherChildren.Add(SearchUtilities.Find("FakeCannonMuzzle_Body (1)")); - otherChildren.Add(SearchUtilities.Find("CannonBarrel_Body")); - otherChildren.Add(SearchUtilities.Find("FakeCannonBarrel_Body (1)")); - otherChildren.Add(SearchUtilities.Find("Debris_Body (1)")); - break; - case AstroObject.Name.GiantsDeep: - otherChildren.Add(SearchUtilities.Find("BrambleIsland_Body")); - otherChildren.Add(SearchUtilities.Find("GabbroIsland_Body")); - otherChildren.Add(SearchUtilities.Find("QuantumIsland_Body")); - otherChildren.Add(SearchUtilities.Find("StatueIsland_Body")); - otherChildren.Add(SearchUtilities.Find("ConstructionYardIsland_Body")); - otherChildren.Add(SearchUtilities.Find("GabbroShip_Body")); - break; - case AstroObject.Name.WhiteHole: - otherChildren.Add(SearchUtilities.Find("WhiteholeStation_Body")); - otherChildren.Add(SearchUtilities.Find("WhiteholeStationSuperstructure_Body")); - break; - case AstroObject.Name.TimberHearth: - otherChildren.Add(SearchUtilities.Find("MiningRig_Body")); - otherChildren.Add(SearchUtilities.Find("Ship_Body")); - otherChildren.Add(SearchUtilities.Find("ModelRocket_Body")); - break; - case AstroObject.Name.DreamWorld: - otherChildren.Add(SearchUtilities.Find("BackRaft_Body")); - otherChildren.Add(SearchUtilities.Find("SealRaft_Body")); - break; - case AstroObject.Name.MapSatellite: - otherChildren.Add(SearchUtilities.Find("HearthianRecorder_Body")); - break; - // For some dumb reason the sun station doesn't use AstroObject.Name.SunStation - case AstroObject.Name.CustomString: - if (primary._customName.Equals("Sun Station")) - { - // there are multiple debris with the same name - otherChildren.AddRange(Object.FindObjectsOfType() - .Select(x => x.gameObject) - .Where(x => x.name == "SS_Debris_Body")); - } - break; - default: - break; - } - - return otherChildren.ToArray(); - } - } -} + } + + public static AstroObject GetAstroObject(string name, bool flag = false) + { + if (string.IsNullOrEmpty(name)) return null; + + if (_customAstroObjectDictionary.ContainsKey(name)) + { + return _customAstroObjectDictionary[name]; + } + + // Else check stock names + var stringID = name.ToUpper().Replace(" ", "_").Replace("'", ""); + if (stringID.Equals("ATTLEROCK")) stringID = "TIMBER_MOON"; + if (stringID.Equals("HOLLOWS_LANTERN")) stringID = "VOLCANIC_MOON"; + if (stringID.Equals("ASH_TWIN")) stringID = "TOWER_TWIN"; + if (stringID.Equals("EMBER_TWIN")) stringID = "CAVE_TWIN"; + if (stringID.Equals("INTERLOPER")) stringID = "COMET"; + + string key; + if (stringID.ToUpper().Replace("_", "").Equals("MAPSATELLITE")) + { + key = AstroObject.Name.MapSatellite.ToString(); + } + else + { + key = AstroObject.StringIDToAstroObjectName(stringID).ToString(); + } + + if (_customAstroObjectDictionary.ContainsKey(key)) + { + return _customAstroObjectDictionary[key]; + } + + // Try again + if (!flag) return GetAstroObject(name.Replace(" ", ""), true); + + return null; + } + + public static void RegisterCustomAstroObject(AstroObject ao) + { + var key = ao._name == AstroObject.Name.CustomString ? ao.GetCustomName() : ao._name.ToString(); + + if (_customAstroObjectDictionary.Keys.Contains(key)) + { + Logger.LogWarning($"Registering duplicate [{ao.name}] as [{key}]"); + _customAstroObjectDictionary[key] = ao; + } + else + { + Logger.Log($"Registering [{ao.name}] as [{key}]"); + _customAstroObjectDictionary.Add(key, ao); + } + } + + public static void DeregisterCustomAstroObject(AstroObject ao) + { + var key = ao._name == AstroObject.Name.CustomString ? ao.GetCustomName() : ao._name.ToString(); + _customAstroObjectDictionary.Remove(key); + } + + public static AstroObject[] GetAllAstroObjects() + { + return _customAstroObjectDictionary.Values.ToArray(); + } + + public static GameObject[] GetMoons(AstroObject primary) + { + return _customAstroObjectDictionary.Values.Where(x => x._primaryBody == primary).Select(x => x.gameObject).ToArray(); + } + + public static GameObject[] GetChildren(AstroObject primary) + { + if (primary == null) return new GameObject[0]; + + var otherChildren = new List(); + switch (primary._name) + { + case AstroObject.Name.TowerTwin: + otherChildren.Add(SearchUtilities.Find("TimeLoopRing_Body")); + break; + case AstroObject.Name.ProbeCannon: + otherChildren.Add(SearchUtilities.Find("NomaiProbe_Body")); + otherChildren.Add(SearchUtilities.Find("CannonMuzzle_Body")); + otherChildren.Add(SearchUtilities.Find("FakeCannonMuzzle_Body (1)")); + otherChildren.Add(SearchUtilities.Find("CannonBarrel_Body")); + otherChildren.Add(SearchUtilities.Find("FakeCannonBarrel_Body (1)")); + otherChildren.Add(SearchUtilities.Find("Debris_Body (1)")); + break; + case AstroObject.Name.GiantsDeep: + otherChildren.Add(SearchUtilities.Find("BrambleIsland_Body")); + otherChildren.Add(SearchUtilities.Find("GabbroIsland_Body")); + otherChildren.Add(SearchUtilities.Find("QuantumIsland_Body")); + otherChildren.Add(SearchUtilities.Find("StatueIsland_Body")); + otherChildren.Add(SearchUtilities.Find("ConstructionYardIsland_Body")); + otherChildren.Add(SearchUtilities.Find("GabbroShip_Body")); + break; + case AstroObject.Name.WhiteHole: + otherChildren.Add(SearchUtilities.Find("WhiteholeStation_Body")); + otherChildren.Add(SearchUtilities.Find("WhiteholeStationSuperstructure_Body")); + break; + case AstroObject.Name.TimberHearth: + otherChildren.Add(SearchUtilities.Find("MiningRig_Body")); + otherChildren.Add(SearchUtilities.Find("Ship_Body")); + otherChildren.Add(SearchUtilities.Find("ModelRocket_Body")); + break; + case AstroObject.Name.DreamWorld: + otherChildren.Add(SearchUtilities.Find("BackRaft_Body")); + otherChildren.Add(SearchUtilities.Find("SealRaft_Body")); + break; + case AstroObject.Name.MapSatellite: + otherChildren.Add(SearchUtilities.Find("HearthianRecorder_Body")); + break; + case AstroObject.Name.DarkBramble: + otherChildren.Add(SearchUtilities.Find("DB_ClusterDimension_Body")); + otherChildren.Add(SearchUtilities.Find("DB_VesselDimension_Body")); + otherChildren.Add(SearchUtilities.Find("DB_PioneerDimension_Body")); + otherChildren.Add(SearchUtilities.Find("DB_HubDimension_Body")); + otherChildren.Add(SearchUtilities.Find("DB_ExitOnlyDimension_Body")); + otherChildren.Add(SearchUtilities.Find("DB_EscapePodDimension_Body")); + otherChildren.Add(SearchUtilities.Find("DB_AnglerNestDimension_Body")); + break; + // For some dumb reason the sun station doesn't use AstroObject.Name.SunStation + case AstroObject.Name.CustomString: + if (primary._customName.Equals("Sun Station")) + { + // there are multiple debris with the same name + otherChildren.AddRange(Object.FindObjectsOfType() + .Select(x => x.gameObject) + .Where(x => x.name == "SS_Debris_Body")); + } + break; + default: + break; + } + + return otherChildren.ToArray(); + } + } +} diff --git a/NewHorizons/Utility/DebugUtilities/DebugRaycaster.cs b/NewHorizons/Utility/DebugUtilities/DebugRaycaster.cs index bad05a9f..6d5890f1 100644 --- a/NewHorizons/Utility/DebugUtilities/DebugRaycaster.cs +++ b/NewHorizons/Utility/DebugUtilities/DebugRaycaster.cs @@ -100,7 +100,7 @@ namespace NewHorizons.Utility.DebugUtilities var hitAstroObject = o.GetComponent() ?? o.GetComponentInParent(); data.bodyName = o.name; - data.bodyPath = SearchUtilities.GetPath(o.transform); + data.bodyPath = o.transform.GetPath(); data.hitObject = o; data.hitBodyGameObject = hitAstroObject?.gameObject ?? o; data.plane = ConstructPlane(data); diff --git a/NewHorizons/Utility/Logger.cs b/NewHorizons/Utility/Logger.cs index 0ef837d2..5935b269 100644 --- a/NewHorizons/Utility/Logger.cs +++ b/NewHorizons/Utility/Logger.cs @@ -36,7 +36,7 @@ namespace NewHorizons.Utility public static void LogPath(GameObject go) { if (go == null) Log("Can't print path: GameObject is null"); - else Log($"{SearchUtilities.GetPath(go.transform)}"); + else Log($"{go.transform.GetPath()}"); } public static void Log(string text, LogType type) diff --git a/NewHorizons/Utility/SearchUtilities.cs b/NewHorizons/Utility/SearchUtilities.cs index 8159bbea..d31310e6 100644 --- a/NewHorizons/Utility/SearchUtilities.cs +++ b/NewHorizons/Utility/SearchUtilities.cs @@ -1,8 +1,10 @@ -using System; +using HarmonyLib; using System.Collections.Generic; using System.Linq; using UnityEngine; +using UnityEngine.SceneManagement; using Object = UnityEngine.Object; + namespace NewHorizons.Utility { public static class SearchUtilities @@ -15,23 +17,6 @@ namespace NewHorizons.Utility CachedGameObjects.Clear(); } - public static GameObject CachedFind(string path) - { - if (CachedGameObjects.ContainsKey(path)) - { - return CachedGameObjects[path]; - } - else - { - GameObject foundObject = GameObject.Find(path); - if (foundObject != null) - { - CachedGameObjects.Add(path, foundObject); - } - return foundObject; - } - } - public static List FindObjectsOfTypeAndName(string name) where T : Object { T[] firstList = GameObject.FindObjectsOfType(); @@ -94,118 +79,47 @@ namespace NewHorizons.Utility return null; } - public static string GetPath(Transform current) + public static string GetPath(this Transform current) { if (current.parent == null) return current.name; - return GetPath(current.parent) + "/" + current.name; + return current.parent.GetPath() + "/" + current.name; } - /* - public static GameObject Find(string path) - { - var go = GameObject.Find(path); - if (go != null) return go; - - var names = path.Split(new char[] { '\\', '/' }); - - foreach (var possibleMatch in FindObjectsOfTypeAndName(names.Last())) - { - Logger.LogPath(possibleMatch); - if (GetPath(possibleMatch.transform) == path) return possibleMatch; - } - - return null; - } - */ - - public static GameObject FindChild(GameObject g, string childName) - { - foreach(Transform child in g.transform) - { - if (child.gameObject.name == childName) return child.gameObject; - } - - return null; - } + public static GameObject FindChild(this GameObject g, string childPath) => + g.transform.Find(childPath)?.gameObject; public static GameObject Find(string path, bool warn = true) { - if (CachedGameObjects.ContainsKey(path)) - { - return CachedGameObjects[path]; - } - try - { - var go = GameObject.Find(path); - - var names = path.Split(new char[] { '\\', '/' }); - if (go == null) - { - - // Get the root object and hope its the right one - var root = GameObject.Find(names[0]); - if (root == null) root = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects().Where(x => x.name.Equals(names[0])).FirstOrDefault(); - - var t = root?.transform; - if (t == null) - { - if (warn) Logger.LogWarning($"Couldn't find root object in path ({names[0]})"); - } - else - { - for (int i = 1; i < names.Length; i++) - { - var child = t.transform.Find(names[i]); - - if (child == null) - { - foreach (Transform c in t.GetComponentsInChildren(true)) - { - if (c.name.Equals(names[i])) - { - child = c; - break; - } - } - } - - if (child == null) - { - if (warn) Logger.LogWarning($"Couldn't find object in path ({names[i]})"); - t = null; - break; - } - - t = child; - } - } - - go = t?.gameObject; - } - - if (go == null) - { - var name = names.Last(); - if (warn) Logger.LogWarning($"Couldn't find object {path}, will look for potential matches for name {name}"); - go = FindObjectOfTypeAndName(name); - } - - if (go != null) - { - CachedGameObjects.Add(path, go); - } - - return go; - } - catch (Exception) + if (CachedGameObjects.TryGetValue(path, out var go)) return go; + + go = GameObject.Find(path); + if (go != null) return go; + + var names = path.Split('/'); + var rootName = names[0]; + var root = SceneManager.GetActiveScene().GetRootGameObjects().FirstOrDefault(x => x.name == rootName); + if (root == null) { + if (warn) Logger.LogWarning($"Couldn't find root object in path ({path})"); return null; } + + var childPath = names.Skip(1).Join(delimiter: "/"); + go = root.FindChild(childPath); + if (go == null) + { + var name = names.Last(); + if (warn) Logger.LogWarning($"Couldn't find object in path ({path}), will look for potential matches for name {name}"); + go = FindObjectOfTypeAndName(name); + } + + CachedGameObjects.Add(path, go); + return go; } - public static List GetAllChildren(GameObject parent) + public static List GetAllChildren(this GameObject parent) { - List children = new List(); + var children = new List(); foreach (Transform child in parent.transform) { children.Add(child.gameObject); diff --git a/NewHorizons/VoiceActing/IVoiceMod.cs b/NewHorizons/VoiceActing/IVoiceMod.cs new file mode 100644 index 00000000..d9b12384 --- /dev/null +++ b/NewHorizons/VoiceActing/IVoiceMod.cs @@ -0,0 +1,7 @@ +namespace NewHorizons.VoiceActing +{ + public interface IVoiceMod + { + void RegisterAssets(string assetsFolder); + } +} diff --git a/NewHorizons/VoiceActing/VoiceHandler.cs b/NewHorizons/VoiceActing/VoiceHandler.cs new file mode 100644 index 00000000..4718d5a3 --- /dev/null +++ b/NewHorizons/VoiceActing/VoiceHandler.cs @@ -0,0 +1,41 @@ +using NewHorizons.Utility; +using System.IO; +using System.Linq; + +namespace NewHorizons.VoiceActing +{ + public static class VoiceHandler + { + public static bool Enabled { get; private set; } + + private static IVoiceMod API; + + public static void Init() + { + API = Main.Instance.ModHelper.Interaction.TryGetModApi("Krevace.VoiceMod"); + + if (API == null) + { + Logger.Log("VoiceMod isn't installed"); + Enabled = false; + return; + } + + Enabled = true; + + foreach (var mod in Main.Instance.GetDependants().Append(Main.Instance)) + { + var folder = $"{mod.ModHelper.Manifest.ModFolderPath}VoiceMod"; + if (Directory.Exists(folder)) + { + Logger.Log($"Registering VoiceMod audio for {mod.ModHelper.Manifest.Name} from {folder}"); + API.RegisterAssets(folder); + } + else + { + Logger.Log($"Didn't find VoiceMod audio for {mod.ModHelper.Manifest.Name} at {folder}"); + } + } + } + } +} diff --git a/NewHorizons/manifest.json b/NewHorizons/manifest.json index 4f2896d8..b3873d1c 100644 --- a/NewHorizons/manifest.json +++ b/NewHorizons/manifest.json @@ -1,9 +1,10 @@ { + "$schema": "https://raw.githubusercontent.com/amazingalek/owml/master/schemas/manifest_schema.json", "filename": "NewHorizons.dll", - "author": "xen and Bwc9876", + "author": "xen, Bwc9876, clay, MegaPiggy, John, Book", "name": "New Horizons", "uniqueName": "xen.NewHorizons", - "version": "1.3.1", + "version": "1.3.2", "owmlVersion": "2.5.2", "conflicts": [ "Raicuparta.QuantumSpaceBuddies", "Vesper.AutoResume", "PacificEngine.OW_Randomizer" ], "pathsToPreserve": [ "planets", "systems", "translations" ]