diff --git a/NewHorizons/Builder/Atmosphere/AirBuilder.cs b/NewHorizons/Builder/Atmosphere/AirBuilder.cs index e4518e4cc..b7a3bd3ed 100644 --- a/NewHorizons/Builder/Atmosphere/AirBuilder.cs +++ b/NewHorizons/Builder/Atmosphere/AirBuilder.cs @@ -1,4 +1,5 @@ using NewHorizons.External.Configs; +using NewHorizons.Utility.OWUtilities; using UnityEngine; namespace NewHorizons.Builder.Atmosphere { @@ -8,7 +9,7 @@ public static void Make(GameObject planetGO, Sector sector, PlanetConfig config) { var airGO = new GameObject("Air"); airGO.SetActive(false); - airGO.layer = 17; + airGO.layer = Layer.BasicEffectVolume; airGO.transform.parent = sector?.transform ?? planetGO.transform; var sc = airGO.AddComponent(); diff --git a/NewHorizons/Builder/Atmosphere/CloudsBuilder.cs b/NewHorizons/Builder/Atmosphere/CloudsBuilder.cs index 7eb98eb18..d7dde4c8a 100644 --- a/NewHorizons/Builder/Atmosphere/CloudsBuilder.cs +++ b/NewHorizons/Builder/Atmosphere/CloudsBuilder.cs @@ -7,6 +7,7 @@ using Logger = NewHorizons.Utility.Logger; using System.Collections.Generic; using Tessellation; +using NewHorizons.Utility.OWUtilities; namespace NewHorizons.Builder.Atmosphere { @@ -118,7 +119,7 @@ public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atm GameObject cloudsFluidGO = new GameObject("CloudsFluid"); cloudsFluidGO.SetActive(false); - cloudsFluidGO.layer = 17; + cloudsFluidGO.layer = Layer.BasicEffectVolume; cloudsFluidGO.transform.parent = cloudsMainGO.transform; SphereCollider fluidSC = cloudsFluidGO.AddComponent(); @@ -251,7 +252,7 @@ public static GameObject MakeTopClouds(GameObject rootObject, AtmosphereModule a if (atmo.clouds.unlit) { - cloudsTopGO.layer = LayerMask.NameToLayer("IgnoreSun"); + cloudsTopGO.layer = Layer.IgnoreSun; } if (atmo.clouds.rotationSpeed != 0f) @@ -303,7 +304,7 @@ public static GameObject MakeTransparentClouds(GameObject rootObject, Atmosphere { GameObject tcrqcGO = new GameObject("TransparentCloudRenderQueueController"); tcrqcGO.transform.SetParent(cloudsTransparentGO.transform, false); - tcrqcGO.layer = LayerMask.NameToLayer("BasicEffectVolume"); + tcrqcGO.layer = Layer.BasicEffectVolume; var shape = tcrqcGO.AddComponent(); shape.radius = 1; diff --git a/NewHorizons/Builder/Body/BrambleDimensionBuilder.cs b/NewHorizons/Builder/Body/BrambleDimensionBuilder.cs index 02f32731e..fcbd1f872 100644 --- a/NewHorizons/Builder/Body/BrambleDimensionBuilder.cs +++ b/NewHorizons/Builder/Body/BrambleDimensionBuilder.cs @@ -10,6 +10,7 @@ using UnityEngine; using Logger = NewHorizons.Utility.Logger; using static NewHorizons.Main; +using NewHorizons.Utility.OWMLUtilities; namespace NewHorizons.Builder.Body { @@ -103,8 +104,7 @@ public static GameObject Make(NewHorizonsBody body, GameObject go, NHAstroObject default: geometryPrefab = _hubGeometry; break; } - var detailInfo = new PropModule.DetailInfo(); - var geometry = DetailBuilder.Make(go, sector, geometryPrefab, detailInfo); + var geometry = DetailBuilder.Make(go, sector, geometryPrefab, new PropModule.DetailInfo()); var exitWarps = _exitWarps.InstantiateInactive(); var repelVolume = _repelVolume.InstantiateInactive(); @@ -245,13 +245,13 @@ public static GameObject Make(NewHorizonsBody body, GameObject go, NHAstroObject cloak._sectors = new Sector[] { sector }; cloak.GetComponent().enabled = true; + // Cull stuff + var cullController = go.AddComponent(); + cullController.SetSector(sector); + // Do next update so other nodes can be built first Delay.FireOnNextUpdate(() => { - // Cull stuff - var cullController = go.AddComponent(); - cullController.SetSector(sector); - // Prevent recursion from causing hard crash foreach (var senderWarp in outerFogWarpVolume._senderWarps.ToList()) { diff --git a/NewHorizons/Builder/Body/CloakBuilder.cs b/NewHorizons/Builder/Body/CloakBuilder.cs index 4b0ee5588..338049594 100644 --- a/NewHorizons/Builder/Body/CloakBuilder.cs +++ b/NewHorizons/Builder/Body/CloakBuilder.cs @@ -1,6 +1,7 @@ using NewHorizons.Components; using NewHorizons.External.Modules; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using OWML.Common; using UnityEngine; using Logger = NewHorizons.Utility.Logger; diff --git a/NewHorizons/Builder/Body/FunnelBuilder.cs b/NewHorizons/Builder/Body/FunnelBuilder.cs index aeeea8819..5f1004129 100644 --- a/NewHorizons/Builder/Body/FunnelBuilder.cs +++ b/NewHorizons/Builder/Body/FunnelBuilder.cs @@ -1,10 +1,12 @@ using System.Runtime.Serialization; -using NewHorizons.Components; using NewHorizons.Utility; using UnityEngine; using Logger = NewHorizons.Utility.Logger; using NewHorizons.External.Modules.VariableSize; using NewHorizons.Components.Orbital; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; +using NewHorizons.Components.SizeControllers; namespace NewHorizons.Builder.Body { diff --git a/NewHorizons/Builder/Body/Geometry/CubeSphere.cs b/NewHorizons/Builder/Body/Geometry/CubeSphere.cs index 0e4173142..d8257fd12 100644 --- a/NewHorizons/Builder/Body/Geometry/CubeSphere.cs +++ b/NewHorizons/Builder/Body/Geometry/CubeSphere.cs @@ -1,4 +1,4 @@ -using NewHorizons.Utility; +using NewHorizons.Utility.Geometry; using UnityEngine; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Builder.Body.Geometry diff --git a/NewHorizons/Builder/Body/RingBuilder.cs b/NewHorizons/Builder/Body/RingBuilder.cs index 40d5953f5..581498eab 100644 --- a/NewHorizons/Builder/Body/RingBuilder.cs +++ b/NewHorizons/Builder/Body/RingBuilder.cs @@ -8,6 +8,7 @@ using UnityEngine; using Logger = NewHorizons.Utility.Logger; using NewHorizons.Components.Volumes; +using NewHorizons.Utility.OWUtilities; namespace NewHorizons.Builder.Body { @@ -30,7 +31,7 @@ public static GameObject Make(GameObject planetGO, Sector sector, RingModule rin ringVolume.transform.localPosition = Vector3.zero; ringVolume.transform.localScale = Vector3.one; ringVolume.transform.localRotation = Quaternion.identity; - ringVolume.layer = LayerMask.NameToLayer("BasicEffectVolume"); + ringVolume.layer = Layer.BasicEffectVolume; var ringShape = ringVolume.AddComponent(); ringShape.innerRadius = ring.innerRadius; diff --git a/NewHorizons/Builder/Body/SingularityBuilder.cs b/NewHorizons/Builder/Body/SingularityBuilder.cs index 96466121b..4ca159822 100644 --- a/NewHorizons/Builder/Body/SingularityBuilder.cs +++ b/NewHorizons/Builder/Body/SingularityBuilder.cs @@ -10,6 +10,9 @@ using System.Drawing; using Color = UnityEngine.Color; using NewHorizons.Components.Volumes; +using NewHorizons.Builder.Props; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; namespace NewHorizons.Builder.Body { @@ -29,6 +32,7 @@ public static class SingularityBuilder public static readonly int Color1 = Shader.PropertyToID("_Color"); private static Dictionary _singularitiesByID; + private static List<(string, string)> _pairsToLink; private static Mesh _blackHoleMesh; private static GameObject _blackHoleAmbience; @@ -42,14 +46,8 @@ public static class SingularityBuilder private static GameObject _whiteHoleRulesetVolume; private static GameObject _whiteHoleVolume; - private static bool _isInit; - internal static void InitPrefabs() { - if (_isInit) return; - - _isInit = true; - if (_blackHoleProxyPrefab == null) _blackHoleProxyPrefab = SearchUtilities.Find(_blackHoleProxyPath).InstantiateInactive().Rename("BlackHoleSingularity").DontDestroyOnLoad(); if (_whiteHoleProxyPrefab == null) _whiteHoleProxyPrefab = SearchUtilities.Find(_whiteHoleProxyPath).InstantiateInactive().Rename("WhiteHoleSingularity").DontDestroyOnLoad(); @@ -69,13 +67,14 @@ internal static void InitPrefabs() if (_whiteHoleVolume == null) _whiteHoleVolume = SearchUtilities.Find("WhiteHole_Body/WhiteHoleVolume").InstantiateInactive().Rename("WhiteHoleVolume").DontDestroyOnLoad(); } - public static void Make(GameObject go, Sector sector, OWRigidbody OWRB, PlanetConfig config, SingularityModule singularity) + public static void Init() { - InitPrefabs(); - - // 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(); + _singularitiesByID = new Dictionary(); + _pairsToLink = new List<(string, string)>(); + } + public static void Make(GameObject go, Sector sector, OWRigidbody OWRB, PlanetConfig config, SingularityModule singularity) + { var horizonRadius = singularity.horizonRadius; var distortRadius = singularity.distortRadius != 0f ? singularity.distortRadius : horizonRadius * 2.5f; var pairedSingularity = singularity.pairedSingularity; @@ -92,73 +91,69 @@ public static void Make(GameObject go, Sector sector, OWRigidbody OWRB, PlanetCo hasHazardVolume, singularity.targetStarSystem, singularity.curve, singularity.hasWarpEffects, singularity.renderQueueOverride, singularity.rename, singularity.parentPath, singularity.isRelativeToParent); var uniqueID = string.IsNullOrEmpty(singularity.uniqueID) ? config.name : singularity.uniqueID; + _singularitiesByID.Add(uniqueID, newSingularity); - - // Try to pair them - if (!string.IsNullOrEmpty(pairedSingularity) && newSingularity != null) + if (!string.IsNullOrEmpty(pairedSingularity)) { - if (_singularitiesByID.TryGetValue(pairedSingularity, out var pairedSingularityGO)) + if (polarity) { - switch (polarity) - { - case true: - PairSingularities(uniqueID, pairedSingularity, newSingularity, pairedSingularityGO); - break; - case false: - PairSingularities(pairedSingularity, uniqueID, pairedSingularityGO, newSingularity); - break; - } + _pairsToLink.Add((uniqueID, pairedSingularity)); + } + else + { + _pairsToLink.Add((pairedSingularity, uniqueID)); } } + } - public static void PairSingularities(string blackHoleID, string whiteHoleID, GameObject blackHole, GameObject whiteHole) + public static void PairAllSingularities() { - InitPrefabs(); - - if (blackHole == null || whiteHole == null) return; - - Logger.LogVerbose($"Pairing singularities [{blackHoleID}], [{whiteHoleID}]"); - - var whiteHoleVolume = whiteHole.GetComponentInChildren(); - var blackHoleVolume = blackHole.GetComponentInChildren(); - - if (whiteHoleVolume == null || blackHoleVolume == null) + foreach (var pair in _pairsToLink) { - Logger.LogWarning($"[{blackHoleID}] and [{whiteHoleID}] do not have compatible polarities"); - return; + var (blackHoleID, whiteHoleID) = pair; + if (!_singularitiesByID.TryGetValue(blackHoleID, out GameObject blackHole)) + { + Logger.LogWarning($"Black hole [{blackHoleID}] is missing."); + break; + } + if (!_singularitiesByID.TryGetValue(whiteHoleID, out GameObject whiteHole)) + { + Logger.LogWarning($"White hole [{whiteHoleID}] is missing."); + break; + } + var whiteHoleVolume = whiteHole.GetComponentInChildren(); + var blackHoleVolume = blackHole.GetComponentInChildren(); + if (whiteHoleVolume == null || blackHoleVolume == null) + { + Logger.LogWarning($"Singularities [{blackHoleID}] and [{whiteHoleID}] do not have compatible polarities."); + break; + } + if (blackHoleVolume._whiteHole != null && blackHoleVolume._whiteHole != whiteHoleVolume) + { + Logger.LogWarning($"Black hole [{blackHoleID}] has already been linked!"); + break; + } + Logger.LogVerbose($"Pairing singularities [{blackHoleID}], [{whiteHoleID}]"); + blackHoleVolume._whiteHole = whiteHoleVolume; } - - blackHoleVolume._whiteHole = whiteHoleVolume; } public static GameObject MakeSingularity(GameObject planetGO, Sector sector, Vector3 position, Vector3 rotation, bool polarity, float horizon, float distort, bool hasDestructionVolume, string targetStarSystem = null, TimeValuePair[] curve = null, bool warpEffects = true, int renderQueue = 2985, string rename = null, string parentPath = null, bool isRelativeToParent = false) { - InitPrefabs(); - // polarity true = black, false = white - var singularity = new GameObject(!string.IsNullOrEmpty(rename) ? rename : (polarity ? "BlackHole" : "WhiteHole")); - singularity.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(parentPath)) + var info = new SingularityModule { - var newParent = planetGO.transform.Find(parentPath); - if (newParent != null) - { - singularity.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{parentPath}"); - } - } + position = position, + rotation = rotation, + isRelativeToParent = isRelativeToParent, + parentPath = parentPath, + rename = rename, + }; - if (isRelativeToParent) - singularity.transform.localPosition = position; - else - singularity.transform.position = planetGO.transform.TransformPoint(position); + var singularity = GeneralPropBuilder.MakeNew(polarity ? "BlackHole" : "WhiteHole", planetGO, sector, info); var singularityRenderer = MakeSingularityGraphics(singularity, polarity, horizon, distort, renderQueue); @@ -190,7 +185,7 @@ public static void PairSingularities(string blackHoleID, string whiteHoleID, Gam if (hasDestructionVolume || targetStarSystem != null) { var destructionVolumeGO = new GameObject("DestructionVolume"); - destructionVolumeGO.layer = LayerMask.NameToLayer("BasicEffectVolume"); + destructionVolumeGO.layer = Layer.BasicEffectVolume; destructionVolumeGO.transform.parent = singularity.transform; destructionVolumeGO.transform.localScale = Vector3.one; destructionVolumeGO.transform.localPosition = Vector3.zero; @@ -273,20 +268,12 @@ public static void PairSingularities(string blackHoleID, string whiteHoleID, Gam whiteHoleFluidVolume.enabled = true; } - var rot = Quaternion.Euler(rotation); - if (isRelativeToParent) - singularity.transform.localRotation = rot; - else - singularity.transform.rotation = planetGO.transform.TransformRotation(rot); - singularity.SetActive(true); return singularity; } public static MeshRenderer MakeSingularityGraphics(GameObject singularity, bool polarity, float horizon, float distort, int queue = 2985) { - InitPrefabs(); - var singularityRenderer = new GameObject(polarity ? "BlackHoleRenderer" : "WhiteHoleRenderer"); singularityRenderer.transform.parent = singularity.transform; singularityRenderer.transform.localPosition = Vector3.zero; @@ -309,8 +296,6 @@ public static MeshRenderer MakeSingularityGraphics(GameObject singularity, bool public static GameObject MakeSingularityProxy(GameObject rootObject, MVector3 position, bool polarity, float horizon, float distort, TimeValuePair[] curve = null, int queue = 2985) { - InitPrefabs(); - var singularityRenderer = MakeSingularityGraphics(rootObject, polarity, horizon, distort, queue); if (position != null) singularityRenderer.transform.localPosition = position; diff --git a/NewHorizons/Builder/Body/StarBuilder.cs b/NewHorizons/Builder/Body/StarBuilder.cs index 2da12c1e5..70e09ad96 100644 --- a/NewHorizons/Builder/Body/StarBuilder.cs +++ b/NewHorizons/Builder/Body/StarBuilder.cs @@ -9,6 +9,7 @@ using UnityEngine.InputSystem.XR; using System.Linq; using NewHorizons.Components.Stars; +using NewHorizons.Utility.OWUtilities; namespace NewHorizons.Builder.Body { @@ -122,7 +123,7 @@ public static (GameObject, StarController, StarEvolutionController, Light) Make( heatVolume.transform.SetParent(starGO.transform, false); heatVolume.transform.localPosition = Vector3.zero; heatVolume.transform.localScale = Vector3.one; - heatVolume.layer = LayerMask.NameToLayer("BasicEffectVolume"); + heatVolume.layer = Layer.BasicEffectVolume; heatVolume.AddComponent().radius = 1.1f; heatVolume.AddComponent(); heatVolume.AddComponent()._damagePerSecond = 20f; @@ -132,7 +133,7 @@ public static (GameObject, StarController, StarEvolutionController, Light) Make( deathVolume.transform.SetParent(starGO.transform, false); deathVolume.transform.localPosition = Vector3.zero; deathVolume.transform.localScale = Vector3.one; - deathVolume.layer = LayerMask.NameToLayer("BasicEffectVolume"); + deathVolume.layer = Layer.BasicEffectVolume; var sphereCollider = deathVolume.AddComponent(); sphereCollider.radius = 1f; sphereCollider.isTrigger = true; @@ -148,7 +149,7 @@ public static (GameObject, StarController, StarEvolutionController, Light) Make( planetDestructionVolume.transform.SetParent(starGO.transform, false); planetDestructionVolume.transform.localPosition = Vector3.zero; planetDestructionVolume.transform.localScale = Vector3.one; - planetDestructionVolume.layer = LayerMask.NameToLayer("BasicEffectVolume"); + planetDestructionVolume.layer = Layer.BasicEffectVolume; var planetSphereCollider = planetDestructionVolume.AddComponent(); planetSphereCollider.radius = 0.8f; planetSphereCollider.isTrigger = true; @@ -445,7 +446,7 @@ public static StellarDeathController MakeSupernova(GameObject starGO, StarModule supernovaWallAudio.transform.SetParent(supernovaGO.transform, false); supernovaWallAudio.transform.localPosition = Vector3.zero; supernovaWallAudio.transform.localScale = Vector3.one; - supernovaWallAudio.layer = LayerMask.NameToLayer("BasicEffectVolume"); + supernovaWallAudio.layer = Layer.BasicEffectVolume; var audioSource = supernovaWallAudio.AddComponent(); audioSource.loop = true; audioSource.maxDistance = 2000; diff --git a/NewHorizons/Builder/Body/WaterBuilder.cs b/NewHorizons/Builder/Body/WaterBuilder.cs index 857358e56..fb0e25ecb 100644 --- a/NewHorizons/Builder/Body/WaterBuilder.cs +++ b/NewHorizons/Builder/Body/WaterBuilder.cs @@ -3,6 +3,8 @@ using UnityEngine; using NewHorizons.External.Modules.VariableSize; using Tessellation; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; namespace NewHorizons.Builder.Body { @@ -51,8 +53,8 @@ public static RadialFluidVolume Make(GameObject planetGO, Sector sector, OWRigid waterGO.transform.localScale = new Vector3(waterSize, waterSize, waterSize); // Don't ignore sun when not under clouds - waterGO.layer = 0; - Delay.FireOnNextUpdate(() => { if (planetGO.FindChild("Sector/SunOverride") != null) waterGO.layer = 15; }); + waterGO.layer = Layer.Default; + Delay.FireOnNextUpdate(() => { if (planetGO.FindChild("Sector/SunOverride") != null) waterGO.layer = Layer.IgnoreSun; }); TessellatedSphereRenderer TSR = waterGO.AddComponent(); TSR.tessellationMeshGroup = ScriptableObject.CreateInstance(); @@ -99,7 +101,7 @@ public static RadialFluidVolume Make(GameObject planetGO, Sector sector, OWRigid var buoyancyObject = new GameObject("WaterVolume"); buoyancyObject.transform.parent = waterGO.transform; buoyancyObject.transform.localScale = Vector3.one; - buoyancyObject.layer = LayerMask.NameToLayer("BasicEffectVolume"); + buoyancyObject.layer = Layer.BasicEffectVolume; var sphereCollider = buoyancyObject.AddComponent(); sphereCollider.radius = 1; diff --git a/NewHorizons/Builder/General/AstroObjectBuilder.cs b/NewHorizons/Builder/General/AstroObjectBuilder.cs index 26eb7f3b4..c11201590 100644 --- a/NewHorizons/Builder/General/AstroObjectBuilder.cs +++ b/NewHorizons/Builder/General/AstroObjectBuilder.cs @@ -1,6 +1,6 @@ using NewHorizons.Components.Orbital; using NewHorizons.External.Configs; -using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using UnityEngine; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Builder.General diff --git a/NewHorizons/Builder/General/DetectorBuilder.cs b/NewHorizons/Builder/General/DetectorBuilder.cs index fff255b5a..3610da32d 100644 --- a/NewHorizons/Builder/General/DetectorBuilder.cs +++ b/NewHorizons/Builder/General/DetectorBuilder.cs @@ -1,6 +1,7 @@ using NewHorizons.Components.Orbital; using NewHorizons.External.Configs; using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; using System.Collections.Generic; using UnityEngine; using Logger = NewHorizons.Utility.Logger; @@ -81,7 +82,7 @@ public static GameObject Make(GameObject planetGO, OWRigidbody OWRB, AstroObject detectorGO.SetActive(false); detectorGO.transform.parent = planetGO.transform; detectorGO.transform.localPosition = Vector3.zero; - detectorGO.layer = LayerMask.NameToLayer("BasicDetector"); + detectorGO.layer = Layer.BasicDetector; ConstantForceDetector forceDetector = detectorGO.AddComponent(); forceDetector._inheritElement0 = true; @@ -90,7 +91,7 @@ public static GameObject Make(GameObject planetGO, OWRigidbody OWRB, AstroObject // For falling into sun if (!config.Base.invulnerableToSun && config.Star == null && config.FocalPoint == null) { - detectorGO.layer = LayerMask.NameToLayer("AdvancedDetector"); + detectorGO.layer = Layer.AdvancedDetector; var fluidDetector = detectorGO.AddComponent(); var sphereCollider = detectorGO.AddComponent(); diff --git a/NewHorizons/Builder/General/GravityBuilder.cs b/NewHorizons/Builder/General/GravityBuilder.cs index 997e7a04f..21b729a8b 100644 --- a/NewHorizons/Builder/General/GravityBuilder.cs +++ b/NewHorizons/Builder/General/GravityBuilder.cs @@ -1,5 +1,6 @@ using NewHorizons.External.Configs; using NewHorizons.External.Modules; +using NewHorizons.Utility.OWUtilities; using UnityEngine; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Builder.General @@ -23,7 +24,7 @@ public static GravityVolume Make(GameObject planetGO, AstroObject ao, OWRigidbod var gravityGO = new GameObject("GravityWell"); gravityGO.transform.parent = planetGO.transform; gravityGO.transform.localPosition = Vector3.zero; - gravityGO.layer = 17; + gravityGO.layer = Layer.BasicEffectVolume; gravityGO.SetActive(false); var SC = gravityGO.AddComponent(); diff --git a/NewHorizons/Builder/General/RFVolumeBuilder.cs b/NewHorizons/Builder/General/RFVolumeBuilder.cs index 7ea5ab61c..bb3d032bb 100644 --- a/NewHorizons/Builder/General/RFVolumeBuilder.cs +++ b/NewHorizons/Builder/General/RFVolumeBuilder.cs @@ -1,5 +1,6 @@ using NewHorizons.External.Configs; using NewHorizons.External.Modules; +using NewHorizons.Utility.OWUtilities; using UnityEngine; namespace NewHorizons.Builder.General { @@ -12,7 +13,7 @@ public static GameObject Make(GameObject planetGO, OWRigidbody owrb, float spher var rfGO = new GameObject("RFVolume"); rfGO.transform.parent = planetGO.transform; rfGO.transform.localPosition = Vector3.zero; - rfGO.layer = 19; + rfGO.layer = Layer.ReferenceFrameVolume; rfGO.SetActive(false); var SC = rfGO.AddComponent(); diff --git a/NewHorizons/Builder/General/SpawnPointBuilder.cs b/NewHorizons/Builder/General/SpawnPointBuilder.cs index 437fb1b6b..e93b39e02 100644 --- a/NewHorizons/Builder/General/SpawnPointBuilder.cs +++ b/NewHorizons/Builder/General/SpawnPointBuilder.cs @@ -1,5 +1,9 @@ +using Epic.OnlineServices.Presence; +using NewHorizons.Builder.Props; using NewHorizons.External.Modules; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; using System; using System.Reflection; using UnityEngine; @@ -12,35 +16,21 @@ public static class SpawnPointBuilder public static SpawnPoint Make(GameObject planetGO, SpawnModule module, OWRigidbody owRigidBody) { SpawnPoint playerSpawn = null; - if (!Main.Instance.IsWarpingFromVessel && !Main.Instance.IsWarpingFromShip && module.playerSpawnPoint != null) - { - GameObject spawnGO = new GameObject("PlayerSpawnPoint"); - spawnGO.transform.parent = planetGO.transform; - spawnGO.layer = 8; - spawnGO.transform.localPosition = module.playerSpawnPoint; + if (!Main.Instance.IsWarpingFromVessel && !Main.Instance.IsWarpingFromShip && module.playerSpawn != null) + { + GameObject spawnGO = GeneralPropBuilder.MakeNew("PlayerSpawnPoint", planetGO, null, module.playerSpawn); + spawnGO.layer = Layer.PlayerSafetyCollider; playerSpawn = spawnGO.AddComponent(); playerSpawn._triggerVolumes = new OWTriggerVolume[0]; - if (module.playerSpawnRotation != null) - { - spawnGO.transform.rotation = Quaternion.Euler(module.playerSpawnRotation); - } - else - { - spawnGO.transform.rotation = Quaternion.FromToRotation(Vector3.up, (playerSpawn.transform.position - planetGO.transform.position).normalized); - } - - spawnGO.transform.position = spawnGO.transform.position + spawnGO.transform.TransformDirection(Vector3.up) * 4f; + spawnGO.transform.position += spawnGO.transform.up * 4f; } - if (module.shipSpawnPoint != null) + if (module.shipSpawn != null) { - GameObject spawnGO = new GameObject("ShipSpawnPoint"); - spawnGO.transform.parent = planetGO.transform; - spawnGO.layer = 8; - - spawnGO.transform.localPosition = module.shipSpawnPoint; + GameObject spawnGO = GeneralPropBuilder.MakeNew("ShipSpawnPoint", planetGO, null, module.shipSpawn); + spawnGO.layer = Layer.PlayerSafetyCollider; var spawnPoint = spawnGO.AddComponent(); spawnPoint._isShipSpawn = true; @@ -49,17 +39,13 @@ public static SpawnPoint Make(GameObject planetGO, SpawnModule module, OWRigidbo var ship = SearchUtilities.Find("Ship_Body"); if (ship != null) { - ship.transform.position = spawnPoint.transform.position; + ship.transform.position = spawnGO.transform.position; + ship.transform.rotation = spawnGO.transform.rotation; - if (module.shipSpawnRotation != null) - { - ship.transform.rotation = Quaternion.Euler(module.shipSpawnRotation); - } - else + // Move it up a bit more when aligning to surface + if (module.shipSpawn.alignRadial.GetValueOrDefault()) { - ship.transform.rotation = Quaternion.FromToRotation(Vector3.up, (spawnPoint.transform.position - planetGO.transform.position).normalized); - // Move it up a bit more when aligning to surface - ship.transform.position = ship.transform.position + ship.transform.TransformDirection(Vector3.up) * 4f; + ship.transform.position += ship.transform.up * 4f; } ship.GetRequiredComponent().SetBodyToMatch(owRigidBody); @@ -69,7 +55,7 @@ public static SpawnPoint Make(GameObject planetGO, SpawnModule module, OWRigidbo Logger.LogVerbose("Overriding player spawn to be inside ship"); GameObject playerSpawnGO = new GameObject("PlayerSpawnPoint"); playerSpawnGO.transform.parent = ship.transform; - playerSpawnGO.layer = 8; + playerSpawnGO.layer = Layer.PlayerSafetyCollider; playerSpawnGO.transform.localPosition = new Vector3(0, 0, 0); @@ -80,7 +66,7 @@ public static SpawnPoint Make(GameObject planetGO, SpawnModule module, OWRigidbo } } - if ((Main.Instance.IsWarpingFromVessel || (!Main.Instance.IsWarpingFromShip && module.startWithSuit)) && !suitUpQueued) + if ((Main.Instance.IsWarpingFromVessel || (!Main.Instance.IsWarpingFromShip && (module.playerSpawn?.startWithSuit ?? false))) && !suitUpQueued) { suitUpQueued = true; Delay.RunWhen(() => Main.IsSystemReady, () => SuitUp()); diff --git a/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs b/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs index 969347f3e..a6fce3fce 100644 --- a/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs +++ b/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs @@ -1,6 +1,6 @@ using NewHorizons.Components.Orbital; using NewHorizons.External.Modules; -using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; using System.Linq; using UnityEngine; using Logger = NewHorizons.Utility.Logger; diff --git a/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs b/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs index 88ebf55bf..e0fa3a58a 100644 --- a/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs +++ b/NewHorizons/Builder/Orbital/OrbitlineBuilder.cs @@ -1,6 +1,7 @@ using NewHorizons.Components.Orbital; using NewHorizons.External.Configs; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using UnityEngine; namespace NewHorizons.Builder.Orbital { diff --git a/NewHorizons/Builder/Props/BrambleNodeBuilder.cs b/NewHorizons/Builder/Props/BrambleNodeBuilder.cs index 6b8415cd0..9d191e171 100644 --- a/NewHorizons/Builder/Props/BrambleNodeBuilder.cs +++ b/NewHorizons/Builder/Props/BrambleNodeBuilder.cs @@ -3,6 +3,8 @@ using NewHorizons.External.Configs; using NewHorizons.Handlers; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; using OWML.Common; using System.Collections.Generic; using System.Linq; @@ -182,7 +184,7 @@ public static GameObject Make(GameObject go, Sector sector, BrambleNodeInfo conf var prefab = config.isSeed ? _brambleSeedPrefab : _brambleNodePrefab; // Spawn the bramble node - var brambleNode = prefab.InstantiateInactive(); + var brambleNode = GeneralPropBuilder.MakeFromPrefab(prefab, config.name ?? "Bramble Node to " + config.linksTo, go, sector, config); foreach (var collider in brambleNode.GetComponentsInChildren(true)) { collider.enabled = true; @@ -192,11 +194,6 @@ public static GameObject Make(GameObject go, Sector sector, BrambleNodeInfo conf var outerFogWarpVolume = GetOuterFogWarpVolumeFromAstroObject(go); var fogLight = brambleNode.GetComponent(); - brambleNode.transform.parent = sector?.transform ?? go.transform; - brambleNode.transform.position = go.transform.TransformPoint(config.position ?? Vector3.zero); - brambleNode.transform.rotation = go.transform.TransformRotation(Quaternion.Euler(config.rotation ?? Vector3.zero)); - brambleNode.name = config.name ?? "Bramble Node to " + config.linksTo; - // This node comes with Feldspar's signal, we don't want that though GameObject.Destroy(brambleNode.FindChild("Signal_Harmonica")); diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index 691712746..291201dd7 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -3,6 +3,7 @@ using NewHorizons.External.Modules; using NewHorizons.Handlers; using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; using OWML.Common; using System; using System.Collections.Generic; @@ -85,18 +86,17 @@ public static GameObject Make(GameObject go, Sector sector, GameObject prefab, P GameObject prop; bool isItem; + bool invalidComponentFound = false; // We save copies with all their components fixed, good if the user is placing the same detail more than once if (detail?.path != null && _fixedPrefabCache.TryGetValue((sector, detail.path), out var storedPrefab)) { - prop = storedPrefab.prefab.InstantiateInactive(); - prop.name = prefab.name; + prop = GeneralPropBuilder.MakeFromPrefab(storedPrefab.prefab, prefab.name, go, sector, detail); isItem = storedPrefab.isItem; } else { - prop = prefab.InstantiateInactive(); - prop.name = prefab.name; + prop = GeneralPropBuilder.MakeFromPrefab(prefab, prefab.name, go, sector, detail); StreamingHandler.SetUpStreaming(prop, sector); @@ -106,13 +106,20 @@ public static GameObject Make(GameObject go, Sector sector, GameObject prefab, P foreach (var component in prop.GetComponentsInChildren(true)) { + // Components can come through as null here (yes, really), + // Usually if a script was added to a prefab in an asset bundle but isn't present in the loaded mod DLLs + if (component == null) + { + invalidComponentFound = true; + continue; + } if (component.gameObject == prop && component is OWItem) isItem = true; if (sector == null) { if (FixUnsectoredComponent(component)) continue; } - else FixSectoredComponent(component, sector, isTorch); + else FixSectoredComponent(component, sector, isTorch, detail.keepLoaded); FixComponent(component, go); } @@ -124,27 +131,20 @@ public static GameObject Make(GameObject go, Sector sector, GameObject prefab, P } } - prop.transform.parent = sector?.transform ?? go.transform; + if (invalidComponentFound) + { + foreach (Transform t in prop.GetComponentsInChildren(true)) + { + if (t.GetComponents().Any(c => c == null)) + { + Logger.LogError($"Failed to instantiate component at {t.GetPath()}. This usually means there's a missing script."); + } + } + } // Items shouldn't use these else they get weird if (isItem) detail.keepLoaded = true; - prop.transform.position = detail.position == null ? go.transform.position : go.transform.TransformPoint(detail.position); - - Quaternion rot = detail.rotation == null ? Quaternion.identity : Quaternion.Euler(detail.rotation); - - if (detail.alignToNormal) - { - // Apply the rotation after aligning it with normal - var up = (prop.transform.position - go.transform.position).normalized; - prop.transform.rotation = Quaternion.FromToRotation(Vector3.up, up); - prop.transform.rotation *= rot; - } - else - { - prop.transform.rotation = go.transform.TransformRotation(rot); - } - prop.transform.localScale = detail.stretch ?? (detail.scale != 0 ? Vector3.one * detail.scale : prefab.transform.localScale); if (detail.removeChildren != null) @@ -187,40 +187,6 @@ public static GameObject Make(GameObject go, Sector sector, GameObject prefab, P GameObject.Destroy(prop); prop = newDetailGO; } - - if (detail.rename != null) - { - prop.name = detail.rename; - } - - if (!string.IsNullOrEmpty(detail.parentPath)) - { - var newParent = go.transform.Find(detail.parentPath); - if (newParent != null) - { - prop.transform.parent = newParent.transform; - } - else - { - Logger.LogError($"Cannot find parent object at path: {go.name}/{detail.parentPath}"); - } - } - - if (detail.isRelativeToParent) - { - prop.transform.localPosition = detail.position == null ? Vector3.zero : detail.position; - if (detail.alignToNormal) - { - // Apply the rotation after aligning it with normal - var up = (prop.transform.position - go.transform.position).normalized; - prop.transform.rotation = Quaternion.FromToRotation(Vector3.up, up); - prop.transform.rotation *= rot; - } - else - { - prop.transform.localRotation = rot; - } - } if (isItem) { @@ -248,19 +214,14 @@ public static GameObject Make(GameObject go, Sector sector, GameObject prefab, P /// /// Fix components that have sectors. Has a specific fix if there is a VisionTorchItem on the object. /// - /// - /// - /// - private static void FixSectoredComponent(Component component, Sector sector, bool isTorch = false) + private static void FixSectoredComponent(Component component, Sector sector, bool isTorch, bool keepLoaded) { - if (component is Sector s) - { - s.SetParentSector(sector); - } - - if (component is SectorCullGroup sectorCullGroup) + // keepLoaded should remove existing groups + // renderers/colliders get enabled later so we dont have to do that here + if (keepLoaded && component is SectorCullGroup or SectorCollisionGroup or SectorLightsCullGroup) { - sectorCullGroup._controllingProxy = null; + Component.DestroyImmediate(component); + return; } // fix Sector stuff, eg SectorCullGroup (without this, props that have a SectorCullGroup component will become invisible inappropriately) @@ -269,23 +230,41 @@ private static void FixSectoredComponent(Component component, Sector sector, boo sectorGroup.SetSector(sector); } - if (component is SectoredMonoBehaviour behaviour) + // Not doing else if here because idk if any of the classes below implement ISectorGroup + + if (component is Sector s) + { + s.SetParentSector(sector); + } + + else if (component is SectorCullGroup sectorCullGroup) + { + sectorCullGroup._controllingProxy = null; + + // fixes sector cull group deactivating renderers on map view enter and fast foward + // TODO: does this actually work? what? how? + sectorCullGroup._inMapView = false; + sectorCullGroup._isFastForwarding = false; + sectorCullGroup.SetVisible(sectorCullGroup.ShouldBeVisible(), true, false); + } + + else if(component is SectoredMonoBehaviour behaviour) { behaviour.SetSector(sector); } - if (component is OWItemSocket socket) + else if(component is OWItemSocket socket) { socket._sector = sector; } // Fix slide reel - Softlocks if this object is a vision torch - if (!isTorch && component is SlideCollectionContainer container) + else if(!isTorch && component is SlideCollectionContainer container) { sector.OnOccupantEnterSector.AddListener(_ => container.LoadStreamingTextures()); } - if (component is NomaiRemoteCameraPlatform remoteCameraPlatform) + else if(component is NomaiRemoteCameraPlatform remoteCameraPlatform) { remoteCameraPlatform._visualSector = sector; } @@ -297,7 +276,7 @@ private static void FixSectoredComponent(Component component, Sector sector, boo /// private static bool FixUnsectoredComponent(Component component) { - if (component is FogLight or SectoredMonoBehaviour) + if (component is FogLight or SectoredMonoBehaviour or ISectorGroup) { GameObject.DestroyImmediate(component); return true; @@ -308,28 +287,30 @@ private static bool FixUnsectoredComponent(Component component) private static void FixComponent(Component component, GameObject planetGO) { // Fix other components + // IgnoreSun is just a shadow casting optimization for caves and stuff so we can get rid of it + if (component is Transform && component.gameObject.layer == Layer.IgnoreSun) + { + component.gameObject.layer = Layer.Default; + } // I forget why this is here - if (component is GhostIK or GhostEffects) + else if (component is GhostIK or GhostEffects) { Component.DestroyImmediate(component); return; } - - if (component is DarkMatterVolume) + else if (component is DarkMatterVolume) { var probeVisuals = component.gameObject.transform.Find("ProbeVisuals"); if (probeVisuals != null) probeVisuals.gameObject.SetActive(true); } - - if (component is DarkMatterSubmergeController submergeController) + else if (component is DarkMatterSubmergeController submergeController) { var water = planetGO.GetComponentsInChildren().FirstOrDefault(x => x._fluidType == FluidVolume.Type.WATER); if (submergeController._fluidDetector) submergeController._fluidDetector._onlyDetectableFluid = water; } - // Fix anglerfish speed on orbiting planets - if (component is AnglerfishController angler) + else if (component is AnglerfishController angler) { try { @@ -342,50 +323,39 @@ private static void FixComponent(Component component, GameObject planetGO) } // fix campfires - if (component is InteractVolume interactVolume) + else if (component is InteractVolume) { - Delay.FireOnNextUpdate(() => interactVolume._playerCam = Locator.GetPlayerCamera()); + component.gameObject.AddComponent(); } - if (component is PlayerAttachPoint playerAttachPoint) + else if (component is PlayerAttachPoint) { - var playerBody = GameObject.Find("Player_Body"); - playerAttachPoint._playerController = playerBody.GetComponent(); - playerAttachPoint._playerOWRigidbody = playerBody.GetComponent(); - playerAttachPoint._playerTransform = playerBody.transform; - Delay.FireOnNextUpdate(() => playerAttachPoint._fpsCamController = Locator.GetPlayerCameraController()); + component.gameObject.AddComponent(); } - if (component is NomaiInterfaceOrb orb) + else if (component is NomaiInterfaceOrb orb) { orb._parentAstroObject = planetGO.GetComponent(); orb._parentBody = planetGO.GetComponent(); } - if (component is VisionTorchItem torchItem) + else if (component is VisionTorchItem torchItem) { torchItem.enabled = true; torchItem.mindProjectorTrigger.enabled = true; - Delay.FireOnNextUpdate(() => torchItem.mindSlideProjector._mindProjectorImageEffect = Locator.GetPlayerCamera().GetComponent()); + torchItem.gameObject.AddComponent(); } - if (component is Animator animator) animator.enabled = true; - if (component is Collider collider) collider.enabled = true; + else if (component is Animator animator) animator.enabled = true; + else if(component is Collider collider) collider.enabled = true; // Bug 533 - Don't show the electricity effect renderers - if (component is Renderer renderer && component.gameObject.GetComponent() == null) renderer.enabled = true; - if (component is Shape shape) shape.enabled = true; + else if (component is Renderer renderer && component.gameObject.GetComponent() == null) renderer.enabled = true; + else if(component is Shape shape) shape.enabled = true; - // fixes sector cull group deactivating renderers on map view enter and fast foward - // TODO: does this actually work? what? how? - if (component is SectorCullGroup sectorCullGroup) - { - sectorCullGroup._inMapView = false; - sectorCullGroup._isFastForwarding = false; - sectorCullGroup.SetVisible(sectorCullGroup.ShouldBeVisible(), true, false); - } - // If it's not a moving anglerfish make sure the anim controller is regular - if (component is AnglerfishAnimController && component.GetComponentInParent() == null) + else if(component is AnglerfishAnimController && component.GetComponentInParent() == null) + { component.gameObject.AddComponent(); + } } /// @@ -416,5 +386,53 @@ public void Start() Destroy(this); } } + + /// + /// Has to happen after 1 frame to work with VR + /// + [RequireComponent(typeof(InteractVolume))] + private class InteractVolumeFixer : MonoBehaviour + { + public void Start() + { + var interactVolume = GetComponent(); + interactVolume._playerCam = Locator.GetPlayerCamera(); + + Destroy(this); + } + } + + /// + /// Has to happen after 1 frame to work with VR + /// + [RequireComponent(typeof(PlayerAttachPoint))] + private class PlayerAttachPointFixer : MonoBehaviour + { + public void Start() + { + var playerAttachPoint = GetComponent(); + playerAttachPoint._playerController = Locator.GetPlayerController(); + playerAttachPoint._playerOWRigidbody = Locator.GetPlayerBody(); + playerAttachPoint._playerTransform = Locator.GetPlayerTransform(); + playerAttachPoint._fpsCamController = Locator.GetPlayerCameraController(); + + Destroy(this); + } + } + + /// + /// Has to happen after 1 frame to work with VR + /// + [RequireComponent(typeof(VisionTorchItem))] + private class VisionTorchItemFixer : MonoBehaviour + { + public void Start() + { + var torchItem = GetComponent(); + torchItem.mindSlideProjector._mindProjectorImageEffect = Locator.GetPlayerCamera().GetComponent(); + + Destroy(this); + } + } } -} \ No newline at end of file +} diff --git a/NewHorizons/Builder/Props/DialogueBuilder.cs b/NewHorizons/Builder/Props/DialogueBuilder.cs index d412e839e..c76a02ac7 100644 --- a/NewHorizons/Builder/Props/DialogueBuilder.cs +++ b/NewHorizons/Builder/Props/DialogueBuilder.cs @@ -7,6 +7,7 @@ using NewHorizons.Utility; using Logger = NewHorizons.Utility.Logger; using NewHorizons.Components; +using NewHorizons.Utility.OWUtilities; namespace NewHorizons.Builder.Props { @@ -22,37 +23,11 @@ public static (CharacterDialogueTree, RemoteDialogueTrigger) Make(GameObject go, var dialogue = MakeConversationZone(go, sector, info, mod.ModHelper); RemoteDialogueTrigger remoteTrigger = null; - if (info.remoteTriggerPosition != null || info.remoteTriggerRadius != 0) + if (info.remoteTrigger != null) { remoteTrigger = MakeRemoteDialogueTrigger(go, sector, info, dialogue); } - if (!string.IsNullOrEmpty(info.rename)) - { - dialogue.name = info.rename; - if (remoteTrigger != null) - { - remoteTrigger.name = $"{info.rename}_{remoteTrigger.name}"; - } - } - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var parent = go.transform.Find(info.parentPath); - if (parent != null) - { - dialogue.transform.parent = parent; - if (remoteTrigger != null) - { - remoteTrigger.transform.parent = parent; - } - } - else - { - Logger.LogError($"Cannot find parent object at path: {go.name}/{info.parentPath}"); - } - } - // Make the character look at the player // Useful for dialogue replacement // Overrides parent path for dialogue @@ -66,8 +41,7 @@ public static (CharacterDialogueTree, RemoteDialogueTrigger) Make(GameObject go, private static RemoteDialogueTrigger MakeRemoteDialogueTrigger(GameObject planetGO, Sector sector, PropModule.DialogueInfo info, CharacterDialogueTree dialogue) { - var conversationTrigger = new GameObject("ConversationTrigger"); - conversationTrigger.SetActive(false); + var conversationTrigger = GeneralPropBuilder.MakeNew("ConversationTrigger", planetGO, sector, info.remoteTrigger, defaultPosition: info.position, defaultParentPath: info.pathToAnimController); var remoteDialogueTrigger = conversationTrigger.AddComponent(); var sphereCollider = conversationTrigger.AddComponent(); @@ -81,7 +55,7 @@ private static RemoteDialogueTrigger MakeRemoteDialogueTrigger(GameObject planet dialogue = dialogue, prereqConditionType = RemoteDialogueTrigger.MultiConditionType.AND, // Base game never uses more than one condition anyone so we'll keep it simple - prereqConditions = string.IsNullOrEmpty(info.remoteTriggerPrereqCondition) ? new string[]{ } : new string[] { info.remoteTriggerPrereqCondition }, + prereqConditions = string.IsNullOrEmpty(info.remoteTrigger.prereqCondition) ? new string[]{ } : new string[] { info.remoteTrigger.prereqCondition }, // Just set your enter conditions in XML instead of complicating it with this onTriggerEnterConditions = new string[]{ } } @@ -89,10 +63,8 @@ private static RemoteDialogueTrigger MakeRemoteDialogueTrigger(GameObject planet remoteDialogueTrigger._activatedDialogues = new bool[1]; remoteDialogueTrigger._deactivateTriggerPostConversation = true; - sphereCollider.radius = info.remoteTriggerRadius == 0 ? info.radius : info.remoteTriggerRadius; + sphereCollider.radius = info.remoteTrigger.radius == 0 ? info.radius : info.remoteTrigger.radius; - conversationTrigger.transform.parent = sector?.transform ?? planetGO.transform; - conversationTrigger.transform.position = planetGO.transform.TransformPoint(info.remoteTriggerPosition ?? info.position); conversationTrigger.SetActive(true); return remoteDialogueTrigger; @@ -100,10 +72,9 @@ private static RemoteDialogueTrigger MakeRemoteDialogueTrigger(GameObject planet private static CharacterDialogueTree MakeConversationZone(GameObject planetGO, Sector sector, PropModule.DialogueInfo info, IModHelper mod) { - var conversationZone = new GameObject("ConversationZone"); - conversationZone.SetActive(false); + var conversationZone = GeneralPropBuilder.MakeNew("ConversationZone", planetGO, sector, info, defaultParentPath: info.pathToAnimController); - conversationZone.layer = LayerMask.NameToLayer("Interactible"); + conversationZone.layer = Layer.Interactible; var sphere = conversationZone.AddComponent(); sphere.radius = info.radius; @@ -150,21 +121,6 @@ private static CharacterDialogueTree MakeConversationZone(GameObject planetGO, S break; } - conversationZone.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - conversationZone.transform.parent = planetGO.transform.Find(info.parentPath); - } - else if (!string.IsNullOrEmpty(info.pathToAnimController)) - { - conversationZone.transform.parent = planetGO.transform.Find(info.pathToAnimController); - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) conversationZone.transform.localPosition = pos; - else conversationZone.transform.position = planetGO.transform.TransformPoint(pos); - conversationZone.SetActive(true); return dialogueTree; @@ -259,7 +215,7 @@ private static void MakePlayerTrackingZone(GameObject go, CharacterDialogueTree var playerTrackingZone = new GameObject("PlayerTrackingZone"); playerTrackingZone.SetActive(false); - playerTrackingZone.layer = LayerMask.NameToLayer("BasicEffectVolume"); + playerTrackingZone.layer = Layer.BasicEffectVolume; playerTrackingZone.SetActive(false); var sphereCollider = playerTrackingZone.AddComponent(); diff --git a/NewHorizons/Builder/Props/GeneralPropBuilder.cs b/NewHorizons/Builder/Props/GeneralPropBuilder.cs new file mode 100644 index 000000000..d80ca2457 --- /dev/null +++ b/NewHorizons/Builder/Props/GeneralPropBuilder.cs @@ -0,0 +1,105 @@ +using NewHorizons.External.Modules; +using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Builder.Props +{ + public static class GeneralPropBuilder + { + public static GameObject MakeFromExisting(GameObject go, + GameObject planetGO, Sector sector, GeneralPointPropInfo info, + MVector3 defaultPosition = null, string defaultParentPath = null, Transform parentOverride = null) + { + if (info == null) return go; + + go.transform.parent = parentOverride ?? sector?.transform ?? planetGO?.transform; + + if (info is GeneralSolarSystemPropInfo solarSystemInfo && !string.IsNullOrEmpty(solarSystemInfo.parentBody)) + { + // This can fail if the prop is built before the target planet. Only use it for SolarSystem module props + var targetPlanet = AstroObjectLocator.GetAstroObject(solarSystemInfo.parentBody); + if (targetPlanet != null) + { + planetGO = targetPlanet.gameObject; + sector = targetPlanet.GetRootSector() ?? targetPlanet.GetComponentInChildren(); + go.transform.parent = sector?.transform ?? planetGO?.transform ?? go.transform.parent; + } + else + { + Logger.LogError($"Cannot find parent body named {solarSystemInfo.parentBody}"); + } + } + + if (!string.IsNullOrEmpty(info.rename)) + { + go.name = info.rename; + } + + var parentPath = info.parentPath ?? defaultParentPath; + + if (planetGO != null && !string.IsNullOrEmpty(parentPath)) + { + var newParent = planetGO.transform.Find(parentPath); + if (newParent != null) + { + go.transform.parent = newParent; + sector = newParent.GetComponentInParent(); + } + else + { + Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{parentPath}"); + } + } + + var pos = (Vector3)(info.position ?? defaultPosition ?? Vector3.zero); + var rot = Quaternion.identity; + var alignRadial = false; + if (info is GeneralPropInfo rotInfo) + { + rot = rotInfo.rotation != null ? Quaternion.Euler(rotInfo.rotation) : Quaternion.identity; + alignRadial = rotInfo.alignRadial.HasValue && rotInfo.alignRadial.Value; + } + if (info.isRelativeToParent) + { + go.transform.localPosition = pos; + go.transform.localRotation = rot; + } + else if (planetGO != null) + { + go.transform.position = planetGO.transform.TransformPoint(pos); + go.transform.rotation = planetGO.transform.TransformRotation(rot); + } + else + { + go.transform.position = pos; + go.transform.rotation = rot; + } + if (alignRadial && planetGO != null) + { + var up = (go.transform.position - planetGO.transform.position).normalized; + go.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * rot; + } + return go; + } + + public static GameObject MakeNew(string defaultName, + GameObject planetGO, Sector sector, GeneralPointPropInfo info, + MVector3 defaultPosition = null, string defaultParentPath = null, Transform parentOverride = null) + { + var go = new GameObject(defaultName); + go.SetActive(false); + return MakeFromExisting(go, planetGO, sector, info, defaultPosition, defaultParentPath, parentOverride); + } + + public static GameObject MakeFromPrefab(GameObject prefab, string defaultName, + GameObject planetGO, Sector sector, GeneralPointPropInfo info, + MVector3 defaultPosition = null, string defaultParentPath = null, Transform parentOverride = null) + { + var go = prefab.InstantiateInactive(); + go.name = defaultName; + return MakeFromExisting(go, planetGO, sector, info, defaultPosition, defaultParentPath, parentOverride); + } + } +} diff --git a/NewHorizons/Builder/Props/GeyserBuilder.cs b/NewHorizons/Builder/Props/GeyserBuilder.cs index 11c9f02cc..cdd9c714f 100644 --- a/NewHorizons/Builder/Props/GeyserBuilder.cs +++ b/NewHorizons/Builder/Props/GeyserBuilder.cs @@ -1,5 +1,6 @@ using NewHorizons.External.Modules; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using UnityEngine; using Logger = NewHorizons.Utility.Logger; @@ -18,36 +19,12 @@ public static void Make(GameObject planetGO, Sector sector, PropModule.GeyserInf { InitPrefab(); - var geyserGO = _geyserPrefab.InstantiateInactive(); - geyserGO.name = !string.IsNullOrEmpty(info.rename) ? info.rename : "Geyser"; - geyserGO.transform.parent = sector?.transform ?? planetGO.transform; + var geyserGO = GeneralPropBuilder.MakeFromPrefab(_geyserPrefab, "Geyser", planetGO, sector, info); - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - geyserGO.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)info.position; - - // Offset height, default -97.5 pushes it underground so the spout is at the surface - var length = pos.magnitude + info.offset; - - // About 130 high, bubbles start at 10, shaft starts at 67, spout starts at 97.5 - geyserGO.transform.position = planetGO.transform.TransformPoint(pos.normalized * length); + geyserGO.transform.position += geyserGO.transform.up * info.offset; geyserGO.transform.localScale = Vector3.one; - var up = planetGO.transform.TransformPoint(pos) - planetGO.transform.position; - geyserGO.transform.rotation = Quaternion.FromToRotation(geyserGO.transform.up, up) * geyserGO.transform.rotation; - var bubbles = geyserGO.FindChild("GeyserParticles/GeyserBubbles"); var shaft = geyserGO.FindChild("GeyserParticles/GeyserShaft"); var spout = geyserGO.FindChild("GeyserParticles/GeyserSpout"); diff --git a/NewHorizons/Builder/Props/NomaiTextBuilder.cs b/NewHorizons/Builder/Props/NomaiTextBuilder.cs index 5e630fec9..19af1f49b 100644 --- a/NewHorizons/Builder/Props/NomaiTextBuilder.cs +++ b/NewHorizons/Builder/Props/NomaiTextBuilder.cs @@ -1,6 +1,7 @@ using NewHorizons.External.Modules; using NewHorizons.Handlers; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using OWML.Common; using OWML.Utils; using System; @@ -150,7 +151,7 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom switch (info.type) { - case PropModule.NomaiTextInfo.NomaiTextType.Wall: + case PropModule.NomaiTextType.Wall: { var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlPath).gameObject; @@ -215,7 +216,7 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return nomaiWallTextObj; } - case PropModule.NomaiTextInfo.NomaiTextType.Scroll: + case PropModule.NomaiTextType.Scroll: { var customScroll = _scrollPrefab.InstantiateInactive(); @@ -304,7 +305,7 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return customScroll; } - case PropModule.NomaiTextInfo.NomaiTextType.Computer: + case PropModule.NomaiTextType.Computer: { var computerObject = _computerPrefab.InstantiateInactive(); @@ -357,16 +358,9 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return computerObject; } - case PropModule.NomaiTextInfo.NomaiTextType.PreCrashComputer: + case PropModule.NomaiTextType.PreCrashComputer: { - var detailInfo = new PropModule.DetailInfo() - { - position = info.position, - parentPath = info.parentPath, - isRelativeToParent = info.isRelativeToParent, - rename = info.rename - }; - var computerObject = DetailBuilder.Make(planetGO, sector, _preCrashComputerPrefab, detailInfo); + var computerObject = DetailBuilder.Make(planetGO, sector, _preCrashComputerPrefab, new PropModule.DetailInfo(info)); computerObject.SetActive(false); var up = computerObject.transform.position - planetGO.transform.position; @@ -407,10 +401,10 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return computerObject; } - case PropModule.NomaiTextInfo.NomaiTextType.Cairn: - case PropModule.NomaiTextInfo.NomaiTextType.CairnVariant: + case PropModule.NomaiTextType.Cairn: + case PropModule.NomaiTextType.CairnVariant: { - var cairnObject = (info.type == PropModule.NomaiTextInfo.NomaiTextType.CairnVariant ? _cairnVariantPrefab : _cairnPrefab).InstantiateInactive(); + var cairnObject = (info.type == PropModule.NomaiTextType.CairnVariant ? _cairnVariantPrefab : _cairnPrefab).InstantiateInactive(); if (!string.IsNullOrEmpty(info.rename)) { @@ -482,18 +476,11 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return cairnObject; } - case PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder: - case PropModule.NomaiTextInfo.NomaiTextType.Recorder: + case PropModule.NomaiTextType.PreCrashRecorder: + case PropModule.NomaiTextType.Recorder: { - var prefab = (info.type == PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder ? _preCrashRecorderPrefab : _recorderPrefab); - var detailInfo = new PropModule.DetailInfo { - parentPath = info.parentPath, - rotation = info.rotation, - position = info.position, - isRelativeToParent = info.isRelativeToParent, - rename = info.rename - }; - var recorderObject = DetailBuilder.Make(planetGO, sector, prefab, detailInfo); + var prefab = (info.type == PropModule.NomaiTextType.PreCrashRecorder ? _preCrashRecorderPrefab : _recorderPrefab); + var recorderObject = DetailBuilder.Make(planetGO, sector, prefab, new PropModule.DetailInfo(info)); recorderObject.SetActive(false); if (info.rotation == null) @@ -517,7 +504,7 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom conversationInfoToCorrespondingSpawnedGameObject[info] = recorderObject; return recorderObject; } - case PropModule.NomaiTextInfo.NomaiTextType.Trailmarker: + case PropModule.NomaiTextType.Trailmarker: { var trailmarkerObject = _trailmarkerPrefab.InstantiateInactive(); @@ -703,9 +690,9 @@ internal static GameObject MakeArc(PropModule.NomaiTextArcInfo arcInfo, GameObje if (arcInfo.position == null) arc.transform.localPosition = Vector3.zero; else arc.transform.localPosition = new Vector3(arcInfo.position.x, arcInfo.position.y, 0); - arc.transform.localRotation = Quaternion.Euler(0, 0, arcInfo.zRotation); + arc.transform.localRotation = Quaternion.Euler(0, 0, arcInfo.zRotation.GetValueOrDefault()); - if (arcInfo.mirror) arc.transform.localScale = new Vector3(-1, 1, 1); + if (arcInfo.mirror.GetValueOrDefault()) arc.transform.localScale = new Vector3(-1, 1, 1); } // Try auto I guess else diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 4531bab76..6bddf3036 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -93,8 +93,7 @@ private static GameObject MakeSlideReel(GameObject planetGO, Sector sector, Prop if (_slideReelPrefab == null) return null; - var slideReelObj = _slideReelPrefab.InstantiateInactive(); - slideReelObj.name = !string.IsNullOrEmpty(info.rename) ? info.rename : $"Prefab_IP_Reel_{mod.ModHelper.Manifest.Name}"; + var slideReelObj = GeneralPropBuilder.MakeFromPrefab(_slideReelPrefab, $"Prefab_IP_Reel_{mod.ModHelper.Manifest.Name}", planetGO, sector, info); var slideReel = slideReelObj.GetComponent(); slideReel.SetSector(sector); @@ -107,34 +106,6 @@ private static GameObject MakeSlideReel(GameObject planetGO, Sector sector, Prop renderer.enabled = true; } - slideReelObj.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - slideReelObj.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - var rot = Quaternion.Euler((Vector3)(info.rotation ?? Vector3.zero)); - if (info.isRelativeToParent) - { - slideReelObj.transform.localPosition = pos; - slideReelObj.transform.localRotation = rot; - } - else - { - slideReelObj.transform.position = planetGO.transform.TransformPoint(pos); - slideReelObj.transform.rotation = planetGO.transform.TransformRotation(rot); - } - // Now we replace the slides int slidesCount = info.slides.Length; var slideCollection = new SlideCollection(slidesCount); @@ -195,42 +166,13 @@ public static GameObject MakeAutoProjector(GameObject planetGO, Sector sector, P if (_autoPrefab == null) return null; - var projectorObj = _autoPrefab.InstantiateInactive(); - projectorObj.name = !string.IsNullOrEmpty(info.rename) ? info.rename : $"Prefab_IP_AutoProjector_{mod.ModHelper.Manifest.Name}"; + var projectorObj = GeneralPropBuilder.MakeFromPrefab(_autoPrefab, $"Prefab_IP_AutoProjector_{mod.ModHelper.Manifest.Name}", planetGO, sector, info); var autoProjector = projectorObj.GetComponent(); autoProjector._sector = sector; var slideCollectionContainer = autoProjector.GetRequiredComponent(); - autoProjector.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - autoProjector.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - var rot = Quaternion.Euler((Vector3)(info.rotation ?? Vector3.zero)); - if (info.isRelativeToParent) - { - autoProjector.transform.localPosition = pos; - autoProjector.transform.localRotation = rot; - } - else - { - autoProjector.transform.position = planetGO.transform.TransformPoint(pos); - autoProjector.transform.rotation = planetGO.transform.TransformRotation(rot); - } - // Now we replace the slides int slidesCount = info.slides.Length; var slideCollection = new SlideCollection(slidesCount); @@ -260,15 +202,7 @@ public static GameObject MakeMindSlidesTarget(GameObject planetGO, Sector sector if (_visionTorchDetectorPrefab == null) return null; // spawn a trigger for the vision torch - var detailInfo = new PropModule.DetailInfo() - { - position = info.position, - rotation = info.rotation, - parentPath = info.parentPath, - isRelativeToParent = info.isRelativeToParent, - scale = 2 - }; - var g = DetailBuilder.Make(planetGO, sector, _visionTorchDetectorPrefab, detailInfo); + var g = DetailBuilder.Make(planetGO, sector, _visionTorchDetectorPrefab, new DetailInfo(info) { scale = 2, rename = !string.IsNullOrEmpty(info.rename) ? info.rename : "VisionStaffDetector" }); if (g == null) { @@ -276,8 +210,6 @@ public static GameObject MakeMindSlidesTarget(GameObject planetGO, Sector sector return null; } - g.name = !string.IsNullOrEmpty(info.rename) ? info.rename : "VisionStaffDetector"; - // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item var slides = info.slides; var slidesCount = slides.Length; @@ -307,15 +239,7 @@ public static GameObject MakeStandingVisionTorch(GameObject planetGO, Sector sec if (_standingVisionTorchPrefab == null) return null; // Spawn the torch itself - var detailInfo = new PropModule.DetailInfo() - { - position = info.position, - rotation = info.rotation, - parentPath = info.parentPath, - isRelativeToParent = info.isRelativeToParent, - rename = info.rename - }; - var standingTorch = DetailBuilder.Make(planetGO, sector, _standingVisionTorchPrefab, detailInfo); + var standingTorch = DetailBuilder.Make(planetGO, sector, _standingVisionTorchPrefab, new DetailInfo(info)); if (standingTorch == null) { diff --git a/NewHorizons/Builder/Props/PropBuildManager.cs b/NewHorizons/Builder/Props/PropBuildManager.cs index 4758e43a4..7466c19cf 100644 --- a/NewHorizons/Builder/Props/PropBuildManager.cs +++ b/NewHorizons/Builder/Props/PropBuildManager.cs @@ -1,4 +1,5 @@ using NewHorizons.Builder.Body; +using NewHorizons.Builder.Props.TranslatorText; using NewHorizons.Builder.ShipLog; using NewHorizons.External.Configs; using NewHorizons.Utility; @@ -6,6 +7,7 @@ using System; using System.Collections.Generic; using UnityEngine; +using static NewHorizons.External.Modules.PropModule; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Builder.Props { @@ -235,6 +237,34 @@ public static void Make(GameObject go, Sector sector, OWRigidbody planetBody, Ne } } } + if (config.Props.warpReceivers != null) + { + foreach (var warpReceiver in config.Props.warpReceivers) + { + try + { + WarpPadBuilder.Make(go, sector, warpReceiver); + } + catch (Exception ex) + { + Logger.LogError($"Couldn't make warp receiver [{warpReceiver.frequency}] for [{go.name}]:\n{ex}"); + } + } + } + if (config.Props.warpTransmitters != null) + { + foreach (var warpTransmitter in config.Props.warpTransmitters) + { + try + { + WarpPadBuilder.Make(go, sector, warpTransmitter); + } + catch (Exception ex) + { + Logger.LogError($"Couldn't make warp transmitter [{warpTransmitter.frequency}] for [{go.name}]:\n{ex}"); + } + } + } } } } diff --git a/NewHorizons/Builder/Props/QuantumBuilder.cs b/NewHorizons/Builder/Props/QuantumBuilder.cs index 8a5a383b8..f3916a35c 100644 --- a/NewHorizons/Builder/Props/QuantumBuilder.cs +++ b/NewHorizons/Builder/Props/QuantumBuilder.cs @@ -2,7 +2,7 @@ using NewHorizons.Components.Quantum; using NewHorizons.External.Configs; using NewHorizons.External.Modules; -using NewHorizons.Utility; +using NewHorizons.Utility.Geometry; using OWML.Common; using System; using System.Collections.Generic; @@ -50,11 +50,7 @@ public static void MakeSocketGroup(GameObject go, Sector sector, PlanetConfig co { var socketInfo = quantumGroup.sockets[i]; - var socket = new GameObject("Socket " + i); - socket.SetActive(false); - socket.transform.parent = groupRoot.transform; - socket.transform.localPosition = socketInfo.position; - socket.transform.localEulerAngles = socketInfo.rotation; + var socket = GeneralPropBuilder.MakeNew("Socket " + i, go, sector, socketInfo, parentOverride: groupRoot.transform); sockets[i] = socket.AddComponent(); sockets[i]._lightSources = new Light[0]; diff --git a/NewHorizons/Builder/Props/RaftBuilder.cs b/NewHorizons/Builder/Props/RaftBuilder.cs index 11b40a267..4440dbfab 100644 --- a/NewHorizons/Builder/Props/RaftBuilder.cs +++ b/NewHorizons/Builder/Props/RaftBuilder.cs @@ -52,35 +52,7 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Raf if (_prefab == null || sector == null) return null; - GameObject raftObject = _prefab.InstantiateInactive(); - raftObject.name = !string.IsNullOrEmpty(info.rename) ? info.rename : "Raft_Body"; - raftObject.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - raftObject.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - var rot = Quaternion.identity; - if (info.isRelativeToParent) - { - raftObject.transform.localPosition = pos; - raftObject.transform.localRotation = rot; - } - else - { - raftObject.transform.position = planetGO.transform.TransformPoint(pos); - raftObject.transform.rotation = planetGO.transform.TransformRotation(rot); - } + GameObject raftObject = GeneralPropBuilder.MakeFromPrefab(_prefab, "Raft_Body", planetGO, sector, info); StreamingHandler.SetUpStreaming(raftObject, sector); diff --git a/NewHorizons/Builder/Props/RemoteBuilder.cs b/NewHorizons/Builder/Props/RemoteBuilder.cs index 4fa179f38..98cf8534a 100644 --- a/NewHorizons/Builder/Props/RemoteBuilder.cs +++ b/NewHorizons/Builder/Props/RemoteBuilder.cs @@ -1,10 +1,13 @@ +using NewHorizons.Builder.Props.TranslatorText; using NewHorizons.External.Modules; using NewHorizons.Handlers; using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; using OWML.Common; using System; using System.Linq; using UnityEngine; +using static NewHorizons.External.Modules.PropModule; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Builder.Props @@ -86,7 +89,7 @@ internal static void InitPrefabs() if (_shareStonePrefab == null) { GameObject stone = new GameObject("ShareStoneFallback"); - stone.layer = LayerMask.NameToLayer("Interactible"); + stone.layer = Layer.Interactible; stone.SetActive(false); SphereCollider sc = stone.AddComponent(); sc.center = Vector3.zero; @@ -169,15 +172,7 @@ public static void Make(GameObject go, Sector sector, PropModule.RemoteInfo info public static void MakeWhiteboard(GameObject go, Sector sector, NomaiRemoteCameraPlatform.ID id, Texture2D decal, PropModule.RemoteInfo.WhiteboardInfo info, NewHorizonsBody nhBody) { - var detailInfo = new PropModule.DetailInfo() - { - position = info.position, - rotation = info.rotation, - parentPath = info.parentPath, - isRelativeToParent = info.isRelativeToParent, - rename = info.rename - }; - var whiteboard = DetailBuilder.Make(go, sector, _whiteboardPrefab, detailInfo); + var whiteboard = DetailBuilder.Make(go, sector, _whiteboardPrefab, new DetailInfo(info)); whiteboard.SetActive(false); var decalMat = new Material(_decalMaterial); @@ -194,7 +189,7 @@ public static void MakeWhiteboard(GameObject go, Sector sector, NomaiRemoteCamer { var textInfo = info.nomaiText[i]; component._remoteIDs[i] = RemoteHandler.GetPlatformID(textInfo.id); - var wallText = TranslatorTextBuilder.Make(whiteboard, sector, new PropModule.NomaiTextInfo + var wallText = TranslatorTextBuilder.Make(whiteboard, sector, new TranslatorTextInfo { arcInfo = textInfo.arcInfo, location = textInfo.location, @@ -203,7 +198,7 @@ public static void MakeWhiteboard(GameObject go, Sector sector, NomaiRemoteCamer rename = textInfo.rename, rotation = Vector3.zero, seed = textInfo.seed, - type = PropModule.NomaiTextInfo.NomaiTextType.Wall, + type = NomaiTextType.Wall, xmlFile = textInfo.xmlFile }, nhBody).GetComponent(); wallText._showTextOnStart = false; @@ -217,15 +212,7 @@ public static void MakeWhiteboard(GameObject go, Sector sector, NomaiRemoteCamer public static void MakePlatform(GameObject go, Sector sector, NomaiRemoteCameraPlatform.ID id, Texture2D decal, PropModule.RemoteInfo.PlatformInfo info, IModBehaviour mod) { - var detailInfo = new PropModule.DetailInfo() - { - position = info.position, - rotation = info.rotation, - parentPath = info.parentPath, - isRelativeToParent = info.isRelativeToParent, - rename = info.rename - }; - var platform = DetailBuilder.Make(go, sector, _remoteCameraPlatformPrefab, detailInfo); + var platform = DetailBuilder.Make(go, sector, _remoteCameraPlatformPrefab, new DetailInfo(info)); platform.SetActive(false); var decalMat = new Material(_decalMaterial); @@ -251,37 +238,7 @@ public static void MakePlatform(GameObject go, Sector sector, NomaiRemoteCameraP public static void MakeStone(GameObject go, Sector sector, NomaiRemoteCameraPlatform.ID id, Texture2D decal, PropModule.RemoteInfo.StoneInfo info, IModBehaviour mod) { - var shareStone = _shareStonePrefab.InstantiateInactive(); - - shareStone.name = !string.IsNullOrEmpty(info.rename) ? info.rename : ("ShareStone_" + id.ToString()); - - shareStone.transform.parent = sector?.transform ?? go.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = go.transform.Find(info.parentPath); - if (newParent != null) - { - shareStone.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {go.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - var rot = Quaternion.Euler((Vector3)(info.rotation ?? Vector3.zero)); - if (info.isRelativeToParent) - { - shareStone.transform.localPosition = pos; - shareStone.transform.localRotation = rot; - } - else - { - shareStone.transform.position = go.transform.TransformPoint(pos); - shareStone.transform.rotation = go.transform.TransformRotation(rot); - } + var shareStone = GeneralPropBuilder.MakeFromPrefab(_shareStonePrefab, "ShareStone_" + id.ToString(), go, sector, info); shareStone.GetComponent()._connectedPlatform = id; diff --git a/NewHorizons/Builder/Props/ScatterBuilder.cs b/NewHorizons/Builder/Props/ScatterBuilder.cs index f6583c4d2..b963b0127 100644 --- a/NewHorizons/Builder/Props/ScatterBuilder.cs +++ b/NewHorizons/Builder/Props/ScatterBuilder.cs @@ -1,6 +1,8 @@ using NewHorizons.External.Configs; using NewHorizons.External.Modules; using NewHorizons.Utility; +using NewHorizons.Utility.Geometry; +using NewHorizons.Utility.OWMLUtilities; using OWML.Common; using System; using System.Collections.Generic; diff --git a/NewHorizons/Builder/Props/SignalBuilder.cs b/NewHorizons/Builder/Props/SignalBuilder.cs index 876fc2c25..1ffe52548 100644 --- a/NewHorizons/Builder/Props/SignalBuilder.cs +++ b/NewHorizons/Builder/Props/SignalBuilder.cs @@ -1,5 +1,7 @@ using NewHorizons.External.Modules; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; using OWML.Common; using OWML.Utils; using System.Collections.Generic; @@ -109,27 +111,8 @@ public static string GetCustomSignalName(SignalName signalName) public static GameObject Make(GameObject planetGO, Sector sector, SignalModule.SignalInfo info, IModBehaviour mod) { - var signalGO = new GameObject($"Signal_{info.name}"); - signalGO.SetActive(false); - signalGO.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - signalGO.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) signalGO.transform.localPosition = pos; - else signalGO.transform.position = planetGO.transform.TransformPoint(pos); - signalGO.layer = LayerMask.NameToLayer("AdvancedEffectVolume"); + var signalGO = GeneralPropBuilder.MakeNew($"Signal_{info.name}", planetGO, sector, info); + signalGO.layer = Layer.AdvancedEffectVolume; var source = signalGO.AddComponent(); var owAudioSource = signalGO.AddComponent(); diff --git a/NewHorizons/Builder/Props/TornadoBuilder.cs b/NewHorizons/Builder/Props/TornadoBuilder.cs index 2b63bd523..2341211f2 100644 --- a/NewHorizons/Builder/Props/TornadoBuilder.cs +++ b/NewHorizons/Builder/Props/TornadoBuilder.cs @@ -2,6 +2,7 @@ using NewHorizons.External.Modules; using NewHorizons.Handlers; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using System; using UnityEngine; using Logger = NewHorizons.Utility.Logger; @@ -98,11 +99,8 @@ public static void Make(GameObject planetGO, Sector sector, PropModule.TornadoIn private static void MakeTornado(GameObject planetGO, Sector sector, PropModule.TornadoInfo info, Vector3 position, bool downwards) { - var tornadoGO = downwards ? _downPrefab.InstantiateInactive() : _upPrefab.InstantiateInactive(); - tornadoGO.name = !string.IsNullOrEmpty(info.rename) ? info.rename : (downwards ? "Tornado_Down" : "Tornado_Up"); - tornadoGO.transform.parent = sector?.transform ?? planetGO.transform; - tornadoGO.transform.position = planetGO.transform.TransformPoint(position); - tornadoGO.transform.rotation = Quaternion.FromToRotation(Vector3.up, planetGO.transform.TransformDirection(position.normalized)); + var prefab = downwards ? _downPrefab.InstantiateInactive() : _upPrefab.InstantiateInactive(); + var tornadoGO = GeneralPropBuilder.MakeFromPrefab(prefab, downwards ? "Tornado_Down" : "Tornado_Up", planetGO, sector, info, defaultPosition: position); // Add the sound thing before changing the scale var soundGO = _soundPrefab.InstantiateInactive(); diff --git a/NewHorizons/Builder/Props/TranslatorText/NomaiTextArcArranger.cs b/NewHorizons/Builder/Props/TranslatorText/NomaiTextArcArranger.cs index d05bda586..17e44ce1b 100644 --- a/NewHorizons/Builder/Props/TranslatorText/NomaiTextArcArranger.cs +++ b/NewHorizons/Builder/Props/TranslatorText/NomaiTextArcArranger.cs @@ -1,14 +1,13 @@ -using NewHorizons.Utility; -using System.Collections; +using NewHorizons.Utility.Geometry; using System.Collections.Generic; using System.Linq; using UnityEngine; -using UnityEngine.Profiling; using Logger = NewHorizons.Utility.Logger; -namespace NewHorizons.Builder.Props +namespace NewHorizons.Builder.Props.TranslatorText { - public class NomaiTextArcArranger : MonoBehaviour { + public class NomaiTextArcArranger : MonoBehaviour + { private static int MAX_MOVE_DISTANCE = 2; public List spirals = new List(); @@ -23,7 +22,7 @@ public class NomaiTextArcArranger : MonoBehaviour { public float maxY = 2.6f; public float minY = -1f; - public static SpiralManipulator CreateSpiral(NomaiTextArcBuilder.SpiralProfile profile, GameObject spiralMeshHolder) + public static SpiralManipulator CreateSpiral(NomaiTextArcBuilder.SpiralProfile profile, GameObject spiralMeshHolder) { var rootArc = NomaiTextArcBuilder.BuildSpiralGameObject(profile); rootArc.transform.parent = spiralMeshHolder.transform; @@ -31,7 +30,7 @@ public static SpiralManipulator CreateSpiral(NomaiTextArcBuilder.SpiralProfile p var manip = rootArc.AddComponent(); if (Random.value < 0.5) manip.transform.localScale = new Vector3(-1, 1, 1); // randomly mirror - + // add to arranger var arranger = spiralMeshHolder.GetAddComponent(); if (arranger.root == null) arranger.root = manip; @@ -40,11 +39,11 @@ public static SpiralManipulator CreateSpiral(NomaiTextArcBuilder.SpiralProfile p return manip; } - - public void FDGSimulationStep() + + public void FDGSimulationStep() { - if (updateToposortOnNextStep) - { + if (updateToposortOnNextStep) + { updateToposortOnNextStep = false; GenerateReverseToposort(); } @@ -56,13 +55,13 @@ public void FDGSimulationStep() Vector2 force = Vector2.zero; // accumulate the force the children feel - if (childForces.ContainsKey(s1)) + if (childForces.ContainsKey(s1)) { force += 0.9f * childForces[s1]; } - + // push away from fellow spirals - foreach (var s2 in spirals) + foreach (var s2 in spirals) { if (s1 == s2) continue; if (s1.parent == s2) continue; @@ -74,29 +73,29 @@ public void FDGSimulationStep() var f2 = (s2.localPosition - s1.localPosition); force -= f2 / Mathf.Pow(f2.magnitude, 6); } - + // push away from the edges var MAX_EDGE_PUSH_FORCE = 1; - force += new Vector2(0, -1) * Mathf.Max(0, (s1.transform.localPosition.y + maxY)*(MAX_EDGE_PUSH_FORCE / maxY) - MAX_EDGE_PUSH_FORCE); - force += new Vector2(0, 1) * Mathf.Max(0, (s1.transform.localPosition.y + minY)*(MAX_EDGE_PUSH_FORCE / minY) - MAX_EDGE_PUSH_FORCE); - force += new Vector2(-1, 0) * Mathf.Max(0, (s1.transform.localPosition.x + maxX)*(MAX_EDGE_PUSH_FORCE / maxX) - MAX_EDGE_PUSH_FORCE); - force += new Vector2(1, 0) * Mathf.Max(0, (s1.transform.localPosition.x + minX)*(MAX_EDGE_PUSH_FORCE / minX) - MAX_EDGE_PUSH_FORCE); + force += new Vector2(0, -1) * Mathf.Max(0, (s1.transform.localPosition.y + maxY) * (MAX_EDGE_PUSH_FORCE / maxY) - MAX_EDGE_PUSH_FORCE); + force += new Vector2(0, 1) * Mathf.Max(0, (s1.transform.localPosition.y + minY) * (MAX_EDGE_PUSH_FORCE / minY) - MAX_EDGE_PUSH_FORCE); + force += new Vector2(-1, 0) * Mathf.Max(0, (s1.transform.localPosition.x + maxX) * (MAX_EDGE_PUSH_FORCE / maxX) - MAX_EDGE_PUSH_FORCE); + force += new Vector2(1, 0) * Mathf.Max(0, (s1.transform.localPosition.x + minX) * (MAX_EDGE_PUSH_FORCE / minX) - MAX_EDGE_PUSH_FORCE); // push up just to make everything a little more pretty (this is not neccessary to get an arrangement that simply has no overlap/spirals exiting the bounds) - force += new Vector2(0, 1) * 1; - + force += new Vector2(0, 1) * 1; + // renormalize the force magnitude (keeps force sizes reasonable, and improves stability in the case of small forces) var avg = 1; // the size of vector required to get a medium push var scale = 0.75f; - force = force.normalized * scale * (1 / (1 + Mathf.Exp(avg-force.magnitude)) - 1 / (1 + Mathf.Exp(avg))); // apply a sigmoid-ish smoothing operation, so only giant forces actually move the spirals + force = force.normalized * scale * (1 / (1 + Mathf.Exp(avg - force.magnitude)) - 1 / (1 + Mathf.Exp(avg))); // apply a sigmoid-ish smoothing operation, so only giant forces actually move the spirals // if this is the root spiral, then rotate it instead of trying to move it - if (s1.parent == null) + if (s1.parent == null) { // this is the root spiral, so rotate instead of moving var finalAngle = Mathf.Atan2(force.y, force.x); // root spiral is always at 0, 0 var currentAngle = Mathf.Atan2(s1.center.y, s1.center.x); // root spiral is always at 0, 0 - s1.transform.localEulerAngles = new Vector3(0, 0, finalAngle-currentAngle); + s1.transform.localEulerAngles = new Vector3(0, 0, finalAngle - currentAngle); s1.UpdateChildren(); continue; @@ -105,11 +104,11 @@ public void FDGSimulationStep() // pick the parent point that's closest to center+force, and move to there var spiral = s1; var parentPoints = spiral.parent.GetComponent().GetPoints(); - + var idealPoint = spiral.position + force; var bestPointIndex = 0; var bestPointDistance = 99999999f; - for (var j = SpiralManipulator.MIN_PARENT_POINT; j < SpiralManipulator.MAX_PARENT_POINT && j < parentPoints.Length; j++) + for (var j = SpiralManipulator.MIN_PARENT_POINT; j < SpiralManipulator.MAX_PARENT_POINT && j < parentPoints.Length; j++) { // don't put this spiral on a point already occupied by a sibling if (j != spiral._parentPointIndex && spiral.parent.pointsOccupiedByChildren.Contains(j)) continue; @@ -118,33 +117,34 @@ public void FDGSimulationStep() point = spiral.parent.transform.TransformPoint(point); var dist = Vector2.Distance(point, idealPoint); - if (dist < bestPointDistance) { + if (dist < bestPointDistance) + { bestPointDistance = dist; bestPointIndex = j; } } - + // limit the distance a spiral can move in a single step bestPointIndex = spiral._parentPointIndex + Mathf.Min(MAX_MOVE_DISTANCE, Mathf.Max(-MAX_MOVE_DISTANCE, bestPointIndex - spiral._parentPointIndex)); // minimize step size to help stability - + // actually move the spiral spiral.PlaceOnParentPoint(bestPointIndex); - + // Enforce bounds - if (OutsideBounds(s1)) + if (OutsideBounds(s1)) { var start = s1._parentPointIndex; var originalMirror = s1.Mirrored; var success = AttemptToPushSpiralInBounds(s1, start); - if (!success) + if (!success) { // try flipping it if nothing worked with original mirror state - s1.Mirror(); + s1.Mirror(); success = AttemptToPushSpiralInBounds(s1, start); } - if (!success) + if (!success) { // if we couldn't put it inside the bounds, put it back how we found it (this increases stability of the rest of the spirals) if (s1.Mirrored != originalMirror) s1.Mirror(); @@ -164,22 +164,22 @@ public void GenerateReverseToposort() reverseToposortedSpirals = new List(); Queue frontierQueue = new Queue(); frontierQueue.Enqueue(root); - - while(frontierQueue.Count > 0) + + while (frontierQueue.Count > 0) { var spiral = frontierQueue.Dequeue(); reverseToposortedSpirals.Add(spiral); - - foreach(var child in spiral.children) frontierQueue.Enqueue(child); + + foreach (var child in spiral.children) frontierQueue.Enqueue(child); } - + reverseToposortedSpirals.Reverse(); } #region overlap handling // returns whether there was overlap or not - public bool AttemptOverlapResolution() + public bool AttemptOverlapResolution() { var overlappingSpirals = FindOverlap(); if (overlappingSpirals.x < 0) return false; @@ -195,27 +195,27 @@ public bool AttemptOverlapResolution() return true; } - - public Vector2Int FindOverlap() + + public Vector2Int FindOverlap() { var index = -1; - foreach (var s1 in spirals) + foreach (var s1 in spirals) { index++; if (s1.parent == null) continue; var jndex = -1; - foreach (var s2 in spirals) + foreach (var s2 in spirals) { jndex++; - if (SpiralsOverlap(s1, s2)) return new Vector2Int(index, jndex);; + if (SpiralsOverlap(s1, s2)) return new Vector2Int(index, jndex); ; } } return new Vector2Int(-1, -1); } - public bool SpiralsOverlap(SpiralManipulator s1, SpiralManipulator s2) + public bool SpiralsOverlap(SpiralManipulator s1, SpiralManipulator s2) { if (s1 == s2) return false; if (Vector3.Distance(s1.center, s2.center) > Mathf.Max(s1.NomaiTextLine.GetWorldRadius(), s2.NomaiTextLine.GetWorldRadius())) return false; // no overlap possible - too far away @@ -229,31 +229,32 @@ public bool SpiralsOverlap(SpiralManipulator s1, SpiralManipulator s2) if (s1.parent == s2) s1Points.RemoveAt(0); // don't consider the base points so that we can check if children overlap their parents if (s2.parent == s1) s2Points.RemoveAt(0); // (note: the base point of a child is always exactly overlapping with one of the parent's points) - foreach(var p1 in s1Points) + foreach (var p1 in s1Points) { - foreach(var p2 in s2Points) + foreach (var p2 in s2Points) { - if (Vector3.SqrMagnitude(p1-p2) <= thresholdForOverlap) return true; // s1 and s2 overlap + if (Vector3.SqrMagnitude(p1 - p2) <= thresholdForOverlap) return true; // s1 and s2 overlap } } return false; } - + #endregion overlap handling - + #region bounds handling - public bool OutsideBounds(SpiralManipulator spiral) + public bool OutsideBounds(SpiralManipulator spiral) { var points = spiral.NomaiTextLine.GetPoints() .Select(p => spiral.transform.TransformPoint(p)) .Select(p => spiral.transform.parent.InverseTransformPoint(p)) .ToList(); - foreach(var point in points) { + foreach (var point in points) + { if (point.x < minX || point.x > maxX || - point.y < minY || point.y > maxY) + point.y < minY || point.y > maxY) { return true; } @@ -262,29 +263,29 @@ public bool OutsideBounds(SpiralManipulator spiral) return false; } - private bool AttemptToPushSpiralInBounds(SpiralManipulator s1, int start) + private bool AttemptToPushSpiralInBounds(SpiralManipulator s1, int start) { - var range = Mathf.Max(start-SpiralManipulator.MIN_PARENT_POINT, SpiralManipulator.MAX_PARENT_POINT-start); + var range = Mathf.Max(start - SpiralManipulator.MIN_PARENT_POINT, SpiralManipulator.MAX_PARENT_POINT - start); for (var i = 1; i <= range; i++) { - if (start-i >= SpiralManipulator.MIN_PARENT_POINT) - { - s1.PlaceOnParentPoint(start-i); + if (start - i >= SpiralManipulator.MIN_PARENT_POINT) + { + s1.PlaceOnParentPoint(start - i); if (!OutsideBounds(s1)) return true; } - - if (start+i <= SpiralManipulator.MAX_PARENT_POINT) - { - s1.PlaceOnParentPoint(start+i); + + if (start + i <= SpiralManipulator.MAX_PARENT_POINT) + { + s1.PlaceOnParentPoint(start + i); if (!OutsideBounds(s1)) return true; } } return false; } - - public void DrawBoundsWithDebugSpheres() + + public void DrawBoundsWithDebugSpheres() { AddDebugShape.AddSphere(this.gameObject, 0.1f, Color.green).transform.localPosition = new Vector3(minX, minY, 0); AddDebugShape.AddSphere(this.gameObject, 0.1f, Color.green).transform.localPosition = new Vector3(minX, maxY, 0); @@ -292,17 +293,18 @@ public void DrawBoundsWithDebugSpheres() AddDebugShape.AddSphere(this.gameObject, 0.1f, Color.green).transform.localPosition = new Vector3(maxX, minY, 0); AddDebugShape.AddSphere(this.gameObject, 0.1f, Color.red).transform.localPosition = new Vector3(0, 0, 0); } - + #endregion bounds handling } - public class SpiralManipulator : MonoBehaviour { + public class SpiralManipulator : MonoBehaviour + { public SpiralManipulator parent; public List children = new List(); public HashSet pointsOccupiedByChildren = new HashSet(); public int _parentPointIndex = -1; - + public static int MIN_PARENT_POINT = 3; public static int MAX_PARENT_POINT = 26; @@ -311,32 +313,33 @@ public class SpiralManipulator : MonoBehaviour { public bool Mirrored { get { return this.transform.localScale.x < 0; } } private NomaiTextLine _NomaiTextLine; - public NomaiTextLine NomaiTextLine + public NomaiTextLine NomaiTextLine { - get + get { if (_NomaiTextLine == null) _NomaiTextLine = GetComponent(); return _NomaiTextLine; } } - public Vector2 center - { - get { return NomaiTextLine.GetWorldCenter(); } + public Vector2 center + { + get { return NomaiTextLine.GetWorldCenter(); } } - public Vector2 localPosition + public Vector2 localPosition { get { return new Vector2(this.transform.localPosition.x, this.transform.localPosition.y); } } - public Vector2 position + public Vector2 position { get { return new Vector2(this.transform.position.x, this.transform.position.y); } } - + #endregion properties - - public SpiralManipulator AddChild(NomaiTextArcBuilder.SpiralProfile profile) { + + public SpiralManipulator AddChild(NomaiTextArcBuilder.SpiralProfile profile) + { var child = NomaiTextArcArranger.CreateSpiral(profile, this.transform.parent.gameObject); var index = Random.Range(MIN_PARENT_POINT, MAX_PARENT_POINT); @@ -348,33 +351,33 @@ public Vector2 position return child; } - public void Mirror() - { + public void Mirror() + { this.transform.localScale = new Vector3(-this.transform.localScale.x, 1, 1); if (this.parent != null) this.PlaceOnParentPoint(this._parentPointIndex); } - - public void UpdateChildren() + + public void UpdateChildren() { - foreach(var child in this.children) + foreach (var child in this.children) { child.PlaceOnParentPoint(child._parentPointIndex); } } - public int PlaceOnParentPoint(int parentPointIndex, bool updateChildren=true) + public int PlaceOnParentPoint(int parentPointIndex, bool updateChildren = true) { // validate var _points = parent.GetComponent().GetPoints(); - parentPointIndex = Mathf.Max(0, Mathf.Min(parentPointIndex, _points.Length-1)); - + parentPointIndex = Mathf.Max(0, Mathf.Min(parentPointIndex, _points.Length - 1)); + // track occupied points if (this._parentPointIndex != -1) parent.pointsOccupiedByChildren.Remove(this._parentPointIndex); this._parentPointIndex = parentPointIndex; parent.pointsOccupiedByChildren.Add(parentPointIndex); // calculate the normal - var normal = _points[Mathf.Min(parentPointIndex+1, _points.Length-1)] - _points[Mathf.Max(parentPointIndex-1, 0)]; + var normal = _points[Mathf.Min(parentPointIndex + 1, _points.Length - 1)] - _points[Mathf.Max(parentPointIndex - 1, 0)]; if (parent.transform.localScale.x < 0) normal = new Vector3(normal.x, -normal.y, -normal.z); float rot = Mathf.Atan2(normal.y, normal.x) * Mathf.Rad2Deg; diff --git a/NewHorizons/Builder/Props/TranslatorText/NomaiTextArcBuilder.cs b/NewHorizons/Builder/Props/TranslatorText/NomaiTextArcBuilder.cs index cb7343fa8..e8f5e8ec7 100644 --- a/NewHorizons/Builder/Props/TranslatorText/NomaiTextArcBuilder.cs +++ b/NewHorizons/Builder/Props/TranslatorText/NomaiTextArcBuilder.cs @@ -1,9 +1,8 @@ -using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; -namespace NewHorizons.Builder.Props +namespace NewHorizons.Builder.Props.TranslatorText { public static class NomaiTextArcBuilder { // TODO: stranger arcs diff --git a/NewHorizons/Builder/Props/TranslatorText/TranslatorTextBuilder.cs b/NewHorizons/Builder/Props/TranslatorText/TranslatorTextBuilder.cs index 96899393c..213f3605a 100644 --- a/NewHorizons/Builder/Props/TranslatorText/TranslatorTextBuilder.cs +++ b/NewHorizons/Builder/Props/TranslatorText/TranslatorTextBuilder.cs @@ -1,20 +1,21 @@ +using HarmonyLib; using NewHorizons.External.Modules; using NewHorizons.Handlers; using NewHorizons.Utility; -using OWML.Common; +using NewHorizons.Utility.Geometry; +using NewHorizons.Utility.OWMLUtilities; +using Newtonsoft.Json; +using OWML.Utils; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml; using UnityEngine; -using Enum = System.Enum; using Logger = NewHorizons.Utility.Logger; using Random = UnityEngine.Random; -using OWML.Utils; -using Newtonsoft.Json; -using System; -namespace NewHorizons.Builder.Props +namespace NewHorizons.Builder.Props.TranslatorText { public static class TranslatorTextBuilder { @@ -22,7 +23,7 @@ public static class TranslatorTextBuilder private static Material _adultArcMaterial; private static Material _childArcMaterial; private static GameObject _scrollPrefab; - private static GameObject _computerPrefab; + public static GameObject ComputerPrefab { get; private set; } private static GameObject _preCrashComputerPrefab; private static GameObject _cairnPrefab; private static GameObject _cairnVariantPrefab; @@ -37,9 +38,9 @@ public static GameObject GetSpawnedGameObjectByNomaiTextArcInfo(PropModule.Nomai return arcInfoToCorrespondingSpawnedGameObject[arc]; } - private static Dictionary conversationInfoToCorrespondingSpawnedGameObject = new Dictionary(); + private static Dictionary conversationInfoToCorrespondingSpawnedGameObject = new Dictionary(); - public static GameObject GetSpawnedGameObjectByNomaiTextInfo(PropModule.NomaiTextInfo convo) + public static GameObject GetSpawnedGameObjectByTranslatorTextInfo(PropModule.TranslatorTextInfo convo) { Logger.LogVerbose("Retrieving wall text obj for " + convo); if (!conversationInfoToCorrespondingSpawnedGameObject.ContainsKey(convo)) return null; @@ -75,120 +76,76 @@ internal static void InitPrefabs() .sharedMaterial; } - if (_scrollPrefab == null) _scrollPrefab = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_HangingCity/Sector_HangingCity_District2/Interactables_HangingCity_District2/Prefab_NOM_Scroll").InstantiateInactive().Rename("Prefab_NOM_Scroll").DontDestroyOnLoad(); + if (_scrollPrefab == null) + { + _scrollPrefab = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_HangingCity/Sector_HangingCity_District2/Interactables_HangingCity_District2/Prefab_NOM_Scroll").InstantiateInactive().Rename("Prefab_NOM_Scroll").DontDestroyOnLoad(); + } - if (_computerPrefab == null) + if (ComputerPrefab == null) { - _computerPrefab = SearchUtilities.Find("VolcanicMoon_Body/Sector_VM/Interactables_VM/Prefab_NOM_Computer").InstantiateInactive().Rename("Prefab_NOM_Computer").DontDestroyOnLoad(); - _computerPrefab.transform.rotation = Quaternion.identity; + ComputerPrefab = SearchUtilities.Find("VolcanicMoon_Body/Sector_VM/Interactables_VM/Prefab_NOM_Computer").InstantiateInactive().Rename("Prefab_NOM_Computer").DontDestroyOnLoad(); } if (_preCrashComputerPrefab == null) { _preCrashComputerPrefab = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_EscapePodCrashSite/Sector_CrashFragment/EscapePod_Socket/Interactibles_EscapePod/Prefab_NOM_Vessel_Computer").InstantiateInactive().Rename("Prefab_NOM_Vessel_Computer").DontDestroyOnLoad(); - _preCrashComputerPrefab.transform.rotation = Quaternion.identity; } if (_cairnPrefab == null) { _cairnPrefab = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_Crossroads/Interactables_Crossroads/Trailmarkers/Prefab_NOM_BH_Cairn_Arc (1)").InstantiateInactive().Rename("Prefab_NOM_Cairn").DontDestroyOnLoad(); - _cairnPrefab.transform.rotation = Quaternion.identity; } if (_cairnVariantPrefab == null) { _cairnVariantPrefab = SearchUtilities.Find("TimberHearth_Body/Sector_TH/Sector_NomaiMines/Interactables_NomaiMines/Prefab_NOM_TH_Cairn_Arc").InstantiateInactive().Rename("Prefab_NOM_Cairn").DontDestroyOnLoad(); - _cairnVariantPrefab.transform.rotation = Quaternion.identity; } if (_recorderPrefab == null) { _recorderPrefab = SearchUtilities.Find("Comet_Body/Prefab_NOM_Shuttle/Sector_NomaiShuttleInterior/Interactibles_NomaiShuttleInterior/Prefab_NOM_Recorder").InstantiateInactive().Rename("Prefab_NOM_Recorder").DontDestroyOnLoad(); - _recorderPrefab.transform.rotation = Quaternion.identity; } if (_preCrashRecorderPrefab == null) { _preCrashRecorderPrefab = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_EscapePodCrashSite/Sector_CrashFragment/Interactables_CrashFragment/Prefab_NOM_Recorder").InstantiateInactive().Rename("Prefab_NOM_Recorder_Vessel").DontDestroyOnLoad(); - _preCrashRecorderPrefab.transform.rotation = Quaternion.identity; } if (_trailmarkerPrefab == null) { _trailmarkerPrefab = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_HangingCity/Sector_HangingCity_District2/Interactables_HangingCity_District2/Prefab_NOM_Sign").InstantiateInactive().Rename("Prefab_NOM_Trailmarker").DontDestroyOnLoad(); - _trailmarkerPrefab.transform.rotation = Quaternion.identity; } } - public static GameObject Make(GameObject planetGO, Sector sector, PropModule.NomaiTextInfo info, NewHorizonsBody nhBody) + public static GameObject Make(GameObject planetGO, Sector sector, PropModule.TranslatorTextInfo info, NewHorizonsBody nhBody) { InitPrefabs(); - var xmlPath = File.ReadAllText(Path.Combine(nhBody.Mod.ModHelper.Manifest.ModFolderPath, info.xmlFile)); + var xmlContent = !string.IsNullOrEmpty(info.xmlFile) ? File.ReadAllText(Path.Combine(nhBody.Mod.ModHelper.Manifest.ModFolderPath, info.xmlFile)) : null; + + if (xmlContent == null && info.type != PropModule.NomaiTextType.Whiteboard) + { + Logger.LogError($"Failed to create translator text because {nameof(info.xmlFile)} was not set to a valid text .xml file path"); + return null; + } switch (info.type) { - case PropModule.NomaiTextInfo.NomaiTextType.Wall: + case PropModule.NomaiTextType.Wall: { - var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlPath, nhBody).gameObject; - - if (!string.IsNullOrEmpty(info.rename)) - { - nomaiWallTextObj.name = info.rename; - } - - nomaiWallTextObj.transform.parent = sector?.transform ?? planetGO.transform; + var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlContent, nhBody).gameObject; + nomaiWallTextObj = GeneralPropBuilder.MakeFromExisting(nomaiWallTextObj, planetGO, sector, info); - if (!string.IsNullOrEmpty(info.parentPath)) + if (info.normal != null) { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - nomaiWallTextObj.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } + var up = (nomaiWallTextObj.transform.position - planetGO.transform.position).normalized; + var forward = planetGO.transform.TransformDirection(info.normal).normalized; - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) - { - nomaiWallTextObj.transform.localPosition = pos; - 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; + nomaiWallTextObj.transform.forward = forward; - nomaiWallTextObj.transform.up = up; - nomaiWallTextObj.transform.forward = forward; - } - if (info.rotation != null) - { - nomaiWallTextObj.transform.localRotation = Quaternion.Euler(info.rotation); - } - } - else - { - nomaiWallTextObj.transform.position = planetGO.transform.TransformPoint(pos); - 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; - - nomaiWallTextObj.transform.forward = forward; - - var desiredUp = Vector3.ProjectOnPlane(up, forward); - var zRotation = Vector3.SignedAngle(nomaiWallTextObj.transform.up, desiredUp, forward); - nomaiWallTextObj.transform.RotateAround(nomaiWallTextObj.transform.position, forward, zRotation); - } - if (info.rotation != null) - { - nomaiWallTextObj.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); - } + var desiredUp = Vector3.ProjectOnPlane(up, forward); + var zRotation = Vector3.SignedAngle(nomaiWallTextObj.transform.up, desiredUp, forward); + nomaiWallTextObj.transform.RotateAround(nomaiWallTextObj.transform.position, forward, zRotation); } // nomaiWallTextObj.GetComponent().DrawBoundsWithDebugSpheres(); @@ -198,20 +155,11 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return nomaiWallTextObj; } - case PropModule.NomaiTextInfo.NomaiTextType.Scroll: + case PropModule.NomaiTextType.Scroll: { - var customScroll = _scrollPrefab.InstantiateInactive(); + var customScroll = GeneralPropBuilder.MakeFromPrefab(_scrollPrefab, _scrollPrefab.name, planetGO, sector, info); - if (!string.IsNullOrEmpty(info.rename)) - { - customScroll.name = info.rename; - } - else - { - customScroll.name = _scrollPrefab.name; - } - - var nomaiWallText = MakeWallText(planetGO, sector, info, xmlPath, nhBody); + var nomaiWallText = MakeWallText(planetGO, sector, info, xmlContent, nhBody); nomaiWallText.transform.parent = customScroll.transform; nomaiWallText.transform.localPosition = Vector3.zero; nomaiWallText.transform.localRotation = Quaternion.identity; @@ -237,36 +185,6 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom // 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; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - customScroll.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) customScroll.transform.localPosition = pos; - else customScroll.transform.position = planetGO.transform.TransformPoint(pos); - - var up = planetGO.transform.InverseTransformPoint(customScroll.transform.position).normalized; - if (info.rotation != null) - { - customScroll.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); - } - else - { - customScroll.transform.rotation = Quaternion.FromToRotation(customScroll.transform.up, up) * customScroll.transform.rotation; - } - customScroll.SetActive(true); Delay.FireOnNextUpdate( @@ -289,50 +207,18 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return customScroll; } - case PropModule.NomaiTextInfo.NomaiTextType.Computer: + case PropModule.NomaiTextType.Computer: { - var computerObject = _computerPrefab.InstantiateInactive(); - - if (!string.IsNullOrEmpty(info.rename)) - { - computerObject.name = info.rename; - } - else - { - computerObject.name = _computerPrefab.name; - } - - computerObject.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - computerObject.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) computerObject.transform.localPosition = pos; - else computerObject.transform.position = planetGO.transform.TransformPoint(pos); - - 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 computerObject = GeneralPropBuilder.MakeFromPrefab(ComputerPrefab, ComputerPrefab.name, planetGO, sector, info); var computer = computerObject.GetComponent(); computer.SetSector(sector); computer._location = EnumUtils.Parse(info.location.ToString()); - computer._dictNomaiTextData = MakeNomaiTextDict(xmlPath); - computer._nomaiTextAsset = new TextAsset(xmlPath); + computer._dictNomaiTextData = MakeNomaiTextDict(xmlContent); + computer._nomaiTextAsset = new TextAsset(xmlContent); computer._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile); - AddTranslation(xmlPath); + AddTranslation(xmlContent); // Make sure the computer model is loaded StreamingHandler.SetUpStreaming(computerObject, sector); @@ -342,30 +228,19 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return computerObject; } - case PropModule.NomaiTextInfo.NomaiTextType.PreCrashComputer: + case PropModule.NomaiTextType.PreCrashComputer: { - var detailInfo = new PropModule.DetailInfo() - { - position = info.position, - parentPath = info.parentPath, - isRelativeToParent = info.isRelativeToParent, - rename = info.rename - }; - var computerObject = DetailBuilder.Make(planetGO, sector, _preCrashComputerPrefab, detailInfo); + var computerObject = DetailBuilder.Make(planetGO, sector, _preCrashComputerPrefab, new PropModule.DetailInfo(info)); computerObject.SetActive(false); - 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); computer._location = EnumUtils.Parse(info.location.ToString()); - computer._dictNomaiTextData = MakeNomaiTextDict(xmlPath); - computer._nomaiTextAsset = new TextAsset(xmlPath); + computer._dictNomaiTextData = MakeNomaiTextDict(xmlContent); + computer._nomaiTextAsset = new TextAsset(xmlContent); computer._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile); - AddTranslation(xmlPath); + AddTranslation(xmlContent); // Make fifth ring work var fifthRingObject = computerObject.FindChild("Props_NOM_Vessel_Computer 1/Props_NOM_Vessel_Computer_Effects (4)"); @@ -392,62 +267,26 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return computerObject; } - case PropModule.NomaiTextInfo.NomaiTextType.Cairn: - case PropModule.NomaiTextInfo.NomaiTextType.CairnVariant: + case PropModule.NomaiTextType.Cairn: + case PropModule.NomaiTextType.CairnVariant: { - var cairnObject = (info.type == PropModule.NomaiTextInfo.NomaiTextType.CairnVariant ? _cairnVariantPrefab : _cairnPrefab).InstantiateInactive(); - - if (!string.IsNullOrEmpty(info.rename)) - { - cairnObject.name = info.rename; - } - else - { - cairnObject.name = _cairnPrefab.name; - } - - cairnObject.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - cairnObject.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) cairnObject.transform.localPosition = pos; - else cairnObject.transform.position = planetGO.transform.TransformPoint(pos); - - if (info.rotation != null) - { - var rot = Quaternion.Euler(info.rotation); - if (info.isRelativeToParent) cairnObject.transform.localRotation = rot; - else cairnObject.transform.rotation = planetGO.transform.TransformRotation(rot); - } - 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; - } + var cairnPrefab = info.type == PropModule.NomaiTextType.CairnVariant ? _cairnVariantPrefab : _cairnPrefab; + var cairnObject = GeneralPropBuilder.MakeFromPrefab(cairnPrefab, _cairnPrefab.name, planetGO, sector, info); // 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) + // idk why, but sometimes stuff is null here, so just wait a frame to let it initialize + Delay.FireOnNextUpdate(() => { - rock._returning = false; - rock._owCollider.SetActivation(true); - rock.enabled = false; - } + 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; @@ -456,10 +295,10 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom nomaiWallText.SetSector(sector); nomaiWallText._location = EnumUtils.Parse(info.location.ToString()); - nomaiWallText._dictNomaiTextData = MakeNomaiTextDict(xmlPath); - nomaiWallText._nomaiTextAsset = new TextAsset(xmlPath); + nomaiWallText._dictNomaiTextData = MakeNomaiTextDict(xmlContent); + nomaiWallText._nomaiTextAsset = new TextAsset(xmlContent); nomaiWallText._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile); - AddTranslation(xmlPath); + AddTranslation(xmlContent); // Make sure the computer model is loaded StreamingHandler.SetUpStreaming(cairnObject, sector); @@ -467,34 +306,21 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return cairnObject; } - case PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder: - case PropModule.NomaiTextInfo.NomaiTextType.Recorder: + case PropModule.NomaiTextType.PreCrashRecorder: + case PropModule.NomaiTextType.Recorder: { - var prefab = (info.type == PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder ? _preCrashRecorderPrefab : _recorderPrefab); - var detailInfo = new PropModule.DetailInfo { - parentPath = info.parentPath, - rotation = info.rotation, - position = info.position, - isRelativeToParent = info.isRelativeToParent, - rename = info.rename - }; - var recorderObject = DetailBuilder.Make(planetGO, sector, prefab, detailInfo); + var prefab = (info.type == PropModule.NomaiTextType.PreCrashRecorder ? _preCrashRecorderPrefab : _recorderPrefab); + var recorderObject = DetailBuilder.Make(planetGO, sector, prefab, new PropModule.DetailInfo(info)); recorderObject.SetActive(false); - if (info.rotation == null) - { - 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._location = EnumUtils.Parse(info.location.ToString()); - nomaiText._dictNomaiTextData = MakeNomaiTextDict(xmlPath); - nomaiText._nomaiTextAsset = new TextAsset(xmlPath); + nomaiText._dictNomaiTextData = MakeNomaiTextDict(xmlContent); + nomaiText._nomaiTextAsset = new TextAsset(xmlContent); nomaiText._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile); - AddTranslation(xmlPath); + AddTranslation(xmlContent); recorderObject.SetActive(true); @@ -502,54 +328,13 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom conversationInfoToCorrespondingSpawnedGameObject[info] = recorderObject; return recorderObject; } - case PropModule.NomaiTextInfo.NomaiTextType.Trailmarker: + case PropModule.NomaiTextType.Trailmarker: { - var trailmarkerObject = _trailmarkerPrefab.InstantiateInactive(); - - if (!string.IsNullOrEmpty(info.rename)) - { - trailmarkerObject.name = info.rename; - } - else - { - trailmarkerObject.name = _trailmarkerPrefab.name; - } - - trailmarkerObject.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - trailmarkerObject.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) trailmarkerObject.transform.localPosition = pos; - else trailmarkerObject.transform.position = planetGO.transform.TransformPoint(pos); + var trailmarkerObject = GeneralPropBuilder.MakeFromPrefab(_trailmarkerPrefab, _trailmarkerPrefab.name, planetGO, sector, info); // shrink because that is what mobius does on all trailmarkers or else they are the size of the player trailmarkerObject.transform.localScale = Vector3.one * 0.75f; - if (info.rotation != null) - { - var rot = Quaternion.Euler(info.rotation); - if (info.isRelativeToParent) trailmarkerObject.transform.localRotation = rot; - else trailmarkerObject.transform.rotation = planetGO.transform.TransformRotation(rot); - } - else - { - // By default align it to normal - var up = (trailmarkerObject.transform.position - planetGO.transform.position).normalized; - trailmarkerObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * trailmarkerObject.transform.rotation; - } - // Idk do we have to set it active before finding things? trailmarkerObject.SetActive(true); @@ -557,10 +342,10 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom nomaiWallText.SetSector(sector); nomaiWallText._location = EnumUtils.Parse(info.location.ToString()); - nomaiWallText._dictNomaiTextData = MakeNomaiTextDict(xmlPath); - nomaiWallText._nomaiTextAsset = new TextAsset(xmlPath); + nomaiWallText._dictNomaiTextData = MakeNomaiTextDict(xmlContent); + nomaiWallText._nomaiTextAsset = new TextAsset(xmlContent); nomaiWallText._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile); - AddTranslation(xmlPath); + AddTranslation(xmlContent); // Make sure the model is loaded StreamingHandler.SetUpStreaming(trailmarkerObject, sector); @@ -568,13 +353,46 @@ public static GameObject Make(GameObject planetGO, Sector sector, PropModule.Nom return trailmarkerObject; } + case PropModule.NomaiTextType.Whiteboard: + { + var whiteboardInfo = new PropModule.DetailInfo(info) + { + path = "BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_HangingCity/Sector_HangingCity_District2/Interactables_HangingCity_District2/VisibleFrom_HangingCity/Props_NOM_Whiteboard (1)", + rename = info.rename ?? "Props_NOM_Whiteboard", + }; + var whiteboardObject = DetailBuilder.Make(planetGO, sector, whiteboardInfo); + + // Spawn a scroll and insert it into the whiteboard, but only if text is provided + if (!string.IsNullOrEmpty(info.xmlFile)) + { + var scrollSocket = whiteboardObject.GetComponentInChildren(); + + var scrollInfo = new PropModule.TranslatorTextInfo() + { + type = PropModule.NomaiTextType.Scroll, + arcInfo = info.arcInfo, + seed = info.seed, + xmlFile = info.xmlFile, + }; + + var scrollObject = Make(planetGO, sector, scrollInfo, nhBody); + var scrollItem = scrollObject.GetComponent(); + + Delay.FireOnNextUpdate(() => + { + scrollSocket.PlaceIntoSocket(scrollItem); + }); + } + + return whiteboardObject; + } default: Logger.LogError($"Unsupported NomaiText type {info.type}"); return null; } } - private static NomaiWallText MakeWallText(GameObject go, Sector sector, PropModule.NomaiTextInfo info, string xmlPath, NewHorizonsBody nhBody) + private static NomaiWallText MakeWallText(GameObject go, Sector sector, PropModule.TranslatorTextInfo info, string xmlPath, NewHorizonsBody nhBody) { GameObject nomaiWallTextObj = new GameObject("NomaiWallText"); nomaiWallTextObj.SetActive(false); @@ -611,7 +429,7 @@ private static NomaiWallText MakeWallText(GameObject go, Sector sector, PropModu return nomaiWallText; } - internal static void BuildArcs(string xml, NomaiWallText nomaiWallText, GameObject conversationZone, PropModule.NomaiTextInfo info, NewHorizonsBody nhBody) + internal static void BuildArcs(string xml, NomaiWallText nomaiWallText, GameObject conversationZone, PropModule.TranslatorTextInfo info, NewHorizonsBody nhBody) { var dict = MakeNomaiTextDict(xml); @@ -631,7 +449,7 @@ private struct ArcCacheData public bool mirrored; } - internal static void RefreshArcs(NomaiWallText nomaiWallText, GameObject conversationZone, PropModule.NomaiTextInfo info, NewHorizonsBody nhBody, string cacheKey) + internal static void RefreshArcs(NomaiWallText nomaiWallText, GameObject conversationZone, PropModule.TranslatorTextInfo info, NewHorizonsBody nhBody, string cacheKey) { var dict = nomaiWallText._dictNomaiTextData; Random.InitState(info.seed == 0 ? info.xmlFile.GetHashCode() : info.seed); @@ -704,15 +522,13 @@ internal static void RefreshArcs(NomaiWallText nomaiWallText, GameObject convers var arcInfo = info.arcInfo[j]; var arc = arranger.spirals[j]; - if (arcInfo.keepAutoPlacement) continue; - - if (arcInfo.position == null) arc.transform.localPosition = Vector3.zero; - else arc.transform.localPosition = new Vector3(arcInfo.position.x, arcInfo.position.y, 0); - - arc.transform.localRotation = Quaternion.Euler(0, 0, arcInfo.zRotation); - - if (arcInfo.mirror) arc.transform.localScale = new Vector3(-1, 1, 1); - else arc.transform.localScale = new Vector3( 1, 1, 1); + if (arcInfo.position != null || arcInfo.zRotation != null || arcInfo.mirror != null) + { + var pos = (Vector2)(arcInfo.position ?? Vector2.zero); + arc.transform.localPosition = new Vector3(pos.x, pos.y, 0); + arc.transform.localRotation = Quaternion.Euler(0, 0, arcInfo.zRotation.GetValueOrDefault()); + arc.transform.localScale = arcInfo.mirror.GetValueOrDefault() ? new Vector3(-1, 1, 1) : new Vector3(1, 1, 1); + } } // make an entry in the cache for all these spirals diff --git a/NewHorizons/Builder/Props/VolcanoBuilder.cs b/NewHorizons/Builder/Props/VolcanoBuilder.cs index e5e902355..6d39a591b 100644 --- a/NewHorizons/Builder/Props/VolcanoBuilder.cs +++ b/NewHorizons/Builder/Props/VolcanoBuilder.cs @@ -1,5 +1,6 @@ using NewHorizons.External.Modules; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using UnityEngine; using Logger = NewHorizons.Utility.Logger; @@ -45,31 +46,7 @@ public static void Make(GameObject planetGO, Sector sector, PropModule.VolcanoIn { InitPrefab(); - var launcherGO = _meteorLauncherPrefab.InstantiateInactive(); - launcherGO.name = !string.IsNullOrEmpty(info.rename) ? info.rename : "MeteorLauncher"; - launcherGO.transform.parent = sector?.transform ?? planetGO.transform; - launcherGO.transform.position = planetGO.transform.TransformPoint(info.position == null ? Vector3.zero : (Vector3)info.position); - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - launcherGO.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) - launcherGO.transform.localPosition = pos; - else - launcherGO.transform.position = planetGO.transform.TransformPoint(pos); - - launcherGO.transform.rotation = Quaternion.FromToRotation(launcherGO.transform.TransformDirection(Vector3.up), pos.normalized).normalized; + var launcherGO = GeneralPropBuilder.MakeFromPrefab(_meteorLauncherPrefab, "MeteorLauncher", planetGO, sector, info); var meteorLauncher = launcherGO.GetComponent(); meteorLauncher._audioSector = sector; diff --git a/NewHorizons/Builder/Props/WarpPadBuilder.cs b/NewHorizons/Builder/Props/WarpPadBuilder.cs new file mode 100644 index 000000000..c4de76793 --- /dev/null +++ b/NewHorizons/Builder/Props/WarpPadBuilder.cs @@ -0,0 +1,147 @@ +using NewHorizons.Builder.Props.TranslatorText; +using NewHorizons.External.Modules; +using NewHorizons.External.Modules.WarpPad; +using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; +using OWML.Utils; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Builder.Props +{ + public static class WarpPadBuilder + { + private static GameObject _detailedReceiverPrefab; + private static GameObject _receiverPrefab; + private static GameObject _transmitterPrefab; + private static GameObject _platformContainerPrefab; + + public static void InitPrefabs() + { + if (_platformContainerPrefab == null) + { + // Put this around the platforms without details + // Trifid is a Nomai ruins genius + _platformContainerPrefab = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_SouthHemisphere/Sector_SouthPole/Sector_Observatory/Interactables_Observatory/Prefab_NOM_RemoteViewer/Structure_NOM_RemoteViewer") + .InstantiateInactive() + .DontDestroyOnLoad(); + _platformContainerPrefab.transform.localScale = new Vector3(0.85f, 3f, 0.85f); + } + + if (_detailedReceiverPrefab == null) + { + var thReceiverLamp = SearchUtilities.Find("TimberHearth_Body/Sector_TH/Sector_NomaiCrater/Geometry_NomaiCrater/OtherComponentsGroup/Structure_NOM_WarpReceiver_TimberHearth_Lamp"); + var thReceiver = SearchUtilities.Find("TimberHearth_Body/Sector_TH/Sector_NomaiCrater/Interactables_NomaiCrater/Prefab_NOM_WarpReceiver"); + + _detailedReceiverPrefab = new GameObject("NomaiWarpReceiver"); + + var detailedReceiver = thReceiver.InstantiateInactive(); + detailedReceiver.transform.parent = _detailedReceiverPrefab.transform; + detailedReceiver.transform.localPosition = Vector3.zero; + detailedReceiver.transform.localRotation = Quaternion.identity; + + var lamp = thReceiverLamp.InstantiateInactive(); + lamp.transform.parent = _detailedReceiverPrefab.transform; + lamp.transform.localPosition = thReceiver.transform.InverseTransformPoint(thReceiverLamp.transform.position); + lamp.transform.localRotation = thReceiver.transform.InverseTransformRotation(thReceiverLamp.transform.rotation); + + _detailedReceiverPrefab.SetActive(false); + lamp.SetActive(true); + detailedReceiver.SetActive(true); + + _detailedReceiverPrefab.DontDestroyOnLoad(); + + GameObject.Destroy(_detailedReceiverPrefab.GetComponentInChildren().gameObject); + } + + if (_receiverPrefab == null) + { + _receiverPrefab = SearchUtilities.Find("SunStation_Body/Sector_SunStation/Sector_WarpModule/Interactables_WarpModule/Prefab_NOM_WarpReceiver") + .InstantiateInactive() + .DontDestroyOnLoad(); + GameObject.Destroy(_receiverPrefab.GetComponentInChildren().gameObject); + + var structure = _platformContainerPrefab.Instantiate(); + structure.transform.parent = _receiverPrefab.transform; + structure.transform.localPosition = new Vector3(0, 0.8945f, 0); + structure.transform.localRotation = Quaternion.identity; + structure.SetActive(true); + } + + if (_transmitterPrefab == null) + { + _transmitterPrefab = SearchUtilities.Find("TowerTwin_Body/Sector_TowerTwin/Sector_Tower_SS/Interactables_Tower_SS/Tower_SS_VisibleFrom_TowerTwin/Prefab_NOM_WarpTransmitter") + .InstantiateInactive() + .DontDestroyOnLoad(); + GameObject.Destroy(_transmitterPrefab.GetComponentInChildren().gameObject); + + var structure = _platformContainerPrefab.Instantiate(); + structure.transform.parent = _transmitterPrefab.transform; + structure.transform.localPosition = new Vector3(0, 0.8945f, 0); + structure.transform.localRotation = Quaternion.identity; + structure.SetActive(true); + } + } + + public static void Make(GameObject planetGO, Sector sector, NomaiWarpReceiverInfo info) + { + var detailInfo = new PropModule.DetailInfo(info); + var receiverObject = DetailBuilder.Make(planetGO, sector, info.detailed ? _detailedReceiverPrefab : _receiverPrefab, detailInfo); + + Logger.Log($"Position is {detailInfo.position} was {info.position}"); + + var receiver = receiverObject.GetComponentInChildren(); + + receiver._frequency = GetFrequency(info.frequency); + + receiver._alignmentTarget = planetGO?.transform; + + receiverObject.SetActive(true); + + if (info.computer != null) + { + CreateComputer(planetGO, sector, info.computer, receiver); + } + } + + public static void Make(GameObject planetGO, Sector sector, NomaiWarpTransmitterInfo info) + { + var transmitterObject = DetailBuilder.Make(planetGO, sector, _transmitterPrefab, new PropModule.DetailInfo(info)); + + var transmitter = transmitterObject.GetComponentInChildren(); + transmitter._frequency = GetFrequency(info.frequency); + + transmitter._alignmentWindow = info.alignmentWindow; + + transmitter._upsideDown = info.flipAlignment; + + transmitter.GetComponent().enabled = true; + + transmitterObject.SetActive(true); + } + + private static void CreateComputer(GameObject planetGO, Sector sector, NomaiWarpComputerLoggerInfo computerInfo, NomaiWarpReceiver receiver) + { + var computerObject = DetailBuilder.Make(planetGO, sector, TranslatorTextBuilder.ComputerPrefab, new PropModule.DetailInfo(computerInfo)); + + var computer = computerObject.GetComponentInChildren(); + computer.SetSector(sector); + + Delay.FireOnNextUpdate(computer.ClearAllEntries); + + var computerLogger = computerObject.AddComponent(); + computerLogger._warpReceiver = receiver; + + computerObject.SetActive(true); + } + + private static NomaiWarpPlatform.Frequency GetFrequency(string frequency) + { + if (!EnumUtils.TryParse(frequency, out var frequencyEnum)) + { + frequencyEnum = EnumUtilities.Create(frequency); + } + return frequencyEnum; + } + } +} diff --git a/NewHorizons/Builder/ShipLog/EntryLocationBuilder.cs b/NewHorizons/Builder/ShipLog/EntryLocationBuilder.cs index e7d86a596..ace39be31 100644 --- a/NewHorizons/Builder/ShipLog/EntryLocationBuilder.cs +++ b/NewHorizons/Builder/ShipLog/EntryLocationBuilder.cs @@ -1,3 +1,4 @@ +using NewHorizons.Builder.Props; using NewHorizons.External.Modules; using OWML.Common; using System.Collections.Generic; @@ -11,28 +12,7 @@ public static class EntryLocationBuilder private static readonly List _locationsToInitialize = new List(); public static void Make(GameObject go, Sector sector, PropModule.EntryLocationInfo info, IModBehaviour mod) { - GameObject entryLocationGameObject = new GameObject(!string.IsNullOrEmpty(info.rename) ? info.rename : ("Entry Location (" + info.id + ")")); - entryLocationGameObject.SetActive(false); - entryLocationGameObject.transform.parent = sector?.transform ?? go.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = go.transform.Find(info.parentPath); - if (newParent != null) - { - entryLocationGameObject.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {go.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) - entryLocationGameObject.transform.localPosition = pos; - else - entryLocationGameObject.transform.position = go.transform.TransformPoint(pos); + GameObject entryLocationGameObject = GeneralPropBuilder.MakeNew("Entry Location (" + info.id + ")", go, sector, info); ShipLogEntryLocation newLocation = entryLocationGameObject.AddComponent(); newLocation._entryID = info.id; diff --git a/NewHorizons/Builder/ShipLog/MapModeBuilder.cs b/NewHorizons/Builder/ShipLog/MapModeBuilder.cs index 0eaf91aab..8d01bf62b 100644 --- a/NewHorizons/Builder/ShipLog/MapModeBuilder.cs +++ b/NewHorizons/Builder/ShipLog/MapModeBuilder.cs @@ -9,6 +9,7 @@ using UnityEngine.UI; using Logger = NewHorizons.Utility.Logger; using NewHorizons.Components.ShipLog; +using NewHorizons.Utility.OWUtilities; namespace NewHorizons.Builder.ShipLog { diff --git a/NewHorizons/Builder/ShipLog/RevealBuilder.cs b/NewHorizons/Builder/ShipLog/RevealBuilder.cs index 87c2e1034..1e2d5a8b2 100644 --- a/NewHorizons/Builder/ShipLog/RevealBuilder.cs +++ b/NewHorizons/Builder/ShipLog/RevealBuilder.cs @@ -1,5 +1,7 @@ +using NewHorizons.Builder.Props; using NewHorizons.Components.Achievement; using NewHorizons.External.Modules; +using NewHorizons.Utility.OWUtilities; using OWML.Common; using UnityEngine; using Logger = NewHorizons.Utility.Logger; @@ -9,7 +11,7 @@ public static class RevealBuilder { public static void Make(GameObject go, Sector sector, VolumesModule.RevealVolumeInfo info, IModBehaviour mod) { - var newRevealGO = MakeGameObject(go, sector, info, mod); + var newRevealGO = GeneralPropBuilder.MakeNew("Reveal Volume (" + info.revealOn + ")", go, sector, info); switch (info.revealOn) { case VolumesModule.RevealVolumeInfo.RevealVolumeType.Enter: @@ -36,37 +38,6 @@ private static SphereShape MakeShape(GameObject go, VolumesModule.RevealVolumeIn return newShape; } - private static GameObject MakeGameObject(GameObject planetGO, Sector sector, VolumesModule.RevealVolumeInfo info, IModBehaviour mod) - { - GameObject revealTriggerVolume = new GameObject("Reveal Volume (" + info.revealOn + ")"); - revealTriggerVolume.SetActive(false); - revealTriggerVolume.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.rename)) - { - revealTriggerVolume.name = info.rename; - } - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - revealTriggerVolume.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) revealTriggerVolume.transform.localPosition = pos; - else revealTriggerVolume.transform.position = planetGO.transform.TransformPoint(pos); - - return revealTriggerVolume; - } - private static void MakeTrigger(GameObject go, Sector sector, VolumesModule.RevealVolumeInfo info, IModBehaviour mod) { var shape = MakeShape(go, info, Shape.CollisionMode.Volume); @@ -122,7 +93,7 @@ private static void MakeTrigger(GameObject go, Sector sector, VolumesModule.Reve private static void MakeObservable(GameObject go, Sector sector, VolumesModule.RevealVolumeInfo info, IModBehaviour mod) { - go.layer = LayerMask.NameToLayer("Interactible"); + go.layer = Layer.Interactible; var sphere = go.AddComponent(); sphere.radius = info.radius; diff --git a/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs b/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs index 0543b0aed..cdba01fa7 100644 --- a/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs +++ b/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs @@ -2,6 +2,7 @@ using NewHorizons.External.Modules; using NewHorizons.Handlers; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using OWML.Utils; using System; using System.Collections.Generic; diff --git a/NewHorizons/Builder/StarSystem/SkyboxBuilder.cs b/NewHorizons/Builder/StarSystem/SkyboxBuilder.cs index 8fb429ea7..c92b6520a 100644 --- a/NewHorizons/Builder/StarSystem/SkyboxBuilder.cs +++ b/NewHorizons/Builder/StarSystem/SkyboxBuilder.cs @@ -1,14 +1,15 @@ using NewHorizons.External.Configs; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; using OWML.Common; -using System; using UnityEngine; using Logger = NewHorizons.Utility.Logger; + namespace NewHorizons.Builder.StarSystem { public static class SkyboxBuilder { - private static readonly int _skyboxLayer = LayerMask.NameToLayer("Skybox"); private static readonly Shader _unlitShader = Shader.Find("Unlit/Texture"); public static void Make(StarSystemConfig.SkyboxModule module, IModBehaviour mod) @@ -32,7 +33,7 @@ public static GameObject BuildSkySphere(StarSystemConfig.SkyboxModule module, IM var skySphere = new GameObject("Sky Sphere"); skySphere.transform.SetParent(skybox.transform, false); - skySphere.layer = _skyboxLayer; + skySphere.layer = Layer.Skybox; skySphere.transform.localScale = Vector3.one * 5f; BuildSkySphereFace(skySphere, "Right", Quaternion.Euler(0f, 90f, 0f), mesh, rightTex); @@ -55,7 +56,7 @@ public static GameObject BuildSkySphereFace(GameObject skySphere, string name, Q var go = new GameObject(name) { - layer = _skyboxLayer + layer = Layer.Skybox }; var mf = go.AddComponent(); diff --git a/NewHorizons/Builder/Volumes/AudioVolumeBuilder.cs b/NewHorizons/Builder/Volumes/AudioVolumeBuilder.cs index 8711ddf78..3e2b723be 100644 --- a/NewHorizons/Builder/Volumes/AudioVolumeBuilder.cs +++ b/NewHorizons/Builder/Volumes/AudioVolumeBuilder.cs @@ -1,5 +1,7 @@ +using NewHorizons.Builder.Props; using NewHorizons.External.Modules; using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; using OWML.Common; using OWML.Utils; using System; @@ -16,33 +18,8 @@ public static class AudioVolumeBuilder { public static AudioVolume Make(GameObject planetGO, Sector sector, VolumesModule.AudioVolumeInfo info, IModBehaviour mod) { - var go = new GameObject("AudioVolume"); - go.SetActive(false); - - go.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.rename)) - { - go.name = info.rename; - } - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - go.transform.parent = newParent; - } - else - { - Logger.LogWarning($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) go.transform.localPosition = pos; - else go.transform.position = planetGO.transform.TransformPoint(pos); - go.layer = LayerMask.NameToLayer("AdvancedEffectVolume"); + var go = GeneralPropBuilder.MakeNew("AudioVolume", planetGO, sector, info); + go.layer = Layer.AdvancedEffectVolume; var audioSource = go.AddComponent(); diff --git a/NewHorizons/Builder/Volumes/CreditsVolumeBuilder.cs b/NewHorizons/Builder/Volumes/CreditsVolumeBuilder.cs index c34745c1b..ef8856e51 100644 --- a/NewHorizons/Builder/Volumes/CreditsVolumeBuilder.cs +++ b/NewHorizons/Builder/Volumes/CreditsVolumeBuilder.cs @@ -1,5 +1,6 @@ using NewHorizons.Components.Volumes; using NewHorizons.External.Modules; +using OWML.Utils; using UnityEngine; namespace NewHorizons.Builder.Volumes @@ -11,6 +12,8 @@ public static LoadCreditsVolume Make(GameObject planetGO, Sector sector, Volumes var volume = VolumeBuilder.Make(planetGO, sector, info); volume.creditsType = info.creditsType; + volume.gameOverText = info.gameOverText; + volume.deathType = EnumUtils.Parse(info.deathType.ToString(), DeathType.Default); return volume; } diff --git a/NewHorizons/Builder/Volumes/HazardVolumeBuilder.cs b/NewHorizons/Builder/Volumes/HazardVolumeBuilder.cs index 23a4f1bba..5c64bb0a3 100644 --- a/NewHorizons/Builder/Volumes/HazardVolumeBuilder.cs +++ b/NewHorizons/Builder/Volumes/HazardVolumeBuilder.cs @@ -1,4 +1,6 @@ +using NewHorizons.Builder.Props; using NewHorizons.External.Modules; +using NewHorizons.Utility.OWUtilities; using OWML.Common; using OWML.Utils; using System; @@ -13,33 +15,8 @@ public static class HazardVolumeBuilder { public static HazardVolume Make(GameObject planetGO, Sector sector, OWRigidbody owrb, VolumesModule.HazardVolumeInfo info, IModBehaviour mod) { - var go = new GameObject("HazardVolume"); - go.SetActive(false); - - go.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.rename)) - { - go.name = info.rename; - } - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - go.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) go.transform.localPosition = pos; - else go.transform.position = planetGO.transform.TransformPoint(pos); - go.layer = LayerMask.NameToLayer("BasicEffectVolume"); + var go = GeneralPropBuilder.MakeNew("HazardVolume", planetGO, sector, info); + go.layer = Layer.BasicEffectVolume; var shape = go.AddComponent(); shape.radius = info.radius; @@ -74,7 +51,7 @@ public static HazardVolume Make(GameObject planetGO, Sector sector, OWRigidbody var detectorGO = new GameObject("ConstantFluidDetector"); detectorGO.transform.parent = go.transform; detectorGO.transform.localPosition = Vector3.zero; - detectorGO.layer = LayerMask.NameToLayer("BasicDetector"); + detectorGO.layer = Layer.BasicDetector; var detector = detectorGO.AddComponent(); detector._onlyDetectableFluid = water; detector._buoyancy.boundingRadius = 1; diff --git a/NewHorizons/Builder/Volumes/NotificationVolumeBuilder.cs b/NewHorizons/Builder/Volumes/NotificationVolumeBuilder.cs index 1e3f07b86..c02f29671 100644 --- a/NewHorizons/Builder/Volumes/NotificationVolumeBuilder.cs +++ b/NewHorizons/Builder/Volumes/NotificationVolumeBuilder.cs @@ -1,5 +1,7 @@ +using NewHorizons.Builder.Props; using NewHorizons.External.Modules; using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; using OWML.Common; using System; using System.Collections.Generic; @@ -16,33 +18,8 @@ public static class NotificationVolumeBuilder { public static NHNotificationVolume Make(GameObject planetGO, Sector sector, VolumesModule.NotificationVolumeInfo info, IModBehaviour mod) { - var go = new GameObject("NotificationVolume"); - go.SetActive(false); - - go.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.rename)) - { - go.name = info.rename; - } - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - go.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) go.transform.localPosition = pos; - else go.transform.position = planetGO.transform.TransformPoint(pos); - go.layer = LayerMask.NameToLayer("BasicEffectVolume"); + var go = GeneralPropBuilder.MakeNew("NotificationVolume", planetGO, sector, info); + go.layer = Layer.BasicEffectVolume; var shape = go.AddComponent(); shape.radius = info.radius; diff --git a/NewHorizons/Builder/Volumes/Rulesets/PlayerImpactRulesetBuilder.cs b/NewHorizons/Builder/Volumes/Rulesets/PlayerImpactRulesetBuilder.cs index 9ef330de7..b914ba3bd 100644 --- a/NewHorizons/Builder/Volumes/Rulesets/PlayerImpactRulesetBuilder.cs +++ b/NewHorizons/Builder/Volumes/Rulesets/PlayerImpactRulesetBuilder.cs @@ -1,7 +1,7 @@ using NewHorizons.External.Modules; using UnityEngine; -namespace NewHorizons.Builder.Volumes +namespace NewHorizons.Builder.Volumes.Rulesets { public static class PlayerImpactRulesetBuilder { diff --git a/NewHorizons/Builder/Volumes/Rulesets/ProbeRulesetBuilder.cs b/NewHorizons/Builder/Volumes/Rulesets/ProbeRulesetBuilder.cs index b8293d944..ae9a70ec4 100644 --- a/NewHorizons/Builder/Volumes/Rulesets/ProbeRulesetBuilder.cs +++ b/NewHorizons/Builder/Volumes/Rulesets/ProbeRulesetBuilder.cs @@ -1,7 +1,7 @@ using NewHorizons.External.Modules; using UnityEngine; -namespace NewHorizons.Builder.Volumes +namespace NewHorizons.Builder.Volumes.Rulesets { public static class ProbeRulesetBuilder { diff --git a/NewHorizons/Builder/Volumes/Rulesets/ThrustRulesetBuilder.cs b/NewHorizons/Builder/Volumes/Rulesets/ThrustRulesetBuilder.cs index 8541f516b..a2ce52d68 100644 --- a/NewHorizons/Builder/Volumes/Rulesets/ThrustRulesetBuilder.cs +++ b/NewHorizons/Builder/Volumes/Rulesets/ThrustRulesetBuilder.cs @@ -1,7 +1,7 @@ using NewHorizons.External.Modules; using UnityEngine; -namespace NewHorizons.Builder.Volumes +namespace NewHorizons.Builder.Volumes.Rulesets { public static class ThrustRulesetBuilder { diff --git a/NewHorizons/Builder/Volumes/VanishVolumeBuilder.cs b/NewHorizons/Builder/Volumes/VanishVolumeBuilder.cs index 2048159fa..fbb5c8c07 100644 --- a/NewHorizons/Builder/Volumes/VanishVolumeBuilder.cs +++ b/NewHorizons/Builder/Volumes/VanishVolumeBuilder.cs @@ -1,5 +1,7 @@ +using NewHorizons.Builder.Props; using NewHorizons.Components; using NewHorizons.External.Modules; +using NewHorizons.Utility.OWUtilities; using UnityEngine; using Logger = NewHorizons.Utility.Logger; @@ -9,33 +11,8 @@ public static class VanishVolumeBuilder { public static TVolume Make(GameObject planetGO, Sector sector, VolumesModule.VanishVolumeInfo info) where TVolume : VanishVolume { - var go = new GameObject(typeof(TVolume).Name); - go.SetActive(false); - - go.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.rename)) - { - go.name = info.rename; - } - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - go.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) go.transform.localPosition = pos; - else go.transform.position = planetGO.transform.TransformPoint(pos); - go.layer = LayerMask.NameToLayer("BasicEffectVolume"); + var go = GeneralPropBuilder.MakeNew(typeof(TVolume).Name, planetGO, sector, info); + go.layer = Layer.BasicEffectVolume; var collider = go.AddComponent(); collider.isTrigger = true; diff --git a/NewHorizons/Builder/Volumes/VisorEffects/VisorFrostEffectVolumeBuilder.cs b/NewHorizons/Builder/Volumes/VisorEffects/VisorFrostEffectVolumeBuilder.cs index 139e09f90..b96dadfde 100644 --- a/NewHorizons/Builder/Volumes/VisorEffects/VisorFrostEffectVolumeBuilder.cs +++ b/NewHorizons/Builder/Volumes/VisorEffects/VisorFrostEffectVolumeBuilder.cs @@ -1,7 +1,7 @@ using NewHorizons.External.Modules; using UnityEngine; -namespace NewHorizons.Builder.Volumes +namespace NewHorizons.Builder.Volumes.VisorEffects { public static class VisorFrostEffectVolumeBuilder { diff --git a/NewHorizons/Builder/Volumes/VisorEffects/VisorRainEffectVolumeBuilder.cs b/NewHorizons/Builder/Volumes/VisorEffects/VisorRainEffectVolumeBuilder.cs index bf268c8ec..a0de16da5 100644 --- a/NewHorizons/Builder/Volumes/VisorEffects/VisorRainEffectVolumeBuilder.cs +++ b/NewHorizons/Builder/Volumes/VisorEffects/VisorRainEffectVolumeBuilder.cs @@ -1,7 +1,7 @@ using NewHorizons.External.Modules; using UnityEngine; -namespace NewHorizons.Builder.Volumes +namespace NewHorizons.Builder.Volumes.VisorEffects { public static class VisorRainEffectVolumeBuilder { diff --git a/NewHorizons/Builder/Volumes/VolumeBuilder.cs b/NewHorizons/Builder/Volumes/VolumeBuilder.cs index cc35c636c..0a50d518e 100644 --- a/NewHorizons/Builder/Volumes/VolumeBuilder.cs +++ b/NewHorizons/Builder/Volumes/VolumeBuilder.cs @@ -1,5 +1,7 @@ +using NewHorizons.Builder.Props; using NewHorizons.Components; using NewHorizons.External.Modules; +using NewHorizons.Utility.OWUtilities; using UnityEngine; using Logger = NewHorizons.Utility.Logger; @@ -9,33 +11,8 @@ public static class VolumeBuilder { public static TVolume Make(GameObject planetGO, Sector sector, VolumesModule.VolumeInfo info) where TVolume : MonoBehaviour //Could be BaseVolume but I need to create vanilla volumes too. { - var go = new GameObject(typeof(TVolume).Name); - go.SetActive(false); - - go.transform.parent = sector?.transform ?? planetGO.transform; - - if (!string.IsNullOrEmpty(info.rename)) - { - go.name = info.rename; - } - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - go.transform.parent = newParent; - } - else - { - Logger.LogError($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - - var pos = (Vector3)(info.position ?? Vector3.zero); - if (info.isRelativeToParent) go.transform.localPosition = pos; - else go.transform.position = planetGO.transform.TransformPoint(pos); - go.layer = LayerMask.NameToLayer("BasicEffectVolume"); + var go = GeneralPropBuilder.MakeNew(typeof(TVolume).Name, planetGO, sector, info); + go.layer = Layer.BasicEffectVolume; var shape = go.AddComponent(); shape.radius = info.radius; diff --git a/NewHorizons/Builder/Volumes/VolumesBuildManager.cs b/NewHorizons/Builder/Volumes/VolumesBuildManager.cs index cd1f474ad..9c4357b29 100644 --- a/NewHorizons/Builder/Volumes/VolumesBuildManager.cs +++ b/NewHorizons/Builder/Volumes/VolumesBuildManager.cs @@ -1,6 +1,8 @@ using NewHorizons.Builder.Body; using NewHorizons.Builder.ShipLog; using NewHorizons.Builder.Volumes; +using NewHorizons.Builder.Volumes.Rulesets; +using NewHorizons.Builder.Volumes.VisorEffects; using NewHorizons.Components.Volumes; using NewHorizons.External.Configs; using OWML.Common; diff --git a/NewHorizons/Components/Achievement/AchievementObserveTrigger.cs b/NewHorizons/Components/Achievement/AchievementObserveTrigger.cs index 1a6acf5fe..88392cb0a 100644 --- a/NewHorizons/Components/Achievement/AchievementObserveTrigger.cs +++ b/NewHorizons/Components/Achievement/AchievementObserveTrigger.cs @@ -1,4 +1,5 @@ using NewHorizons.OtherMods.AchievementsPlus; +using NewHorizons.Utility.OWUtilities; using System; using System.Collections.Generic; using System.Linq; @@ -20,7 +21,7 @@ public class AchievementObserveTrigger : MonoBehaviour, IObservable private void Reset() { - gameObject.layer = LayerMask.NameToLayer("Interactible"); + gameObject.layer = Layer.Interactible; } private void Awake() diff --git a/NewHorizons/Components/AddPhysics.cs b/NewHorizons/Components/AddPhysics.cs index 14785f9f9..683b5a3cd 100644 --- a/NewHorizons/Components/AddPhysics.cs +++ b/NewHorizons/Components/AddPhysics.cs @@ -1,4 +1,5 @@ -using System.Collections; +using NewHorizons.Utility.OWUtilities; +using System.Collections; using UnityEngine; namespace NewHorizons.Components; @@ -38,7 +39,7 @@ private IEnumerator Start() var owRigidbody = bodyGo.AddComponent(); owRigidbody._simulateInSector = Sector; - bodyGo.layer = LayerMask.NameToLayer("PhysicalDetector"); + bodyGo.layer = Layer.PhysicalDetector; bodyGo.tag = "DynamicPropDetector"; // this collider is not included in groups. oh well bodyGo.AddComponent().radius = Radius; @@ -66,6 +67,13 @@ private IEnumerator Start() owRigidbody.SetMass(Mass); owRigidbody.SetVelocity(parentBody.GetPointVelocity(transform.position)); + // #536 - Physics objects in bramble dimensions not disabled on load + // sectors wait 3 frames and then call OnSectorOccupantsUpdated + // however we wait .1 real seconds which is longer + // so we have to manually call this + if (owRigidbody._simulateInSector != null) + owRigidbody.OnSectorOccupantsUpdated(); + Destroy(this); } diff --git a/NewHorizons/Components/BrambleSectorController.cs b/NewHorizons/Components/BrambleSectorController.cs index 9d0762eb4..99a7d62cf 100644 --- a/NewHorizons/Components/BrambleSectorController.cs +++ b/NewHorizons/Components/BrambleSectorController.cs @@ -77,6 +77,8 @@ private void EnableRenderers() { light.enabled = true; } + + _renderersShown = true; } private void DisableRenderers() @@ -100,6 +102,8 @@ private void DisableRenderers() { light.enabled = false; } + + _renderersShown = false; } } } diff --git a/NewHorizons/Components/EyeAstroObject.cs b/NewHorizons/Components/EyeAstroObject.cs index 6b78ddb4e..799617bc3 100644 --- a/NewHorizons/Components/EyeAstroObject.cs +++ b/NewHorizons/Components/EyeAstroObject.cs @@ -1,6 +1,4 @@ -using NewHorizons.Utility; - -namespace NewHorizons.Components.Orbital +namespace NewHorizons.Components { public class EyeAstroObject : AstroObject { diff --git a/NewHorizons/Components/NHProxy.cs b/NewHorizons/Components/NHProxy.cs index 92a81e0ec..6df1383a2 100644 --- a/NewHorizons/Components/NHProxy.cs +++ b/NewHorizons/Components/NHProxy.cs @@ -1,6 +1,6 @@ using NewHorizons.Components.SizeControllers; using NewHorizons.Handlers; -using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; using System.Collections.Generic; using System.Linq; using UnityEngine; diff --git a/NewHorizons/Components/Quantum/QuantumPlanet.cs b/NewHorizons/Components/Quantum/QuantumPlanet.cs index 9b551cd7e..89eebdbbe 100644 --- a/NewHorizons/Components/Quantum/QuantumPlanet.cs +++ b/NewHorizons/Components/Quantum/QuantumPlanet.cs @@ -3,7 +3,7 @@ using NewHorizons.Components.Orbital; using NewHorizons.External.Modules; using NewHorizons.Handlers; -using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; using System.Collections.Generic; using System.Linq; using UnityEngine; diff --git a/NewHorizons/Components/RingOpacityController.cs b/NewHorizons/Components/RingOpacityController.cs index df707a33d..0f762506e 100644 --- a/NewHorizons/Components/RingOpacityController.cs +++ b/NewHorizons/Components/RingOpacityController.cs @@ -1,6 +1,5 @@ using NewHorizons.Components.Volumes; using NewHorizons.External.Modules.VariableSize; -using NewHorizons.Utility; using UnityEngine; namespace NewHorizons.Components diff --git a/NewHorizons/Components/ShipLog/ShipLogStarChartMode.cs b/NewHorizons/Components/ShipLog/ShipLogStarChartMode.cs index 03510628e..8bc657100 100644 --- a/NewHorizons/Components/ShipLog/ShipLogStarChartMode.cs +++ b/NewHorizons/Components/ShipLog/ShipLogStarChartMode.cs @@ -1,5 +1,6 @@ using NewHorizons.Handlers; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using System; using System.Collections.Generic; using System.IO; @@ -61,7 +62,7 @@ public override void Initialize(ScreenPromptList centerPromptList, ScreenPromptL var flag = false; if (starSystem.Equals("SolarSystem")) flag = true; else if (starSystem.Equals("EyeOfTheUniverse")) flag = false; - else if (config.Spawn?.shipSpawnPoint != null) flag = true; + else if (config.Spawn?.shipSpawn != null) flag = true; if (!StarChartHandler.HasUnlockedSystem(starSystem)) continue; diff --git a/NewHorizons/Components/ShipWarpController.cs b/NewHorizons/Components/ShipWarpController.cs index 3ff96a3ae..8bfa4bee3 100644 --- a/NewHorizons/Components/ShipWarpController.cs +++ b/NewHorizons/Components/ShipWarpController.cs @@ -1,5 +1,6 @@ using NewHorizons.Builder.General; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using UnityEngine; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Components diff --git a/NewHorizons/Components/FunnelController.cs b/NewHorizons/Components/SizeControllers/FunnelController.cs similarity index 71% rename from NewHorizons/Components/FunnelController.cs rename to NewHorizons/Components/SizeControllers/FunnelController.cs index c0d39468f..a4867408e 100644 --- a/NewHorizons/Components/FunnelController.cs +++ b/NewHorizons/Components/SizeControllers/FunnelController.cs @@ -1,18 +1,19 @@ -using UnityEngine; -namespace NewHorizons.Components +using UnityEngine; +namespace NewHorizons.Components.SizeControllers { - public class FunnelController : MonoBehaviour + public class FunnelController : SizeController { - public AnimationCurve scaleCurve; public Transform target; public Transform anchor; - private void Update() + public override void FixedUpdate() { // Temporary solution that i will never get rid of transform.position = anchor.position; - float num = scaleCurve?.Evaluate(TimeLoop.GetMinutesElapsed()) ?? 1f; + UpdateScale(); + + float num = CurrentScale; var dist = (transform.position - target.position).magnitude; transform.localScale = new Vector3(num, num, dist / 500f); diff --git a/NewHorizons/Components/SizeControllers/SingularitySizeController.cs b/NewHorizons/Components/SizeControllers/SingularitySizeController.cs index 4633324ad..2caa779a5 100644 --- a/NewHorizons/Components/SizeControllers/SingularitySizeController.cs +++ b/NewHorizons/Components/SizeControllers/SingularitySizeController.cs @@ -1,9 +1,6 @@ using NewHorizons.Builder.Body; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using UnityEngine; namespace NewHorizons.Components.SizeControllers @@ -18,7 +15,7 @@ public class SingularitySizeController : SizeController public WhiteHoleFluidVolume fluidVolume; public WhiteHoleVolume volume; - protected new void FixedUpdate() + public override void FixedUpdate() { base.FixedUpdate(); @@ -56,5 +53,63 @@ protected new void FixedUpdate() volume._radius = CurrentScale * innerScale; } } + + protected override void Vanish() + { + if (audioSource != null) + { + audioSource.gameObject.SetActive(false); + audioSource.Stop(); + } + + if (oneShotAudioSource != null) + { + oneShotAudioSource.gameObject.SetActive(false); + } + + if (sphereCollider != null) + { + sphereCollider.gameObject.SetActive(false); + } + + if (fluidVolume != null) + { + fluidVolume.gameObject.SetActive(false); + } + + if (volume != null) + { + volume.gameObject.SetActive(false); + } + } + + protected override void Appear() + { + if (audioSource != null) + { + audioSource.gameObject.SetActive(true); + Delay.FireOnNextUpdate(audioSource.Play); + } + + if (oneShotAudioSource != null) + { + oneShotAudioSource.gameObject.SetActive(true); + } + + if (sphereCollider != null) + { + sphereCollider.gameObject.SetActive(true); + } + + if (fluidVolume != null) + { + fluidVolume.gameObject.SetActive(true); + } + + if (volume != null) + { + volume.gameObject.SetActive(true); + } + } } } diff --git a/NewHorizons/Components/SizeControllers/SizeController.cs b/NewHorizons/Components/SizeControllers/SizeController.cs index 334f5a84d..4e645f56f 100644 --- a/NewHorizons/Components/SizeControllers/SizeController.cs +++ b/NewHorizons/Components/SizeControllers/SizeController.cs @@ -1,25 +1,72 @@ +using NewHorizons.External.Modules.VariableSize; using NewHorizons.Utility; using UnityEngine; + namespace NewHorizons.Components.SizeControllers { public class SizeController : MonoBehaviour { - public AnimationCurve scaleCurve { get; protected set; } + public AnimationCurve scaleCurve; public float CurrentScale { get; protected set; } public float size = 1f; - protected void FixedUpdate() + public void Awake() + { + UpdateScale(); + + if (CurrentScale == 0f) + { + Vanish(); + } + } + + protected void UpdateScale() { if(scaleCurve != null) { + var prevScale = CurrentScale; CurrentScale = scaleCurve.Evaluate(TimeLoop.GetMinutesElapsed()) * size; + + // #514 setting something's scale value to 0 should disable it + if (prevScale != CurrentScale) + { + if (CurrentScale == 0f) + { + Vanish(); + } + else if (prevScale == 0f) + { + Appear(); + } + } } else { CurrentScale = size; } + } + + protected virtual void Vanish() + { + foreach (var child in gameObject.GetAllChildren()) + { + child.SetActive(false); + } + } + + protected virtual void Appear() + { + foreach (var child in gameObject.GetAllChildren()) + { + child.SetActive(true); + } + } + + public virtual void FixedUpdate() + { + UpdateScale(); - base.transform.localScale = Vector3.one * CurrentScale; + transform.localScale = Vector3.one * CurrentScale; } public void SetScaleCurve(TimeValuePair[] curve) diff --git a/NewHorizons/Components/SizeControllers/StarEvolutionController.cs b/NewHorizons/Components/SizeControllers/StarEvolutionController.cs index 6c84317ef..c0d6508e1 100644 --- a/NewHorizons/Components/SizeControllers/StarEvolutionController.cs +++ b/NewHorizons/Components/SizeControllers/StarEvolutionController.cs @@ -4,6 +4,7 @@ using NewHorizons.External.Modules.VariableSize; using NewHorizons.Handlers; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using System; using System.Linq; using UnityEngine; diff --git a/NewHorizons/Components/Volumes/LoadCreditsVolume.cs b/NewHorizons/Components/Volumes/LoadCreditsVolume.cs index 119908406..dd2d83eeb 100644 --- a/NewHorizons/Components/Volumes/LoadCreditsVolume.cs +++ b/NewHorizons/Components/Volumes/LoadCreditsVolume.cs @@ -1,5 +1,8 @@ using NewHorizons.External.Modules; +using NewHorizons.Handlers; +using System.Collections; using UnityEngine; +using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Components.Volumes { @@ -7,29 +10,76 @@ internal class LoadCreditsVolume : BaseVolume { public VolumesModule.LoadCreditsVolumeInfo.CreditsType creditsType = VolumesModule.LoadCreditsVolumeInfo.CreditsType.Fast; + public string gameOverText; + public DeathType deathType = DeathType.Default; + + private GameOverController _gameOverController; + private PlayerCameraEffectController _playerCameraEffectController; + + public void Start() + { + _gameOverController = GameObject.FindObjectOfType(); + _playerCameraEffectController = GameObject.FindObjectOfType(); + } + public override void OnTriggerVolumeEntry(GameObject hitObj) { - if (hitObj.CompareTag("PlayerDetector")) + if (hitObj.CompareTag("PlayerDetector") && enabled) + { + // Have to run it off the mod behaviour since the game over controller disables everything + Main.Instance.StartCoroutine(GameOver()); + } + } + + private IEnumerator GameOver() + { + OWInput.ChangeInputMode(InputMode.None); + ReticleController.Hide(); + Locator.GetPromptManager().SetPromptsVisible(false); + Locator.GetPauseCommandListener().AddPauseCommandLock(); + + // The PlayerCameraEffectController is what actually kills us, so convince it we're already dead + Locator.GetDeathManager()._isDead = true; + + _playerCameraEffectController.OnPlayerDeath(deathType); + + yield return new WaitForSeconds(_playerCameraEffectController._deathFadeLength); + + if (!string.IsNullOrEmpty(gameOverText) && _gameOverController != null) { - switch(creditsType) - { - case VolumesModule.LoadCreditsVolumeInfo.CreditsType.Fast: - LoadManager.LoadScene(OWScene.Credits_Fast, LoadManager.FadeType.ToBlack); - break; - case VolumesModule.LoadCreditsVolumeInfo.CreditsType.Final: - LoadManager.LoadScene(OWScene.Credits_Final, LoadManager.FadeType.ToBlack); - break; - case VolumesModule.LoadCreditsVolumeInfo.CreditsType.Kazoo: - TimelineObliterationController.s_hasRealityEnded = true; - LoadManager.LoadScene(OWScene.Credits_Fast, LoadManager.FadeType.ToBlack); - break; - } + _gameOverController._deathText.text = TranslationHandler.GetTranslation(gameOverText, TranslationHandler.TextType.UI); + _gameOverController.SetupGameOverScreen(5f); + + // We set this to true to stop it from loading the credits scene, so we can do it ourselves + _gameOverController._loading = true; + + yield return new WaitUntil(ReadytoLoadCreditsScene); } + + LoadCreditsScene(); } - public override void OnTriggerVolumeExit(GameObject hitObj) + private bool ReadytoLoadCreditsScene() => _gameOverController._fadedOutText && _gameOverController._textAnimator.IsComplete(); + + public override void OnTriggerVolumeExit(GameObject hitObj) { } + + private void LoadCreditsScene() { + Logger.LogVerbose($"Load credits {creditsType}"); + switch (creditsType) + { + case VolumesModule.LoadCreditsVolumeInfo.CreditsType.Fast: + LoadManager.LoadScene(OWScene.Credits_Fast, LoadManager.FadeType.ToBlack); + break; + case VolumesModule.LoadCreditsVolumeInfo.CreditsType.Final: + LoadManager.LoadScene(OWScene.Credits_Final, LoadManager.FadeType.ToBlack); + break; + case VolumesModule.LoadCreditsVolumeInfo.CreditsType.Kazoo: + TimelineObliterationController.s_hasRealityEnded = true; + LoadManager.LoadScene(OWScene.Credits_Fast, LoadManager.FadeType.ToBlack); + break; + } } } } diff --git a/NewHorizons/External/Configs/PlanetConfig.cs b/NewHorizons/External/Configs/PlanetConfig.cs index 20ca31da0..d5cd663df 100644 --- a/NewHorizons/External/Configs/PlanetConfig.cs +++ b/NewHorizons/External/Configs/PlanetConfig.cs @@ -1,3 +1,4 @@ +using Epic.OnlineServices.Presence; using NewHorizons.External.Modules; using NewHorizons.External.Modules.VariableSize; using Newtonsoft.Json; @@ -465,6 +466,102 @@ public void Migrate() { ShockEffect = new ShockEffectModule() { hasSupernovaShockEffect = true }; } + + // Spawn points reorganized to use GeneralPointPropInfo + if (Spawn != null && Spawn.playerSpawn == null && Spawn.playerSpawnPoint != null) + { + Spawn.playerSpawn = new SpawnModule.PlayerSpawnPoint() + { + position = Spawn.playerSpawnPoint, + rotation = Spawn.playerSpawnRotation, + startWithSuit = Spawn.startWithSuit, + }; + } + if (Spawn != null && Spawn.shipSpawn == null && Spawn.shipSpawnPoint != null) + { + Spawn.shipSpawn = new SpawnModule.ShipSpawnPoint() + { + position = Spawn.shipSpawnPoint, + rotation = Spawn.shipSpawnRotation, + }; + } + + // Remote dialogue trigger reorganized to use GeneralPointPropInfo + if (Props?.dialogue != null) + { + foreach (var dialogue in Props.dialogue) + { + if (dialogue.remoteTrigger == null && (dialogue.remoteTriggerPosition != null || dialogue.remoteTriggerRadius != 0)) + { + dialogue.remoteTrigger = new PropModule.DialogueInfo.RemoteTriggerInfo + { + position = dialogue.remoteTriggerPosition, + radius = dialogue.remoteTriggerRadius, + prereqCondition = dialogue.remoteTriggerPrereqCondition, + }; + } + } + } + + // alignRadial added to all props with rotation; default behavior varies + if (Spawn?.playerSpawn != null && Spawn.playerSpawn.rotation == null && !Spawn.playerSpawn.alignRadial.HasValue) + { + Spawn.playerSpawn.alignRadial = true; + } + if (Spawn?.shipSpawn != null && Spawn.shipSpawn.rotation == null && !Spawn.shipSpawn.alignRadial.HasValue) + { + Spawn.shipSpawn.alignRadial = true; + } + if (Props?.details != null) + { + foreach (var detail in Props.details) + { + if (!detail.alignRadial.HasValue) + { + detail.alignRadial = detail.alignToNormal; + } + } + } + if (Props?.proxyDetails != null) + { + foreach (var detail in Props.proxyDetails) + { + if (!detail.alignRadial.HasValue) + { + detail.alignRadial = detail.alignToNormal; + } + } + } + if (Props?.geysers != null) + { + foreach (var geyser in Props.geysers) + { + if (!geyser.alignRadial.HasValue && geyser.rotation == null) + { + geyser.alignRadial = true; + } + } + } + if (Props?.tornados != null) + { + foreach (var tornado in Props.tornados) + { + if (!tornado.alignRadial.HasValue && tornado.rotation == null) + { + tornado.alignRadial = true; + } + } + } + if (Props?.volcanoes != null) + { + foreach (var volcano in Props.volcanoes) + { + if (!volcano.alignRadial.HasValue && volcano.rotation == null) + { + volcano.alignRadial = true; + } + } + } } } } \ No newline at end of file diff --git a/NewHorizons/External/Configs/StarSystemConfig.cs b/NewHorizons/External/Configs/StarSystemConfig.cs index 5b4c8a231..3e3ccf1c2 100644 --- a/NewHorizons/External/Configs/StarSystemConfig.cs +++ b/NewHorizons/External/Configs/StarSystemConfig.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; +using NewHorizons.External.Modules; using NewHorizons.Utility; using Newtonsoft.Json; using static NewHorizons.External.Modules.ShipLogModule; @@ -84,16 +85,16 @@ public class StarSystemConfig [Obsolete("coords is deprecated, please use Vessel.coords instead")] public NomaiCoordinates coords; - [Obsolete("vesselPosition is deprecated, please use Vessel.vesselPosition instead")] + [Obsolete("vesselPosition is deprecated, please use Vessel.vesselSpawn.position instead")] public MVector3 vesselPosition; - [Obsolete("vesselRotation is deprecated, please use Vessel.vesselRotation instead")] + [Obsolete("vesselRotation is deprecated, please use Vessel.vesselSpawn.rotation instead")] public MVector3 vesselRotation; - [Obsolete("warpExitPosition is deprecated, please use Vessel.warpExitPosition instead")] + [Obsolete("warpExitPosition is deprecated, please use Vessel.warpExit.position instead")] public MVector3 warpExitPosition; - [Obsolete("warpExitRotation is deprecated, please use Vessel.warpExitRotation instead")] + [Obsolete("warpExitRotation is deprecated, please use Vessel.warpExit.rotation instead")] public MVector3 warpExitRotation; /// @@ -185,29 +186,58 @@ public class VesselModule public NomaiCoordinates coords; /// - /// The position in the solar system the vessel will warp to. + /// A ship log fact which will make a prompt appear showing the coordinates when you're in the Vessel. /// - public MVector3 vesselPosition; + public string promptFact; /// - /// Euler angles by which the vessel will be oriented. + /// Whether the vessel should spawn in this system even if it wasn't used to warp to it. This will automatically power on the vessel. /// - public MVector3 vesselRotation; + public bool alwaysPresent; /// - /// The relative position to the vessel that you will be teleported to when you exit the vessel through the black hole. + /// Whether to always spawn the player on the vessel, even if it wasn't used to warp to the system. /// - public MVector3 warpExitPosition; + public bool spawnOnVessel; /// - /// Euler angles by which the warp exit will be oriented. + /// Whether the vessel should have physics enabled. Defaults to false if parentBody is set, and true otherwise. /// - public MVector3 warpExitRotation; + public bool? hasPhysics; /// - /// A ship log fact which will make a prompt appear showing the coordinates when you're in the Vessel. + /// Whether the vessel should have a zero-gravity volume around it. Defaults to false if parentBody is set, and true otherwise. /// - public string promptFact; + public bool? hasZeroGravityVolume; + + /// + /// The location that the vessel will warp to. + /// + public VesselInfo vesselSpawn; + + /// + /// The location that you will be teleported to when you exit the vessel through the black hole. + /// + public WarpExitInfo warpExit; + + [Obsolete("vesselPosition is deprecated, use vesselSpawn.position instead")] public MVector3 vesselPosition; + [Obsolete("vesselRotation is deprecated, use vesselSpawn.rotation instead")] public MVector3 vesselRotation; + [Obsolete("warpExitPosition is deprecated, use vesselSpawn.position instead")] public MVector3 warpExitPosition; + [Obsolete("warpExitRotation is deprecated, use vesselSpawn.rotation instead")] public MVector3 warpExitRotation; + + [JsonObject] + public class VesselInfo : GeneralSolarSystemPropInfo + { + } + + [JsonObject] + public class WarpExitInfo : GeneralSolarSystemPropInfo + { + /// + /// If set, keeps the warp exit attached to the vessel. Overrides `parentPath`. + /// + public bool attachToVessel; + } } /// @@ -245,7 +275,17 @@ public void Merge(StarSystemConfig otherConfig) respawnHere = respawnHere || otherConfig.respawnHere; startHere = startHere || otherConfig.startHere; - Vessel = Vessel == null ? otherConfig.Vessel : Vessel; + if (Vessel != null && otherConfig.Vessel != null) + { + Vessel.spawnOnVessel = Vessel.spawnOnVessel || otherConfig.Vessel.spawnOnVessel; + Vessel.alwaysPresent = Vessel.alwaysPresent || otherConfig.Vessel.alwaysPresent; + Vessel.hasPhysics = Vessel.hasPhysics ?? otherConfig.Vessel.hasPhysics; + Vessel.hasZeroGravityVolume = Vessel.hasZeroGravityVolume ?? otherConfig.Vessel.hasZeroGravityVolume; + } + else + { + Vessel ??= otherConfig.Vessel; + } entryPositions = Concatenate(entryPositions, otherConfig.entryPositions); curiosities = Concatenate(curiosities, otherConfig.curiosities); @@ -270,11 +310,33 @@ public void Migrate() { Vessel = new VesselModule(); } - Vessel.coords = Vessel.coords ?? coords; - Vessel.vesselPosition = Vessel.vesselPosition ?? vesselPosition; - Vessel.vesselRotation = Vessel.vesselRotation ?? vesselRotation; - Vessel.warpExitPosition = Vessel.warpExitPosition ?? warpExitPosition; - Vessel.warpExitRotation = Vessel.warpExitRotation ?? warpExitRotation; + Vessel.coords ??= coords; + Vessel.vesselPosition ??= vesselPosition; + Vessel.vesselRotation ??= vesselRotation; + Vessel.warpExitPosition ??= warpExitPosition; + Vessel.warpExitRotation ??= warpExitRotation; + } + if (Vessel != null) + { + if (Vessel.vesselPosition != null || Vessel.vesselRotation != null) + { + if (Vessel.vesselSpawn == null) + { + Vessel.vesselSpawn = new VesselModule.VesselInfo(); + } + Vessel.vesselSpawn.position ??= Vessel.vesselPosition; + Vessel.vesselSpawn.rotation ??= Vessel.vesselRotation; + } + if (Vessel.warpExitPosition != null || Vessel.warpExitRotation != null) + { + if (Vessel.warpExit == null) + { + Vessel.warpExit = new VesselModule.WarpExitInfo(); + } + Vessel.warpExit.position ??= Vessel.warpExitPosition; + Vessel.warpExit.rotation ??= Vessel.warpExitRotation; + Vessel.warpExit.attachToVessel = true; + } } } } diff --git a/NewHorizons/External/Modules/BrambleModule.cs b/NewHorizons/External/Modules/BrambleModule.cs index 9b98c0de3..63f48abd9 100644 --- a/NewHorizons/External/Modules/BrambleModule.cs +++ b/NewHorizons/External/Modules/BrambleModule.cs @@ -78,18 +78,8 @@ public class BrambleDimensionInfo [JsonObject] - public class BrambleNodeInfo + public class BrambleNodeInfo : GeneralPropInfo { - /// - /// The physical position of the node - /// - public MVector3 position; - - /// - /// The physical rotation of the node - /// - public MVector3 rotation; - /// /// The physical scale of the node, as a multiplier of the original size. /// Nodes are 150m across, seeds are 10m across. diff --git a/NewHorizons/External/Modules/GeneralPropInfo.cs b/NewHorizons/External/Modules/GeneralPropInfo.cs new file mode 100644 index 000000000..8ab528a1e --- /dev/null +++ b/NewHorizons/External/Modules/GeneralPropInfo.cs @@ -0,0 +1,54 @@ + +using NewHorizons.Utility; +using Newtonsoft.Json; + +namespace NewHorizons.External.Modules +{ + [JsonObject] + public abstract class GeneralPointPropInfo + { + /// + /// Position of the object + /// + public MVector3 position; + + /// + /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). + /// + public string parentPath; + + /// + /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. + /// + public bool isRelativeToParent; + + /// + /// An optional rename of this object + /// + public string rename; + } + + [JsonObject] + public abstract class GeneralPropInfo : GeneralPointPropInfo + { + /// + /// Rotation of the object + /// + public MVector3 rotation; + + /// + /// Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation. + /// Defaults to true for geysers, tornados, and volcanoes, and false for everything else. + /// + public bool? alignRadial; + } + + [JsonObject] + public abstract class GeneralSolarSystemPropInfo : GeneralPropInfo + { + /// + /// The name of the planet that will be used with `parentPath`. Must be set if `parentPath` is set. + /// + public string parentBody; + } +} diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index 5ff5625ea..78b12b35d 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -1,12 +1,13 @@ - +using NewHorizons.External.Modules.VariableSize; +using NewHorizons.External.Modules.WarpPad; using NewHorizons.Utility; -using System.ComponentModel; -using System.ComponentModel.DataAnnotations; -using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; using System; -using NewHorizons.External.Modules.VariableSize; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; namespace NewHorizons.External.Modules { @@ -42,7 +43,7 @@ public class PropModule /// /// Add translatable text to this planet /// - public NomaiTextInfo[] translatorText; + public TranslatorTextInfo[] translatorText; /// /// Details which will be shown from 50km away. Meant to be lower resolution. @@ -94,6 +95,16 @@ public class PropModule /// public RemoteInfo[] remotes; + /// + /// Add warp pad receivers to this planet. These are the warp pads you are sent to from Ash Twin. + /// + public NomaiWarpReceiverInfo[] warpReceivers; + + /// + /// Add warp pad transmitters to this planet. These are the warp pads seen on the Ash Twin. + /// + public NomaiWarpTransmitterInfo[] warpTransmitters; + [Obsolete("reveal is deprecated. Use Volumes->revealVolumes instead.")] public VolumesModule.RevealVolumeInfo[] reveal; [Obsolete("audioVolumes is deprecated. Use Volumes->audioVolumes instead.")] public VolumesModule.AudioVolumeInfo[] audioVolumes; @@ -163,17 +174,14 @@ public class ScatterInfo } [JsonObject] - public class DetailInfo + public class DetailInfo : GeneralPropInfo { - /// - /// An optional rename of the detail - /// - public string rename; + public DetailInfo() { } - /// - /// Do we override rotation and try to automatically align this object to stand upright on the body's surface? - /// - public bool alignToNormal; + public DetailInfo(GeneralPointPropInfo info) + { + JsonConvert.PopulateObject(JsonConvert.SerializeObject(info), this); + } /// /// Relative filepath to an asset-bundle to load the prefab defined in `path` from @@ -185,11 +193,6 @@ public class DetailInfo /// public string path; - /// - /// Position of this prop relative to the body's center - /// - public MVector3 position; - /// /// A list of children to remove from this detail /// @@ -201,11 +204,6 @@ public class DetailInfo /// public bool removeComponents; - /// - /// Rotate this prop - /// - public MVector3 rotation; - /// /// Scale the prop /// @@ -221,16 +219,6 @@ public class DetailInfo /// 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; - - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - /// /// Should this detail stay loaded even if you're outside the sector (good for very large props) /// @@ -253,45 +241,22 @@ public class DetailInfo /// If there's already good colliders on the detail, you can make this 0. /// [DefaultValue(1f)] public float physicsRadius = 1f; + + [Obsolete("alignToNormal is deprecated. Use alignRadial instead")] public bool alignToNormal; } [JsonObject] - public class RaftInfo + public class RaftInfo : GeneralPropInfo { - /// - /// Position of the raft - /// - public MVector3 position; - /// /// Acceleration of the raft. Default acceleration is 5. /// [DefaultValue(5f)] public float acceleration = 5f; - - /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// An optional rename of this object - /// - public string rename; } [JsonObject] - public class GeyserInfo + public class GeyserInfo : GeneralPropInfo { - /// - /// Position of the geyser - /// - public MVector3 position; - /// /// Vertical offset of the geyser. From 0, the bubbles start at a height of 10, the shaft at 67, and the spout at 97.5. /// @@ -326,20 +291,10 @@ public class GeyserInfo /// Loudness of the geyser /// [DefaultValue(0.7f)] public float volume = 0.7f; - - /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// An optional rename of this object - /// - public string rename; } [JsonObject] - public class TornadoInfo + public class TornadoInfo : GeneralPropInfo { [JsonConverter(typeof(StringEnumConverter))] public enum TornadoType @@ -363,11 +318,6 @@ public enum TornadoType /// [DefaultValue(30f)] public float height = 30f; - /// - /// Position of the tornado - /// - public MVector3 position; - /// /// The colour of the tornado. /// @@ -403,25 +353,10 @@ public enum TornadoType /// Fluid type for sounds/effects when colliding with this tornado. /// [DefaultValue("cloud")] public FluidType fluidType = FluidType.Cloud; - - /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// An optional rename of this object - /// - public string rename; } [JsonObject] - public class VolcanoInfo + public class VolcanoInfo : GeneralPropInfo { /// /// The colour of the meteor's lava. @@ -452,11 +387,6 @@ public class VolcanoInfo [DefaultValue(50f)] public float minLaunchSpeed = 50f; - /// - /// Position of this volcano. - /// - public MVector3 position; - /// /// Scale of the meteors. /// @@ -466,25 +396,10 @@ public class VolcanoInfo /// The colour of the meteor's stone. /// public MColor stoneTint; - - /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// An optional rename of this object - /// - public string rename; } [JsonObject] - public class DialogueInfo + public class DialogueInfo : GeneralPointPropInfo { /// /// Prevents the dialogue from being created after a specific persistent condition is set. Useful for remote dialogue @@ -506,57 +421,31 @@ public class DialogueInfo /// public string pathToAnimController; - /// - /// When you enter into dialogue, you will look here. - /// - public MVector3 position; - /// /// Radius of the spherical collision volume where you get the "talk to" prompt when looking at. If you use a - /// remoteTriggerPosition, you can set this to 0 to make the dialogue only trigger remotely. + /// remoteTrigger, you can set this to 0 to make the dialogue only trigger remotely. /// public float radius = 1f; - /// - /// Allows you to trigger dialogue from a distance when you walk into an area. - /// - public MVector3 remoteTriggerPosition; - /// /// Distance from radius the prompt appears /// [DefaultValue(2f)] public float range = 2f; /// - /// The radius of the remote trigger volume. + /// Allows you to trigger dialogue from a distance when you walk into an area. /// - public float remoteTriggerRadius; + public RemoteTriggerInfo remoteTrigger; - /// - /// If setting up a remote trigger volume, this conditions must be met for it to trigger. Note: This is a dialogue condition, not a persistent condition. - /// - public string remoteTriggerPrereqCondition; + [Obsolete("remoteTriggerPosition is deprecated. Use remoteTrigger.position instead")] public MVector3 remoteTriggerPosition; + [Obsolete("remoteTriggerRadius is deprecated. Use remoteTrigger.radius instead")] public float remoteTriggerRadius; + [Obsolete("remoteTriggerPrereqCondition is deprecated. Use remoteTrigger.prereqCondition instead")] public string remoteTriggerPrereqCondition; /// /// Relative path to the xml file defining the dialogue. /// public string xmlFile; - /// - /// Whether the positional and rotational coordinates are relative to the animation controller instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// Optionally rename the dialogue object. The remote trigger volume will be renamed to have this as a prefix. - /// - public string rename; - - /// - /// Optionally set the parent object that the dialogue and remote trigger will be attached to - /// - public string parentPath; - /// /// What type of flashlight toggle to do when dialogue is interacted with /// @@ -569,10 +458,23 @@ public enum FlashlightToggle [EnumMember(Value = @"turnOff")] TurnOff = 0, [EnumMember(Value = @"turnOffThenOn")] TurnOffThenOn = 1, } + + [JsonObject] + public class RemoteTriggerInfo : GeneralPointPropInfo + { + /// + /// The radius of the remote trigger volume. + /// + public float radius; + /// + /// This condition must be met for the remote trigger volume to trigger. + /// + public string prereqCondition; + } } [JsonObject] - public class EntryLocationInfo + public class EntryLocationInfo : GeneralPointPropInfo { /// /// Whether this location is cloaked @@ -583,62 +485,79 @@ public class EntryLocationInfo /// ID of the entry this location relates to /// public string id; + } + [JsonObject] + public class TranslatorTextInfo : GeneralPropInfo + { /// - /// The position of this entry location + /// Additional information about each arc in the text /// - public MVector3 position; + public NomaiTextArcInfo[] arcInfo; /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). + /// The random seed used to pick what the text arcs will look like. /// - public string parentPath; + public int seed; /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. + /// Only for wall text. Aligns wall text to face towards the given direction, with 'up' oriented relative to its current rotation or alignment. /// - public bool isRelativeToParent; + public MVector3 normal; /// - /// An optional rename of this object + /// The type of object this is. /// - public string rename; + [DefaultValue("wall")] public NomaiTextType type = NomaiTextType.Wall; + + /// + /// The location of this object. Arcs will be blue if their locations match the wall, else orange. + /// + [DefaultValue("unspecified")] public NomaiTextLocation location = NomaiTextLocation.UNSPECIFIED; + + /// + /// The relative path to the xml file for this object. + /// + public string xmlFile; } - [JsonObject] - public class NomaiTextInfo + [JsonConverter(typeof(StringEnumConverter))] + public enum NomaiTextType { - [JsonConverter(typeof(StringEnumConverter))] - public enum NomaiTextType - { - [EnumMember(Value = @"wall")] Wall = 0, + [EnumMember(Value = @"wall")] Wall = 0, - [EnumMember(Value = @"scroll")] Scroll = 1, + [EnumMember(Value = @"scroll")] Scroll = 1, - [EnumMember(Value = @"computer")] Computer = 2, + [EnumMember(Value = @"computer")] Computer = 2, - [EnumMember(Value = @"cairn")] Cairn = 3, + [EnumMember(Value = @"cairn")] Cairn = 3, - [EnumMember(Value = @"recorder")] Recorder = 4, + [EnumMember(Value = @"recorder")] Recorder = 4, - [EnumMember(Value = @"preCrashRecorder")] PreCrashRecorder = 5, + [EnumMember(Value = @"preCrashRecorder")] PreCrashRecorder = 5, - [EnumMember(Value = @"preCrashComputer")] PreCrashComputer = 6, + [EnumMember(Value = @"preCrashComputer")] PreCrashComputer = 6, - [EnumMember(Value = @"trailmarker")] Trailmarker = 7, + [EnumMember(Value = @"trailmarker")] Trailmarker = 7, - [EnumMember(Value = @"cairnVariant")] CairnVariant = 8, - } + [EnumMember(Value = @"cairnVariant")] CairnVariant = 8, - [JsonConverter(typeof(StringEnumConverter))] - public enum NomaiTextLocation - { - [EnumMember(Value = @"unspecified")] UNSPECIFIED = 0, + [EnumMember(Value = @"whiteboard")] Whiteboard = 9, + } - [EnumMember(Value = @"a")] A = 1, + [JsonConverter(typeof(StringEnumConverter))] + public enum NomaiTextLocation + { + [EnumMember(Value = @"unspecified")] UNSPECIFIED = 0, - [EnumMember(Value = @"b")] B = 2 - } + [EnumMember(Value = @"a")] A = 1, + + [EnumMember(Value = @"b")] B = 2 + } + + [JsonObject] + public class NomaiTextInfo : GeneralPointPropInfo + { /// /// Additional information about each arc in the text @@ -650,11 +569,6 @@ public enum NomaiTextLocation /// public MVector3 normal; - /// - /// Position of the root of this text - /// - public MVector3 position; - /// /// The euler angle rotation of this object. Not required if setting the normal. Computers and cairns will orient /// themselves to the surface of the planet automatically. @@ -672,7 +586,7 @@ public enum NomaiTextLocation [DefaultValue("wall")] public NomaiTextType type = NomaiTextType.Wall; /// - /// The location of this object. + /// The location of this object. Arcs will be blue if their locations match the wall, else orange. /// [DefaultValue("unspecified")] public NomaiTextLocation location = NomaiTextLocation.UNSPECIFIED; @@ -680,21 +594,6 @@ public enum NomaiTextLocation /// The relative path to the xml file for this object. /// public string xmlFile; - - /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// An optional rename of this object - /// - public string rename; } [JsonObject] @@ -711,38 +610,34 @@ public enum NomaiTextArcType } /// - /// Whether to skip modifying this spiral's placement, and instead keep the automatically determined placement. + /// The type of text to display. /// - public bool keepAutoPlacement; - + [DefaultValue("adult")] public NomaiTextArcType type = NomaiTextArcType.Adult; + /// - /// Whether to flip the spiral from left-curling to right-curling or vice versa. + /// The local position of this object on the wall. If specified, auto spiral will not touch this arc. /// - public bool mirror; + public MVector2 position; /// - /// The local position of this object on the wall. + /// The z euler angle for this arc. If specified, auto spiral will not touch this arc. /// - public MVector2 position; + [Range(0f, 360f)] public float? zRotation; /// - /// The type of text to display. + /// Whether to flip the spiral from left-curling to right-curling or vice versa. If specified, auto spiral will not touch this arc. /// - [DefaultValue("adult")] public NomaiTextArcType type = NomaiTextArcType.Adult; + public bool? mirror; /// /// Which variation of the chosen type to place. If not specified, a random variation will be selected based on the seed provided in the parent module. /// + [Obsolete("only used in old nomai text")] [DefaultValue(-1)] public int variation = -1; - - /// - /// The z euler angle for this arc. - /// - [Range(0f, 360f)] public float zRotation; } [JsonObject] - public class ProjectionInfo + public class ProjectionInfo : GeneralPropInfo { [JsonConverter(typeof(StringEnumConverter))] public enum SlideShowType @@ -757,11 +652,6 @@ public enum SlideShowType } - /// - /// The position of this slideshow. - /// - public MVector3 position; - /// /// The ship log facts revealed after finishing this slide reel. /// @@ -775,11 +665,6 @@ public enum SlideShowType /// public string[] playWithShipLogFacts; - /// - /// The rotation of this slideshow. - /// - public MVector3 rotation; - /// /// The list of slides for this object. /// @@ -789,21 +674,6 @@ public enum SlideShowType /// The type of object this is. /// [DefaultValue("slideReel")] public SlideShowType type = SlideShowType.SlideReel; - - /// - /// The relative path from the planet to the parent of this slideshow. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// An optional rename of this object - /// - public string rename; } [JsonObject] @@ -934,18 +804,8 @@ public class QuantumGroupInfo } [JsonObject] - public class QuantumSocketInfo + public class QuantumSocketInfo : GeneralPropInfo { - /// - /// The location of this socket - /// - public MVector3 position; - - /// - /// The rotation the quantum object will take if it's occupying this socket - /// - public MVector3 rotation; - /// /// The probability any props that are part of this group will occupy this socket /// @@ -981,38 +841,13 @@ public class RemoteInfo public StoneInfo[] stones; [JsonObject] - public class WhiteboardInfo + public class WhiteboardInfo : GeneralPropInfo { /// /// The text for each stone /// public SharedNomaiTextInfo[] nomaiText; - /// - /// The location of this platform. - /// - public MVector3 position; - - /// - /// The rotation of this platform. - /// - public MVector3 rotation; - - /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// An optional rename of this object - /// - public string rename; - /// /// Disable the wall, leaving only the pedestal and text. /// @@ -1037,9 +872,9 @@ public class SharedNomaiTextInfo public int seed; // For randomizing arcs /// - /// The location of this object. + /// The location of this object. Arcs will be blue if their locations match the wall, else orange. /// - [DefaultValue("unspecified")] public NomaiTextInfo.NomaiTextLocation location = NomaiTextInfo.NomaiTextLocation.UNSPECIFIED; + [DefaultValue("unspecified")] public NomaiTextLocation location = NomaiTextLocation.UNSPECIFIED; /// /// The relative path to the xml file for this object. @@ -1054,33 +889,8 @@ public class SharedNomaiTextInfo } [JsonObject] - public class PlatformInfo + public class PlatformInfo : GeneralPropInfo { - /// - /// The location of this platform. - /// - public MVector3 position; - - /// - /// The rotation of this platform. - /// - public MVector3 rotation; - - /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// An optional rename of this object - /// - public string rename; - /// /// A ship log fact to reveal when the platform is connected to. /// @@ -1098,32 +908,9 @@ public class PlatformInfo } [JsonObject] - public class StoneInfo + public class StoneInfo : GeneralPropInfo { - /// - /// The location of this stone. - /// - public MVector3 position; - - /// - /// The rotation of this stone. - /// - public MVector3 rotation; - - /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). - /// - public string parentPath; - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// An optional rename of this object - /// - public string rename; } } } diff --git a/NewHorizons/External/Modules/RingModule.cs b/NewHorizons/External/Modules/RingModule.cs index a5c93c4cb..ef60c6cf4 100644 --- a/NewHorizons/External/Modules/RingModule.cs +++ b/NewHorizons/External/Modules/RingModule.cs @@ -1,6 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; -using NewHorizons.Utility; +using NewHorizons.External.Modules.VariableSize; using Newtonsoft.Json; namespace NewHorizons.External.Modules diff --git a/NewHorizons/External/Modules/SignalModule.cs b/NewHorizons/External/Modules/SignalModule.cs index 255ebc9b6..e06405ff0 100644 --- a/NewHorizons/External/Modules/SignalModule.cs +++ b/NewHorizons/External/Modules/SignalModule.cs @@ -15,7 +15,7 @@ public class SignalModule public SignalInfo[] signals; [JsonObject] - public class SignalInfo + public class SignalInfo : GeneralPointPropInfo { [Obsolete("audioClip is deprecated, please use audio instead")] public string audioClip; @@ -61,11 +61,6 @@ public class SignalInfo /// [DefaultValue(true)] public bool onlyAudibleToScope = true; - /// - /// Position of the signal's source - /// - public MVector3 position; - /// /// A ship log fact to reveal when the signal is identified. /// @@ -75,16 +70,6 @@ public class SignalInfo /// Radius of the sphere giving off the signal. /// [DefaultValue(1f)] public float sourceRadius = 1f; - - /// - /// The relative path from the planet to the parent of this signal. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; } } } \ No newline at end of file diff --git a/NewHorizons/External/Modules/SpawnModule.cs b/NewHorizons/External/Modules/SpawnModule.cs index be6c2bfd9..5e2d0377b 100644 --- a/NewHorizons/External/Modules/SpawnModule.cs +++ b/NewHorizons/External/Modules/SpawnModule.cs @@ -1,5 +1,6 @@ -using NewHorizons.Utility; +using NewHorizons.Utility; using Newtonsoft.Json; +using System; namespace NewHorizons.External.Modules { @@ -7,29 +8,36 @@ namespace NewHorizons.External.Modules public class SpawnModule { /// - /// If you want the player to spawn on the new body, set a value for this. Press `P` in game with Debug mode on to have - /// the game log the position you're looking at to find a good value for this. + /// If you want the player to spawn on the new body, set a value for this. /// - public MVector3 playerSpawnPoint; - - /// - /// Euler angles by which the player will be oriented. - /// - public MVector3 playerSpawnRotation; + public PlayerSpawnPoint playerSpawn; /// /// Required for the system to be accessible by warp drive. /// - public MVector3 shipSpawnPoint; + public ShipSpawnPoint shipSpawn; - /// - /// Euler angles by which the ship will be oriented. - /// - public MVector3 shipSpawnRotation; + [Obsolete("playerSpawnPoint is deprecated. Use playerSpawn.position instead")] public MVector3 playerSpawnPoint; + [Obsolete("playerSpawnRotation is deprecated. Use playerSpawn.rotation instead")] public MVector3 playerSpawnRotation; + [Obsolete("shipSpawnPoint is deprecated. Use shipSpawn.position instead")] public MVector3 shipSpawnPoint; + [Obsolete("shipSpawnRotation is deprecated. Use shipSpawn.rotation instead")] public MVector3 shipSpawnRotation; + [Obsolete("startWithSuit is deprecated. Use playerSpawn.startWithSuit instead")] public bool startWithSuit; - /// - /// If you spawn on a planet with no oxygen, you probably want to set this to true ;;) - /// - public bool startWithSuit; + [JsonObject] + public class PlayerSpawnPoint : GeneralPropInfo { + /// + /// If you spawn on a planet with no oxygen, you probably want to set this to true ;;) + /// + public bool startWithSuit; + /// + /// Whether this planet's spawn point is the one the player will initially spawn at, if multiple spawn points exist. + /// + public bool isDefault; + } + + [JsonObject] + public class ShipSpawnPoint : GeneralPropInfo { + + } } } \ No newline at end of file diff --git a/NewHorizons/External/Modules/VariableSize/SingularityModule.cs b/NewHorizons/External/Modules/VariableSize/SingularityModule.cs index e0c1041dc..522ca7c48 100644 --- a/NewHorizons/External/Modules/VariableSize/SingularityModule.cs +++ b/NewHorizons/External/Modules/VariableSize/SingularityModule.cs @@ -9,7 +9,7 @@ namespace NewHorizons.External.Modules.VariableSize { [JsonObject] - public class SingularityModule : VariableSizeModule + public class SingularityModule : GeneralPropInfo { [JsonConverter(typeof(StringEnumConverter))] public enum SingularityType @@ -19,6 +19,11 @@ public enum SingularityType [EnumMember(Value = @"whiteHole")] WhiteHole = 1 } + /// + /// Scale this object over time + /// + public TimeValuePair[] curve; + /// /// 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 @@ -30,16 +35,6 @@ public enum SingularityType /// public string uniqueID; - /// - /// Position of the singularity - /// - public MVector3 position; - - /// - /// Rotation of the singularity. Determines the direction you come out of a white hole - /// - public MVector3 rotation; - /// /// Radius of the singularity. Note that this isn't the same as the event horizon, but includes the entire volume that /// has warped effects in it. @@ -75,20 +70,5 @@ public enum SingularityType /// Optional override for the render queue. If the singularity is rendering oddly, increasing this to 3000 can help /// [Range(2501f, 3500f)] public int renderQueueOverride = 2985; - - /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// An optional rename of this object - /// - public string rename; } } \ No newline at end of file diff --git a/NewHorizons/Utility/TimeValuePair.cs b/NewHorizons/External/Modules/VariableSize/TimeValuePair.cs similarity index 85% rename from NewHorizons/Utility/TimeValuePair.cs rename to NewHorizons/External/Modules/VariableSize/TimeValuePair.cs index acacda16e..38ec9be34 100644 --- a/NewHorizons/Utility/TimeValuePair.cs +++ b/NewHorizons/External/Modules/VariableSize/TimeValuePair.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace NewHorizons.Utility +namespace NewHorizons.External.Modules.VariableSize { [JsonObject] public class TimeValuePair diff --git a/NewHorizons/External/Modules/VariableSize/VariableSizeModule.cs b/NewHorizons/External/Modules/VariableSize/VariableSizeModule.cs index 92ba2dd13..5e5767b14 100644 --- a/NewHorizons/External/Modules/VariableSize/VariableSizeModule.cs +++ b/NewHorizons/External/Modules/VariableSize/VariableSizeModule.cs @@ -1,4 +1,3 @@ -using NewHorizons.Utility; using Newtonsoft.Json; using UnityEngine; diff --git a/NewHorizons/External/Modules/VolumesModule.cs b/NewHorizons/External/Modules/VolumesModule.cs index 797428305..7ccc6d41a 100644 --- a/NewHorizons/External/Modules/VolumesModule.cs +++ b/NewHorizons/External/Modules/VolumesModule.cs @@ -117,33 +117,13 @@ public class VolumesModule public LoadCreditsVolumeInfo[] creditsVolume; [JsonObject] - public class VolumeInfo + public class VolumeInfo : GeneralPointPropInfo { - /// - /// The location of this volume. Optional (will default to 0,0,0). - /// - public MVector3 position; - /// /// The radius of this volume. /// [DefaultValue(1f)] public float radius = 1f; - - /// - /// The relative path from the planet to the parent of this object. Optional (will default to the root sector). - /// - public string parentPath; - - /// - /// Whether the positional coordinates are relative to parent instead of the root planet object. - /// - public bool isRelativeToParent; - - /// - /// An optional rename of this volume. - /// - public string rename; } [JsonObject] @@ -171,6 +151,16 @@ public enum CreditsType [DefaultValue("fast")] public CreditsType creditsType = CreditsType.Fast; + + /// + /// Text displayed in orange on game over. For localization, put translations under UI. + /// + public string gameOverText; + + /// + /// The type of death the player will have if they enter this volume. + /// + [DefaultValue("default")] public DestructionVolumeInfo.DeathType deathType = DestructionVolumeInfo.DeathType.Default; } [JsonObject] diff --git a/NewHorizons/External/Modules/WarpPad/NomaiWarpComputerInfo.cs b/NewHorizons/External/Modules/WarpPad/NomaiWarpComputerInfo.cs new file mode 100644 index 000000000..bd2bb6d75 --- /dev/null +++ b/NewHorizons/External/Modules/WarpPad/NomaiWarpComputerInfo.cs @@ -0,0 +1,9 @@ +using Newtonsoft.Json; + +namespace NewHorizons.External.Modules.WarpPad +{ + [JsonObject] + public class NomaiWarpComputerLoggerInfo : GeneralPropInfo + { + } +} diff --git a/NewHorizons/External/Modules/WarpPad/NomaiWarpPadInfo.cs b/NewHorizons/External/Modules/WarpPad/NomaiWarpPadInfo.cs new file mode 100644 index 000000000..f4cd75153 --- /dev/null +++ b/NewHorizons/External/Modules/WarpPad/NomaiWarpPadInfo.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace NewHorizons.External.Modules.WarpPad +{ + [JsonObject] + public abstract class NomaiWarpPadInfo : GeneralPropInfo + { + public string frequency; + } +} diff --git a/NewHorizons/External/Modules/WarpPad/NomaiWarpPadReceiverInfo.cs b/NewHorizons/External/Modules/WarpPad/NomaiWarpPadReceiverInfo.cs new file mode 100644 index 000000000..6680284c1 --- /dev/null +++ b/NewHorizons/External/Modules/WarpPad/NomaiWarpPadReceiverInfo.cs @@ -0,0 +1,24 @@ +using Newtonsoft.Json; + +namespace NewHorizons.External.Modules.WarpPad +{ + [JsonObject] + public class NomaiWarpReceiverInfo : NomaiWarpPadInfo + { + /// + /// The body the transmitter must be aligned with to warp to this receiver. + /// Defaults to the body the receiver is on. + /// + public string alignmentTargetBody; + + /// + /// Will create a modern Nomai computer linked to this receiver. + /// + public NomaiWarpComputerLoggerInfo computer; + + /// + /// Set to true if you want to include Nomai ruin details around the warp pad. + /// + public bool detailed; + } +} diff --git a/NewHorizons/External/Modules/WarpPad/NomaiWarpTransmitterInfo.cs b/NewHorizons/External/Modules/WarpPad/NomaiWarpTransmitterInfo.cs new file mode 100644 index 000000000..3a1dd55ca --- /dev/null +++ b/NewHorizons/External/Modules/WarpPad/NomaiWarpTransmitterInfo.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; +using System.ComponentModel; + +namespace NewHorizons.External.Modules.WarpPad +{ + [JsonObject] + public class NomaiWarpTransmitterInfo : NomaiWarpPadInfo + { + /// + /// In degrees. Gives a margin of error for alignments. + /// + [DefaultValue(5f)] public float alignmentWindow = 5f; + + /// + /// This makes the alignment happen if the destination planet is BELOW you rather than above. + /// + public bool flipAlignment; + } +} diff --git a/NewHorizons/Handlers/AudioTypeHandler.cs b/NewHorizons/Handlers/AudioTypeHandler.cs index ee12465a2..db7c784b5 100644 --- a/NewHorizons/Handlers/AudioTypeHandler.cs +++ b/NewHorizons/Handlers/AudioTypeHandler.cs @@ -1,4 +1,5 @@ using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using OWML.Common; using OWML.Utils; using System; diff --git a/NewHorizons/Handlers/PlanetCreationHandler.cs b/NewHorizons/Handlers/PlanetCreationHandler.cs index e69411ee8..c6dd25dc9 100644 --- a/NewHorizons/Handlers/PlanetCreationHandler.cs +++ b/NewHorizons/Handlers/PlanetCreationHandler.cs @@ -9,6 +9,8 @@ using NewHorizons.Components.Stars; using NewHorizons.OtherMods.OWRichPresence; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; using System; using System.Collections.Generic; using System.Linq; @@ -129,6 +131,8 @@ public static void Init(List bodies) Logger.Log("Done loading bodies"); + SingularityBuilder.PairAllSingularities(); + // Events.FireOnNextUpdate(PlanetDestroyer.RemoveAllProxies); if (Main.SystemDict[Main.Instance.CurrentStarSystem].Config.destroyStockPlanets) PlanetDestructionHandler.RemoveStockPlanets(); @@ -452,7 +456,11 @@ public static GameObject GenerateStandardBody(NewHorizonsBody body, bool default if (body.Config.Spawn != null) { Logger.LogVerbose("Making spawn point"); - Main.SystemDict[body.Config.starSystem].SpawnPoint = SpawnPointBuilder.Make(go, body.Config.Spawn, owRigidBody); + var spawnPoint = SpawnPointBuilder.Make(go, body.Config.Spawn, owRigidBody); + if (Main.SystemDict[body.Config.starSystem].SpawnPoint == null || (body.Config.Spawn.playerSpawn?.isDefault ?? false)) + { + Main.SystemDict[body.Config.starSystem].SpawnPoint = spawnPoint; + } } if (body.Config.Orbit.showOrbitLine && !body.Config.Orbit.isStatic) diff --git a/NewHorizons/Handlers/PlanetDestructionHandler.cs b/NewHorizons/Handlers/PlanetDestructionHandler.cs index 05ad3455d..3cd344668 100644 --- a/NewHorizons/Handlers/PlanetDestructionHandler.cs +++ b/NewHorizons/Handlers/PlanetDestructionHandler.cs @@ -1,5 +1,7 @@ using NewHorizons.Components.Stars; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; using OWML.Utils; using System; using System.Collections.Generic; diff --git a/NewHorizons/Handlers/PlanetGraphHandler.cs b/NewHorizons/Handlers/PlanetGraphHandler.cs index b31535d2d..126f5801c 100644 --- a/NewHorizons/Handlers/PlanetGraphHandler.cs +++ b/NewHorizons/Handlers/PlanetGraphHandler.cs @@ -1,5 +1,6 @@ using NewHorizons.External.Configs; using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; using System; using System.Collections; using System.Collections.Generic; diff --git a/NewHorizons/Handlers/RemoteHandler.cs b/NewHorizons/Handlers/RemoteHandler.cs index a012074fd..539dcf28b 100644 --- a/NewHorizons/Handlers/RemoteHandler.cs +++ b/NewHorizons/Handlers/RemoteHandler.cs @@ -1,4 +1,4 @@ -using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; using OWML.Common; using OWML.Utils; using System; diff --git a/NewHorizons/Handlers/ShipLogHandler.cs b/NewHorizons/Handlers/ShipLogHandler.cs index 649624906..8618e0cfe 100644 --- a/NewHorizons/Handlers/ShipLogHandler.cs +++ b/NewHorizons/Handlers/ShipLogHandler.cs @@ -1,4 +1,5 @@ using NewHorizons.Utility; +using NewHorizons.Utility.OWUtilities; using System.Collections.Generic; using System.Linq; using UnityEngine; diff --git a/NewHorizons/Handlers/StarChartHandler.cs b/NewHorizons/Handlers/StarChartHandler.cs index e4942499f..65ae35159 100644 --- a/NewHorizons/Handlers/StarChartHandler.cs +++ b/NewHorizons/Handlers/StarChartHandler.cs @@ -66,7 +66,7 @@ public static bool CanWarp() { foreach (var system in _systems) { - if (system.Config.canEnterViaWarpDrive && system.Spawn?.shipSpawnPoint != null && HasUnlockedSystem(system.UniqueID)) + if (system.Config.canEnterViaWarpDrive && system.Spawn?.shipSpawn != null && HasUnlockedSystem(system.UniqueID)) { return true; } diff --git a/NewHorizons/Handlers/SystemCreationHandler.cs b/NewHorizons/Handlers/SystemCreationHandler.cs index cd0dc3463..594128e8f 100644 --- a/NewHorizons/Handlers/SystemCreationHandler.cs +++ b/NewHorizons/Handlers/SystemCreationHandler.cs @@ -1,6 +1,8 @@ using NewHorizons.Builder.StarSystem; using NewHorizons.Components; using NewHorizons.Utility; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; using UnityEngine; using Logger = NewHorizons.Utility.Logger; using Object = UnityEngine.Object; diff --git a/NewHorizons/Handlers/VesselWarpHandler.cs b/NewHorizons/Handlers/VesselWarpHandler.cs index adcbf3fb5..b298010fc 100644 --- a/NewHorizons/Handlers/VesselWarpHandler.cs +++ b/NewHorizons/Handlers/VesselWarpHandler.cs @@ -7,6 +7,9 @@ using Logger = NewHorizons.Utility.Logger; using static NewHorizons.Main; using NewHorizons.Components.Orbital; +using NewHorizons.Builder.Props; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; namespace NewHorizons.Handlers { @@ -24,37 +27,42 @@ public static void Initialize() VesselPrefab = Main.NHPrivateAssetBundle.LoadAsset("Vessel_Body"); } + public static bool IsVesselPresentAndActive() + { + var vesselConfig = SystemDict[Instance.CurrentStarSystem].Config?.Vessel; + var vesselIsPresent = vesselConfig?.alwaysPresent ?? false; + return Instance.IsWarpingFromVessel || vesselIsPresent; + } + + public static bool IsVesselPresent() + { + var isDefaultSolarSystem = Instance.CurrentStarSystem == "SolarSystem"; + var isEyeOfTheUniverse = Instance.CurrentStarSystem == "EyeOfTheUniverse"; + return IsVesselPresentAndActive() || isDefaultSolarSystem || isEyeOfTheUniverse; + } + + public static bool ShouldSpawnAtVessel() + { + var vesselConfig = SystemDict[Instance.CurrentStarSystem].Config?.Vessel; + var shouldSpawnOnVessel = IsVesselPresent() && (vesselConfig?.spawnOnVessel ?? false); + return !Instance.IsWarpingFromShip && (Instance.IsWarpingFromVessel || shouldSpawnOnVessel); + } + public static void LoadVessel() { + var system = SystemDict[Instance.CurrentStarSystem]; if (Instance.CurrentStarSystem == "EyeOfTheUniverse") { _vesselSpawnPoint = SearchUtilities.Find("Vessel_Body/SPAWN_Vessel").GetComponent(); return; } - if (Instance.IsWarpingFromVessel) + if (IsVesselPresentAndActive()) _vesselSpawnPoint = Instance.CurrentStarSystem == "SolarSystem" ? UpdateVessel() : CreateVessel(); else _vesselSpawnPoint = SearchUtilities.Find("DB_VesselDimension_Body/Sector_VesselDimension").GetComponentInChildren(); } - public static void OnReceiveWarpedBody(OWRigidbody warpedBody, NomaiWarpPlatform startPlatform, NomaiWarpPlatform targetPlatform) - { - bool isPlayer = warpedBody.CompareTag("Player"); - if (isPlayer) - { - Transform player_body = Locator.GetPlayerTransform(); - OWRigidbody s_rb = Locator.GetShipBody(); - OWRigidbody p_rb = Locator.GetPlayerBody(); - Vector3 newPos = player_body.position; - Vector3 offset = player_body.up * 10; - newPos += offset; - s_rb.SetPosition(newPos); - s_rb.SetRotation(player_body.transform.rotation); - s_rb.SetVelocity(p_rb.GetVelocity()); - } - } - public static void TeleportToVessel() { var playerSpawner = GameObject.FindObjectOfType(); @@ -84,10 +92,8 @@ public static EyeSpawnPoint CreateVessel() if (VesselPrefab == null) return null; Logger.LogVerbose("Creating Vessel"); - var vesselObject = VesselPrefab.InstantiateInactive(); + var vesselObject = GeneralPropBuilder.MakeFromPrefab(VesselPrefab, VesselPrefab.name, null, null, system.Config.Vessel?.vesselSpawn); VesselObject = vesselObject; - vesselObject.name = VesselPrefab.name; - vesselObject.transform.parent = null; var vesselAO = vesselObject.AddComponent(); vesselAO._owRigidbody = vesselObject.GetComponent(); @@ -98,12 +104,6 @@ public static EyeSpawnPoint CreateVessel() vesselAO.Register(); vesselObject.GetComponentInChildren(true)._referenceFrame._attachedAstroObject = vesselAO; - if (system.Config.Vessel?.vesselPosition != null) - vesselObject.transform.position = system.Config.Vessel.vesselPosition; - - if (system.Config.Vessel?.vesselRotation != null) - vesselObject.transform.eulerAngles = system.Config.Vessel.vesselRotation; - VesselSingularityRoot singularityRoot = vesselObject.GetComponentInChildren(true); VesselWarpController vesselWarpController = vesselObject.GetComponentInChildren(true); @@ -145,18 +145,56 @@ public static EyeSpawnPoint CreateVessel() vesselWarpController._whiteHole = newWhiteHole.GetComponentInChildren(); vesselWarpController._whiteHoleOneShot = vesselWarpController._whiteHole.transform.parent.Find("WhiteHoleAudio_OneShot").GetComponent(); - vesselWarpController._targetWarpPlatform.OnReceiveWarpedBody += OnReceiveWarpedBody; + vesselObject.GetComponent()._labelID = (UITextType)TranslationHandler.AddUI("Vessel"); - if (system.Config.Vessel?.warpExitPosition != null) - vesselWarpController._targetWarpPlatform.transform.localPosition = system.Config.Vessel.warpExitPosition; + var hasParentBody = !string.IsNullOrEmpty(system.Config.Vessel?.vesselSpawn?.parentBody); + var hasPhysics = system.Config.Vessel?.hasPhysics ?? !hasParentBody; - if (system.Config.Vessel?.warpExitRotation != null) - vesselWarpController._targetWarpPlatform.transform.localEulerAngles = system.Config.Vessel.warpExitRotation; + if (hasPhysics) + { + vesselObject.transform.parent = null; + } + else + { + vesselAO._owRigidbody = null; + UnityEngine.Object.DestroyImmediate(vesselObject.GetComponent()); + UnityEngine.Object.DestroyImmediate(vesselObject.GetComponent()); + UnityEngine.Object.DestroyImmediate(vesselObject.GetComponent()); + UnityEngine.Object.DestroyImmediate(vesselObject.GetComponent()); + var rfVolume = vesselObject.transform.Find("RFVolume"); + if (rfVolume != null) + { + GameObject.Destroy(rfVolume.gameObject); + } + } - vesselObject.GetComponent()._labelID = (UITextType)TranslationHandler.AddUI("Vessel"); + var attachWarpExitToVessel = system.Config.Vessel?.warpExit?.attachToVessel ?? false; + var warpExitParent = vesselWarpController._targetWarpPlatform.transform.parent; + + var planetGO = hasPhysics ? vesselObject.transform.parent.gameObject : null; + + var warpExit = GeneralPropBuilder.MakeFromExisting(vesselWarpController._targetWarpPlatform.gameObject, planetGO, null, system.Config.Vessel?.warpExit, parentOverride: attachWarpExitToVessel ? warpExitParent : null); + if (attachWarpExitToVessel) + { + warpExit.transform.parent = warpExitParent; + } + vesselWarpController._targetWarpPlatform._owRigidbody = warpExit.GetAttachedOWRigidbody(); + + var hasZeroGravityVolume = system.Config.Vessel?.hasZeroGravityVolume ?? !hasParentBody; + if (!hasZeroGravityVolume) + { + var zeroGVolume = vesselObject.transform.Find("Sector_VesselBridge/Volumes_VesselBridge/ZeroGVolume"); + if (zeroGVolume != null) + { + GameObject.Destroy(zeroGVolume.gameObject); + } + } EyeSpawnPoint eyeSpawnPoint = vesselObject.GetComponentInChildren(true); - system.SpawnPoint = eyeSpawnPoint; + if (ShouldSpawnAtVessel()) + { + system.SpawnPoint = eyeSpawnPoint; + } vesselObject.SetActive(true); @@ -178,9 +216,6 @@ public static SpawnPoint UpdateVessel() VesselWarpController vesselWarpController = vectorSector.GetComponentInChildren(true); WarpController = vesselWarpController; - if (vesselWarpController._targetWarpPlatform != null) - vesselWarpController._targetWarpPlatform.OnReceiveWarpedBody += OnReceiveWarpedBody; - if (vesselWarpController._whiteHole == null) { GameObject whiteHole = SearchUtilities.Find("DB_VesselDimension_Body/Sector_VesselDimension/Sector_VesselBridge/Interactibles_VesselBridge/WhiteHole"); @@ -247,6 +282,10 @@ public static void SetupWarpController(VesselWarpController vesselWarpController vesselWarpController._cageAnimator.OnTranslationComplete -= new TransformAnimator.AnimationEvent(vesselWarpController.OnCageAnimationComplete); vesselWarpController._cageAnimator.OnTranslationComplete += new TransformAnimator.AnimationEvent(vesselWarpController.OnCageAnimationComplete); } + + // Normally the power-on sound is 2D/global, we set it to 3D/local so it isn't audible if the player isn't nearby + vesselWarpController._audioSource.spatialBlend = 1f; + vesselWarpController._audioSource.rolloffMode = AudioRolloffMode.Linear; } } } diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index a8518b84e..3955d27b4 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -3,6 +3,7 @@ using NewHorizons.Builder.Body; using NewHorizons.Builder.General; using NewHorizons.Builder.Props; +using NewHorizons.Builder.Props.TranslatorText; using NewHorizons.Components; using NewHorizons.Components.Fixers; using NewHorizons.Components.SizeControllers; @@ -16,6 +17,8 @@ using NewHorizons.Utility; using NewHorizons.Utility.DebugMenu; using NewHorizons.Utility.DebugUtilities; +using NewHorizons.Utility.OWMLUtilities; +using NewHorizons.Utility.OWUtilities; using OWML.Common; using OWML.ModHelper; using OWML.Utils; @@ -294,6 +297,8 @@ private void OnSceneLoaded(Scene scene, LoadSceneMode mode) ProjectionBuilder.InitPrefabs(); CloakBuilder.InitPrefab(); RaftBuilder.InitPrefab(); + + WarpPadBuilder.InitPrefabs(); } catch (Exception e) { @@ -362,6 +367,9 @@ private void OnSceneLoaded(Scene scene, LoadSceneMode mode) NewHorizonsData.Load(); + // If the vessel is forcing the player to spawn there, allow it to override + IsWarpingFromVessel = VesselWarpHandler.ShouldSpawnAtVessel(); + // Some builders have to be reset each loop SignalBuilder.Init(); BrambleDimensionBuilder.Init(); @@ -370,6 +378,7 @@ private void OnSceneLoaded(Scene scene, LoadSceneMode mode) AudioTypeHandler.Init(); InterferenceHandler.Init(); RemoteHandler.Init(); + SingularityBuilder.Init(); AtmosphereBuilder.Init(); BrambleNodeBuilder.Init(BodyDict[CurrentStarSystem].Select(x => x.Config).Where(x => x.Bramble?.dimension != null).ToArray()); diff --git a/NewHorizons/NewHorizonsApi.cs b/NewHorizons/NewHorizonsApi.cs index 1ea6b8693..7c0bdc712 100644 --- a/NewHorizons/NewHorizonsApi.cs +++ b/NewHorizons/NewHorizonsApi.cs @@ -155,14 +155,14 @@ public object QuerySystem(Type outType, string jsonPath) } public GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles, - float scale, bool alignWithNormal) + float scale, bool alignRadial) { var prefab = SearchUtilities.Find(propToCopyPath); var detailInfo = new PropModule.DetailInfo() { position = position, rotation = eulerAngles, scale = scale, - alignToNormal = alignWithNormal + alignRadial = alignRadial }; return DetailBuilder.Make(planet, sector, prefab, detailInfo); } @@ -199,10 +199,13 @@ public object QuerySystem(Type outType, string jsonPath) pathToAnimController = pathToAnimController, position = Vector3.zero, radius = radius, - remoteTriggerPosition = null, range = range, - remoteTriggerRadius = remoteTriggerRadius, - xmlFile = xmlFile + xmlFile = xmlFile, + remoteTrigger = new PropModule.DialogueInfo.RemoteTriggerInfo() + { + position = null, + radius = remoteTriggerRadius, + }, }; return DialogueBuilder.Make(root, null, info, mod); diff --git a/NewHorizons/Patches/CameraPatches/NomaiRemoteCameraPatches.cs b/NewHorizons/Patches/CameraPatches/NomaiRemoteCameraPatches.cs index 29719c0e9..c5c591e25 100644 --- a/NewHorizons/Patches/CameraPatches/NomaiRemoteCameraPatches.cs +++ b/NewHorizons/Patches/CameraPatches/NomaiRemoteCameraPatches.cs @@ -4,11 +4,11 @@ namespace NewHorizons.Patches.CameraPatches { - [HarmonyPatch] + [HarmonyPatch(typeof(NomaiRemoteCamera))] public static class NomaiRemoteCameraPatches { [HarmonyPostfix] - [HarmonyPatch(typeof(NomaiRemoteCamera), nameof(NomaiRemoteCamera.Awake))] + [HarmonyPatch(nameof(NomaiRemoteCamera.Awake))] public static void NomaiRemoteCamera_Awake(NomaiRemoteCamera __instance) { // Ensures that if the player is visible from the remote camera they look normal @@ -16,9 +16,9 @@ public static void NomaiRemoteCamera_Awake(NomaiRemoteCamera __instance) // These layers were left on because it doesnt come up in base game (Dreamworld is inactive, player is far away) __instance._camera.mainCamera.cullingMask &= ~(1 << LayerMask.NameToLayer("DreamSimulation")); - __instance._camera.mainCamera.cullingMask &= ~(1 < "None", + NomaiRemoteCameraPlatform.ID.SunStation => UITextLibrary.GetString(UITextType.LocationSS), + NomaiRemoteCameraPlatform.ID.HGT_TimeLoop => UITextLibrary.GetString(UITextType.LocationTT), + NomaiRemoteCameraPlatform.ID.TH_Mine => UITextLibrary.GetString(UITextType.LocationTH), + NomaiRemoteCameraPlatform.ID.THM_EyeLocator => UITextLibrary.GetString(UITextType.LocationTHMoon), + NomaiRemoteCameraPlatform.ID.BH_Observatory or NomaiRemoteCameraPlatform.ID.BH_GravityCannon or NomaiRemoteCameraPlatform.ID.BH_QuantumFragment or NomaiRemoteCameraPlatform.ID.BH_BlackHoleForge or NomaiRemoteCameraPlatform.ID.BH_NorthPole => UITextLibrary.GetString(UITextType.LocationBH), + NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland1 or NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland2 or NomaiRemoteCameraPlatform.ID.GD_StatueIsland => UITextLibrary.GetString(UITextType.LocationGD), + NomaiRemoteCameraPlatform.ID.GD_ProbeCannonSunkenModule => UITextLibrary.GetString(UITextType.LocationOPC_Module3), + NomaiRemoteCameraPlatform.ID.GD_ProbeCannonDamagedModule => UITextLibrary.GetString(UITextType.LocationOPC_Module2), + NomaiRemoteCameraPlatform.ID.GD_ProbeCannonIntactModule => UITextLibrary.GetString(UITextType.LocationOPC_Module1), + NomaiRemoteCameraPlatform.ID.VM_Interior => UITextLibrary.GetString(UITextType.LocationBHMoon), + NomaiRemoteCameraPlatform.ID.HGT_TLE => UITextLibrary.GetString(UITextType.LocationCT), + _ => RemoteHandler.GetPlatformIDName(id), + }; + return false; + } + } +} diff --git a/NewHorizons/Patches/CameraPatches/OWCameraPatch.cs b/NewHorizons/Patches/CameraPatches/OWCameraPatches.cs similarity index 74% rename from NewHorizons/Patches/CameraPatches/OWCameraPatch.cs rename to NewHorizons/Patches/CameraPatches/OWCameraPatches.cs index db9251c11..263a5c45d 100644 --- a/NewHorizons/Patches/CameraPatches/OWCameraPatch.cs +++ b/NewHorizons/Patches/CameraPatches/OWCameraPatches.cs @@ -2,12 +2,12 @@ namespace NewHorizons.Patches.CameraPatches { - [HarmonyPatch] - public static class OWCameraPatch + [HarmonyPatch(typeof(OWCamera))] + public static class OWCameraPatches { [HarmonyPostfix] - [HarmonyPatch(typeof(OWCamera), nameof(OWCamera.Awake))] - public static void OnOWCameraAwake(OWCamera __instance) + [HarmonyPatch(nameof(OWCamera.Awake))] + public static void OWCamera_Awake(OWCamera __instance) { if (Main.SystemDict.TryGetValue(Main.Instance.CurrentStarSystem, out var system) && system?.Config?.farClipPlaneOverride != 0f) { diff --git a/NewHorizons/Patches/CameraPatches/ProbeCameraPatches.cs b/NewHorizons/Patches/CameraPatches/ProbeCameraPatches.cs new file mode 100644 index 000000000..481c0f30f --- /dev/null +++ b/NewHorizons/Patches/CameraPatches/ProbeCameraPatches.cs @@ -0,0 +1,16 @@ +using HarmonyLib; +using NewHorizons.Handlers; + +namespace NewHorizons.Patches.CameraPatches +{ + [HarmonyPatch(typeof(ProbeCamera))] + public static class ProbeCameraPatches + { + [HarmonyPostfix] + [HarmonyPatch(nameof(ProbeCamera.HasInterference))] + public static void ProbeCamera_HasInterference(ProbeCamera __instance, ref bool __result) + { + __result = __result || (__instance._id != ProbeCamera.ID.PreLaunch && (Components.CloakSectorController.isPlayerInside != Components.CloakSectorController.isProbeInside || !InterferenceHandler.IsPlayerSameAsProbe())); + } + } +} diff --git a/NewHorizons/Patches/CharacterDialogueTreePatches.cs b/NewHorizons/Patches/CharacterDialogueTreePatches.cs deleted file mode 100644 index 2d4a8831c..000000000 --- a/NewHorizons/Patches/CharacterDialogueTreePatches.cs +++ /dev/null @@ -1,26 +0,0 @@ -using HarmonyLib; - -namespace NewHorizons.Patches; - -[HarmonyPatch] -internal static class CharacterDialogueTreePatches -{ - [HarmonyPrefix] - [HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.Awake))] - private static void CharacterDialogueTree_Awake(CharacterDialogueTree __instance) - { - GlobalMessenger.AddListener("AttachPlayerToPoint", __instance.OnAttachPlayerToPoint); - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.OnDestroy))] - private static void CharacterDialogueTree_OnDestroy(CharacterDialogueTree __instance) - { - GlobalMessenger.RemoveListener("AttachPlayerToPoint", __instance.OnAttachPlayerToPoint); - } - - private static void OnAttachPlayerToPoint(this CharacterDialogueTree characterDialogueTree, OWRigidbody rigidbody) - { - characterDialogueTree.EndConversation(); - } -} diff --git a/NewHorizons/Patches/CreditsScene/CreditsEntryPatches.cs b/NewHorizons/Patches/CreditsScenePatches/CreditsEntryPatches.cs similarity index 77% rename from NewHorizons/Patches/CreditsScene/CreditsEntryPatches.cs rename to NewHorizons/Patches/CreditsScenePatches/CreditsEntryPatches.cs index fe255ed61..05cad8a4a 100644 --- a/NewHorizons/Patches/CreditsScene/CreditsEntryPatches.cs +++ b/NewHorizons/Patches/CreditsScenePatches/CreditsEntryPatches.cs @@ -1,18 +1,14 @@ using HarmonyLib; -using NewHorizons.Utility; -using System; -namespace NewHorizons.Patches.CreditsScene +namespace NewHorizons.Patches.CreditsScenePatches { - [HarmonyPatch] + [HarmonyPatch(typeof(CreditsEntry))] public static class CreditsEntryPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(CreditsEntry), nameof(CreditsEntry.SetContents))] - public static bool CreditsEntry_SetContents(CreditsEntry __instance, string[] __0) + [HarmonyPatch(nameof(CreditsEntry.SetContents))] + public static bool CreditsEntry_SetContents(CreditsEntry __instance, string[] columnTexts) { - var columnTexts = __0; - for (int i = 0; i < __instance._columns.Length; i++) { // Base method throws out of bounds exception sometimes (_columns length doesn't match columnTexts length) diff --git a/NewHorizons/Patches/CreditsScene/CreditsPatches.cs b/NewHorizons/Patches/CreditsScenePatches/CreditsPatches.cs similarity index 66% rename from NewHorizons/Patches/CreditsScene/CreditsPatches.cs rename to NewHorizons/Patches/CreditsScenePatches/CreditsPatches.cs index 724ef6960..8892f3345 100644 --- a/NewHorizons/Patches/CreditsScene/CreditsPatches.cs +++ b/NewHorizons/Patches/CreditsScenePatches/CreditsPatches.cs @@ -1,13 +1,13 @@ using HarmonyLib; using NewHorizons.Handlers; -namespace NewHorizons.Patches.CreditsScene +namespace NewHorizons.Patches.CreditsScenePatches { - [HarmonyPatch] + [HarmonyPatch(typeof(Credits))] public static class CreditsPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(Credits), nameof(Credits.Start))] + [HarmonyPatch(nameof(Credits.Start))] public static void Credits_Start(Credits __instance) { CreditsHandler.AddCredits(__instance); diff --git a/NewHorizons/Patches/DetectorPatches/AlignToSurfaceFluidDetectorPatches.cs b/NewHorizons/Patches/DetectorPatches/AlignToSurfaceFluidDetectorPatches.cs new file mode 100644 index 000000000..308364a30 --- /dev/null +++ b/NewHorizons/Patches/DetectorPatches/AlignToSurfaceFluidDetectorPatches.cs @@ -0,0 +1,41 @@ +using HarmonyLib; +using UnityEngine; + +namespace NewHorizons.Patches.DetectorPatches +{ + [HarmonyPatch(typeof(AlignToSurfaceFluidDetector))] + public static class AlignToSurfaceFluidDetectorPatches + { + [HarmonyReversePatch] + [HarmonyPatch(typeof(AsymmetricFluidDetector), nameof(AsymmetricFluidDetector.ManagedFixedUpdate))] + public static void AsymmetricFluidDetector_ManagedFixedUpdate(AsymmetricFluidDetector __instance) + { + // This is like doing base.FixedUpdate + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(AlignToSurfaceFluidDetector.ManagedFixedUpdate))] + public static bool AlignToSurfaceFluidDetector_ManagedFixedUpdate(AlignToSurfaceFluidDetector __instance) + { + if (__instance._alignmentFluid is not RadialFluidVolume) return true; + + // Mostly copy pasting from the AlignWithDirection class + AsymmetricFluidDetector_ManagedFixedUpdate(__instance); + + if (__instance._inAlignmentFluid) + { + // Both in world space + var currentDirection = __instance._owRigidbody.transform.up; + var alignmentDirection = (__instance.transform.position - __instance._alignmentFluid.transform.position).normalized; + var degreesToTarget = Vector3.Angle(currentDirection, alignmentDirection); + + var adjustedSlerpRate = Mathf.Clamp01(0.01f * degreesToTarget * Time.fixedDeltaTime); + + Vector3 a = OWPhysics.FromToAngularVelocity(currentDirection, alignmentDirection); + __instance._owRigidbody.AddAngularVelocityChange(a * adjustedSlerpRate); + } + + return false; + } + } +} diff --git a/NewHorizons/Patches/PlayerFogWarpDetectorPatches.cs b/NewHorizons/Patches/DetectorPatches/PlayerFogWarpDetectorPatches.cs similarity index 86% rename from NewHorizons/Patches/PlayerFogWarpDetectorPatches.cs rename to NewHorizons/Patches/DetectorPatches/PlayerFogWarpDetectorPatches.cs index 003484902..e9b894c17 100644 --- a/NewHorizons/Patches/PlayerFogWarpDetectorPatches.cs +++ b/NewHorizons/Patches/DetectorPatches/PlayerFogWarpDetectorPatches.cs @@ -1,15 +1,15 @@ using HarmonyLib; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.DetectorPatches { - [HarmonyPatch] + [HarmonyPatch(typeof(PlayerFogWarpDetector))] public static class PlayerFogWarpDetectorPatches { // Morbius moment: they only let fog go away if there is a fog controller on the planet near you // However you can leave these volumes with fog on your screen, or have fog applied by a bramble node on a fogless planet [HarmonyPostfix] - [HarmonyPatch(typeof(PlayerFogWarpDetector), nameof(PlayerFogWarpDetector.LateUpdate))] + [HarmonyPatch(nameof(PlayerFogWarpDetector.LateUpdate))] public static void PlayerFogWarpDetector_LateUpdate(PlayerFogWarpDetector __instance) { if (PlanetaryFogController.GetActiveFogSphere() == null) diff --git a/NewHorizons/Patches/AchievementPatches.cs b/NewHorizons/Patches/DetectorPatches/ProbeDestructionDetectorPatches.cs similarity index 61% rename from NewHorizons/Patches/AchievementPatches.cs rename to NewHorizons/Patches/DetectorPatches/ProbeDestructionDetectorPatches.cs index 1c75e7d85..b73be6699 100644 --- a/NewHorizons/Patches/AchievementPatches.cs +++ b/NewHorizons/Patches/DetectorPatches/ProbeDestructionDetectorPatches.cs @@ -1,17 +1,15 @@ using HarmonyLib; -using NewHorizons.Components; -using NewHorizons.OtherMods.AchievementsPlus; using NewHorizons.OtherMods.AchievementsPlus.NH; -using System.Linq; +using NewHorizons.OtherMods.AchievementsPlus; using UnityEngine; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.DetectorPatches { - [HarmonyPatch] - public static class AchievementPatches + [HarmonyPatch(typeof(ProbeDestructionDetector))] + internal static class ProbeDestructionDetectorPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(ProbeDestructionDetector), nameof(ProbeDestructionDetector.FixedUpdate))] + [HarmonyPatch(nameof(ProbeDestructionDetector.FixedUpdate))] public static bool ProbeDestructionDetector_FixedUpdate(ProbeDestructionDetector __instance) { if (__instance._activeVolumes.Count > 0 && __instance._safetyVolumes.Count == 0) @@ -32,17 +30,5 @@ public static bool ProbeDestructionDetector_FixedUpdate(ProbeDestructionDetector __instance.enabled = false; return false; } - - [HarmonyPostfix] - [HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.StartConversation))] - public static void CharacterDialogueTree_StartConversation(CharacterDialogueTree __instance) - { - if (!AchievementHandler.Enabled) return; - - if (__instance is NHCharacterDialogueTree) - { - TalkToFiveCharactersAchievement.OnTalkedToCharacter(__instance._characterName); - } - } } } diff --git a/NewHorizons/Patches/DialoguePatches/CharacterDialogueTreePatches.cs b/NewHorizons/Patches/DialoguePatches/CharacterDialogueTreePatches.cs new file mode 100644 index 000000000..32cab4ad2 --- /dev/null +++ b/NewHorizons/Patches/DialoguePatches/CharacterDialogueTreePatches.cs @@ -0,0 +1,41 @@ +using HarmonyLib; +using NewHorizons.Components; +using NewHorizons.OtherMods.AchievementsPlus.NH; +using NewHorizons.OtherMods.AchievementsPlus; + +namespace NewHorizons.Patches.DialoguePatches; + +[HarmonyPatch(typeof(CharacterDialogueTree))] +public static class CharacterDialogueTreePatches +{ + [HarmonyPrefix] + [HarmonyPatch(nameof(CharacterDialogueTree.Awake))] + private static void CharacterDialogueTree_Awake(CharacterDialogueTree __instance) + { + GlobalMessenger.AddListener("AttachPlayerToPoint", __instance.OnAttachPlayerToPoint); + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(CharacterDialogueTree.OnDestroy))] + private static void CharacterDialogueTree_OnDestroy(CharacterDialogueTree __instance) + { + GlobalMessenger.RemoveListener("AttachPlayerToPoint", __instance.OnAttachPlayerToPoint); + } + + private static void OnAttachPlayerToPoint(this CharacterDialogueTree characterDialogueTree, OWRigidbody rigidbody) + { + characterDialogueTree.EndConversation(); + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(CharacterDialogueTree.StartConversation))] + public static void CharacterDialogueTree_StartConversation(CharacterDialogueTree __instance) + { + if (!AchievementHandler.Enabled) return; + + if (__instance is NHCharacterDialogueTree) + { + TalkToFiveCharactersAchievement.OnTalkedToCharacter(__instance._characterName); + } + } +} diff --git a/NewHorizons/Patches/RemoteDialogueTriggerPatches.cs b/NewHorizons/Patches/DialoguePatches/RemoteDialogueTriggerPatches.cs similarity index 72% rename from NewHorizons/Patches/RemoteDialogueTriggerPatches.cs rename to NewHorizons/Patches/DialoguePatches/RemoteDialogueTriggerPatches.cs index f6002b05f..330e578e5 100644 --- a/NewHorizons/Patches/RemoteDialogueTriggerPatches.cs +++ b/NewHorizons/Patches/DialoguePatches/RemoteDialogueTriggerPatches.cs @@ -1,19 +1,18 @@ using HarmonyLib; -using NewHorizons.Utility; -using System; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.DialoguePatches { - /// - /// Should fix a bug where disabled a CharacterDialogueTree makes its related RemoteDialogueTriggers softlock your game - /// - [HarmonyPatch] + [HarmonyPatch(typeof(RemoteDialogueTrigger))] public static class RemoteDialogueTriggerPatches { private static bool _wasLastDialogueInactive = false; + /// + /// Should fix a bug where disabled a CharacterDialogueTree makes its related RemoteDialogueTriggers softlock your game + /// + [HarmonyPostfix] - [HarmonyPatch(typeof(RemoteDialogueTrigger), nameof(RemoteDialogueTrigger.OnTriggerEnter))] + [HarmonyPatch(nameof(RemoteDialogueTrigger.OnTriggerEnter))] public static void RemoteDialogueTrigger_OnTriggerEnter(RemoteDialogueTrigger __instance) { if (__instance._inRemoteDialogue && __instance._activeRemoteDialogue?.gameObject != null) @@ -27,7 +26,7 @@ public static void RemoteDialogueTrigger_OnTriggerEnter(RemoteDialogueTrigger __ } [HarmonyPrefix] - [HarmonyPatch(typeof(RemoteDialogueTrigger), nameof(RemoteDialogueTrigger.OnEndConversation))] + [HarmonyPatch(nameof(RemoteDialogueTrigger.OnEndConversation))] public static void RemoteDialogueTrigger_OnEndConversation(RemoteDialogueTrigger __instance) { if (__instance._inRemoteDialogue && __instance._activeRemoteDialogue != null) diff --git a/NewHorizons/Patches/AutoSlideProjectorPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/AutoSlideProjectorPatches.cs similarity index 51% rename from NewHorizons/Patches/AutoSlideProjectorPatches.cs rename to NewHorizons/Patches/EchoesOfTheEyePatches/AutoSlideProjectorPatches.cs index 9c5d5e2dd..accd6ee62 100644 --- a/NewHorizons/Patches/AutoSlideProjectorPatches.cs +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/AutoSlideProjectorPatches.cs @@ -1,12 +1,12 @@ using HarmonyLib; -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public class AutoSlideProjectorPatches +namespace NewHorizons.Patches.EchoesOfTheEyePatches +{ + [HarmonyPatch(typeof(AutoSlideProjector))] + public static class AutoSlideProjectorPatches { [HarmonyPostfix] - [HarmonyPatch(typeof(AutoSlideProjector), nameof(AutoSlideProjector.Play))] + [HarmonyPatch(nameof(AutoSlideProjector.Play))] public static void AutoSlideProjector_Play(AutoSlideProjector __instance) { __instance._slideCollectionItem.enabled = true; diff --git a/NewHorizons/Patches/CloakPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/CloakFieldControllerPatches.cs similarity index 62% rename from NewHorizons/Patches/CloakPatches.cs rename to NewHorizons/Patches/EchoesOfTheEyePatches/CloakFieldControllerPatches.cs index 2129a198d..cdb8736cd 100644 --- a/NewHorizons/Patches/CloakPatches.cs +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/CloakFieldControllerPatches.cs @@ -1,33 +1,33 @@ using HarmonyLib; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.EchoesOfTheEyePatches { - [HarmonyPatch] - public static class CloakPatches + [HarmonyPatch(typeof(CloakFieldController))] + public static class CloakFieldControllerPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(CloakFieldController), nameof(CloakFieldController.FixedUpdate))] + [HarmonyPatch(nameof(CloakFieldController.FixedUpdate))] public static bool CloakFieldController_FixedUpdate(CloakFieldController __instance) { return __instance != null && __instance._cloakSphereShape != null; } [HarmonyPostfix] - [HarmonyPatch(typeof(CloakFieldController), nameof(CloakFieldController.isPlayerInsideCloak), MethodType.Getter)] + [HarmonyPatch(nameof(CloakFieldController.isPlayerInsideCloak), MethodType.Getter)] public static void CloakFieldController_isPlayerInsideCloak(ref bool __result) { __result = __result || Components.CloakSectorController.isPlayerInside; } [HarmonyPostfix] - [HarmonyPatch(typeof(CloakFieldController), nameof(CloakFieldController.isProbeInsideCloak), MethodType.Getter)] + [HarmonyPatch(nameof(CloakFieldController.isProbeInsideCloak), MethodType.Getter)] public static void CloakFieldController_isProbeInsideCloak(ref bool __result) { __result = __result || Components.CloakSectorController.isProbeInside; } [HarmonyPostfix] - [HarmonyPatch(typeof(CloakFieldController), nameof(CloakFieldController.isShipInsideCloak), MethodType.Getter)] + [HarmonyPatch(nameof(CloakFieldController.isShipInsideCloak), MethodType.Getter)] public static void CloakFieldController_isShipInsideCloak(ref bool __result) { __result = __result || Components.CloakSectorController.isShipInside; diff --git a/NewHorizons/Patches/EchoesOfTheEyePatches/MindProjectorTriggerPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/MindProjectorTriggerPatches.cs new file mode 100644 index 000000000..eefb309b4 --- /dev/null +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/MindProjectorTriggerPatches.cs @@ -0,0 +1,47 @@ +using HarmonyLib; +using NewHorizons.Builder.Props; +using UnityEngine; + +namespace NewHorizons.Patches.EchoesOfTheEyePatches +{ + [HarmonyPatch(typeof(MindProjectorTrigger))] + public static class MindProjectorTriggerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(MindProjectorTrigger.OnTriggerVolumeEntry))] + public static bool MindProjectorTrigger_OnTriggerVolumeEntry(MindProjectorTrigger __instance, GameObject hitObj) + { + var t = hitObj.GetComponent(); + if (t != null) //(hitObj.CompareTag("PrisonerDetector")) + { + __instance._mindProjector.OnProjectionStart += t.onSlidesStart; + __instance._mindProjector.OnProjectionComplete += t.onSlidesComplete; + __instance._mindProjector.SetMindSlideCollection(t.slideCollection); + + __instance.OnBeamStartHitPrisoner.Invoke(); + __instance._mindProjector.Play(reset: true); + __instance._mindProjector.OnProjectionStart += __instance.OnProjectionStart; + __instance._mindProjector.OnProjectionComplete += __instance.OnProjectionComplete; + + Locator.GetPlayerTransform().GetComponent().LockOn(hitObj.transform, Vector3.zero); + __instance._playerLockedOn = true; + return false; + } + + return true; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(MindProjectorTrigger.OnTriggerVolumeExit))] + private static bool MindProjectorTrigger_OnTriggerVolumeExit(MindProjectorTrigger __instance, GameObject hitObj) + { + var t = hitObj.GetComponent(); + if (t != null) //(hitObj.CompareTag("PrisonerDetector")) + { + __instance._mindProjector.OnProjectionStart -= t.onSlidesStart; + __instance._mindProjector.OnProjectionComplete -= t.onSlidesComplete; + } + return true; + } + } +} diff --git a/NewHorizons/Patches/EchoesOfTheEyePatches/MindSlideProjectionPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/MindSlideProjectionPatches.cs new file mode 100644 index 000000000..b40493ab9 --- /dev/null +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/MindSlideProjectionPatches.cs @@ -0,0 +1,35 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.EchoesOfTheEyePatches +{ + [HarmonyPatch(typeof(MindSlideProjector))] + public static class MindSlideProjectionPatches + { + [HarmonyPrefix] + [HarmonyPatch(typeof(MindSlideProjector), nameof(MindSlideProjector.SetMindSlideCollection))] + private static bool MindSlideProjector_SetMindSlideCollection(MindSlideProjector __instance, MindSlideCollection mindSlideCollection) + { + if (mindSlideCollection == null) return false; + + if (__instance._mindSlideCollection == mindSlideCollection) return false; + + // Original method didn't check if old _slideCollectionItem was null. + if (__instance._slideCollectionItem != null) + { + __instance._slideCollectionItem.onSlideTextureUpdated -= __instance.OnSlideTextureUpdated; + __instance._slideCollectionItem.onPlayBeatAudio -= __instance.OnPlayBeatAudio; + } + + __instance._mindSlideCollection = mindSlideCollection; + __instance._defaultSlideDuration = mindSlideCollection.defaultSlideDuration; + + __instance._slideCollectionItem = mindSlideCollection.slideCollectionContainer; + __instance._slideCollectionItem.onSlideTextureUpdated += __instance.OnSlideTextureUpdated; + __instance._slideCollectionItem.onPlayBeatAudio += __instance.OnPlayBeatAudio; + __instance._slideCollectionItem.Initialize(); + __instance._slideCollectionItem.enabled = false; + + return false; + } + } +} diff --git a/NewHorizons/Patches/RaftPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/RaftControllerPatches.cs similarity index 55% rename from NewHorizons/Patches/RaftPatches.cs rename to NewHorizons/Patches/EchoesOfTheEyePatches/RaftControllerPatches.cs index 196885c0d..a0b40a998 100644 --- a/NewHorizons/Patches/RaftPatches.cs +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/RaftControllerPatches.cs @@ -1,12 +1,13 @@ using HarmonyLib; using UnityEngine; -namespace NewHorizons.Patches + +namespace NewHorizons.Patches.EchoesOfTheEyePatches { - [HarmonyPatch] - public static class RaftPatches + [HarmonyPatch(typeof(RaftController))] + public static class RaftControllerPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(RaftController), nameof(RaftController.FixedUpdate))] + [HarmonyPatch(nameof(RaftController.FixedUpdate))] public static bool RaftController_FixedUpdate(RaftController __instance) { // If it has a river fluid its a normal one and we don't do anything @@ -18,7 +19,7 @@ public static bool RaftController_FixedUpdate(RaftController __instance) return false; } bool playerInEffectsRange = __instance._playerInEffectsRange; - __instance._playerInEffectsRange = ((Locator.GetPlayerBody().GetPosition() - __instance._raftBody.GetPosition()).sqrMagnitude < 2500f); + __instance._playerInEffectsRange = (Locator.GetPlayerBody().GetPosition() - __instance._raftBody.GetPosition()).sqrMagnitude < 2500f; if (playerInEffectsRange && !__instance._playerInEffectsRange) { __instance._effectsController.StopAllEffects(); @@ -71,48 +72,5 @@ public static bool RaftController_FixedUpdate(RaftController __instance) return false; } - - [HarmonyReversePatch] - [HarmonyPatch(typeof(AsymmetricFluidDetector), nameof(AsymmetricFluidDetector.ManagedFixedUpdate))] - public static void AsymmetricFluidDetector_ManagedFixedUpdate(AsymmetricFluidDetector __instance) - { - // This is like doing base.FixedUpdate - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(AlignToSurfaceFluidDetector), nameof(AlignToSurfaceFluidDetector.ManagedFixedUpdate))] - public static bool AlignToSurfaceFluidDetector_ManagedFixedUpdate(AlignToSurfaceFluidDetector __instance) - { - if (__instance._alignmentFluid is not RadialFluidVolume) return true; - - // Mostly copy pasting from the AlignWithDirection class - AsymmetricFluidDetector_ManagedFixedUpdate(__instance); - - if (__instance._inAlignmentFluid) - { - // Both in world space - var currentDirection = __instance._owRigidbody.transform.up; - var alignmentDirection = (__instance.transform.position - __instance._alignmentFluid.transform.position).normalized; - var degreesToTarget = Vector3.Angle(currentDirection, alignmentDirection); - - var adjustedSlerpRate = Mathf.Clamp01(0.01f * degreesToTarget * Time.fixedDeltaTime); - - Vector3 a = OWPhysics.FromToAngularVelocity(currentDirection, alignmentDirection); - __instance._owRigidbody.AddAngularVelocityChange(a * adjustedSlerpRate); - } - - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(FluidVolume), nameof(FluidVolume.GetDepthAtPosition))] - public static bool FluidVolume_GetDepthAtPosition(FluidVolume __instance, ref float __result, Vector3 worldPosition) - { - if (__instance is not RadialFluidVolume radialFluidVolume) return true; - - Vector3 vector = radialFluidVolume.transform.InverseTransformPoint(worldPosition); - __result = Mathf.Sqrt(vector.x * vector.x + vector.z * vector.z + vector.y * vector.y) - radialFluidVolume._radius; - return false; - } } } diff --git a/NewHorizons/Patches/EchoesOfTheEyePatches/VisionTorchItemPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/VisionTorchItemPatches.cs new file mode 100644 index 000000000..d23631a55 --- /dev/null +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/VisionTorchItemPatches.cs @@ -0,0 +1,33 @@ +using HarmonyLib; +using UnityEngine; + +namespace NewHorizons.Patches.EchoesOfTheEyePatches +{ + [HarmonyPatch(typeof(VisionTorchItem))] + public static class VisionTorchItemPatches + { + // This is some dark magic + // this creates a method called base_DropItem that basically just calls OWItem.PickUpItem whenever it (VisionTorchItemPatches.base_PickUpItem) is called + [HarmonyReversePatch] + [HarmonyPatch(typeof(OWItem), nameof(OWItem.DropItem))] + private static void base_DropItem(OWItem instance, Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) { } + + + // Make the vision torch droppable. In the base game you can only drop it if you're in the dream world. + [HarmonyPrefix] + [HarmonyPatch(nameof(VisionTorchItem.DropItem))] + public static bool VisionTorchItem_DropItem(VisionTorchItem __instance, Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) + { + if (!Locator.GetDreamWorldController().IsInDream()) + { + base_DropItem(__instance, position, normal, parent, sector, customDropTarget); + } + + if (__instance._wasProjecting) __instance._mindProjectorTrigger.SetProjectorActive(false); + + __instance.gameObject.GetComponent().enabled = true; + + return true; + } + } +} diff --git a/NewHorizons/Patches/EyeOfTheUniversePatches.cs b/NewHorizons/Patches/EyeOfTheUniversePatches.cs deleted file mode 100644 index df4ba1e74..000000000 --- a/NewHorizons/Patches/EyeOfTheUniversePatches.cs +++ /dev/null @@ -1,53 +0,0 @@ -using HarmonyLib; -using UnityEngine; -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public static class EyeOfTheUniversePatches - { - // Funny eye of the universe stuff - - private static void OnLoadScene(OWScene scene) - { - if (scene == OWScene.SolarSystem && !Main.Instance.IsWarpingBackToEye) - { - PlayerData.SaveEyeCompletion(); - - // Switch to default just in case another mod warps back. - if (Main.Instance.CurrentStarSystem == "EyeOfTheUniverse") Main.Instance._currentStarSystem = Main.Instance.DefaultStarSystem; - } - // Switch to eye just in case another mod warps there. - else if (scene == OWScene.EyeOfTheUniverse) Main.Instance._currentStarSystem = "EyeOfTheUniverse"; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(LoadManager), nameof(LoadManager.LoadSceneImmediate))] - public static void LoadManager_LoadSceneImmediate(OWScene scene) => OnLoadScene(scene); - - [HarmonyPrefix] - [HarmonyPatch(typeof(LoadManager), nameof(LoadManager.StartAsyncSceneLoad))] - public static void LoadManager_StartAsyncSceneLoad(OWScene scene) => OnLoadScene(scene); - - [HarmonyPrefix] - [HarmonyPatch(typeof(SubmitActionLoadScene), nameof(SubmitActionLoadScene.ConfirmSubmit))] - public static void SubmitActionLoadScene_ConfirmSubmit(SubmitActionLoadScene __instance) - { - // Title screen can warp you to eye and cause problems. - if (__instance._sceneToLoad == SubmitActionLoadScene.LoadableScenes.EYE) - { - Utility.Logger.LogWarning("Warping to solar system and then back to eye"); - Main.Instance.IsWarpingBackToEye = true; - __instance._sceneToLoad = SubmitActionLoadScene.LoadableScenes.GAME; - } - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(EyeVortexTrigger), nameof(EyeVortexTrigger.OnEnterVortex))] - public static void EyeVortexTrigger_OnEnterVortex(EyeVortexTrigger __instance, GameObject hitObj) - { - if (!hitObj.CompareTag("PlayerDetector")) return; - __instance._tunnelObject.SetActive(true); - } - - } -} diff --git a/NewHorizons/Patches/EyeScenePatches/EyeVortexTriggerPatches.cs b/NewHorizons/Patches/EyeScenePatches/EyeVortexTriggerPatches.cs new file mode 100644 index 000000000..d99e33f04 --- /dev/null +++ b/NewHorizons/Patches/EyeScenePatches/EyeVortexTriggerPatches.cs @@ -0,0 +1,17 @@ +using HarmonyLib; +using UnityEngine; + +namespace NewHorizons.Patches.EyeScenePatches +{ + [HarmonyPatch(typeof(EyeVortexTrigger))] + public static class EyeVortexTriggerPatches + { + [HarmonyPostfix] + [HarmonyPatch(nameof(EyeVortexTrigger.OnEnterVortex))] + public static void EyeVortexTrigger_OnEnterVortex(EyeVortexTrigger __instance, GameObject hitObj) + { + if (!hitObj.CompareTag("PlayerDetector")) return; + __instance._tunnelObject.SetActive(true); + } + } +} diff --git a/NewHorizons/Patches/EyeScenePatches/LoadManagerPatches.cs b/NewHorizons/Patches/EyeScenePatches/LoadManagerPatches.cs new file mode 100644 index 000000000..2bf53abfa --- /dev/null +++ b/NewHorizons/Patches/EyeScenePatches/LoadManagerPatches.cs @@ -0,0 +1,29 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.EyeScenePatches +{ + [HarmonyPatch(typeof(LoadManager))] + public static class LoadManagerPatches + { + private static void OnLoadScene(OWScene scene) + { + if (scene == OWScene.SolarSystem && !Main.Instance.IsWarpingBackToEye) + { + PlayerData.SaveEyeCompletion(); + + // Switch to default just in case another mod warps back. + if (Main.Instance.CurrentStarSystem == "EyeOfTheUniverse") Main.Instance._currentStarSystem = Main.Instance.DefaultStarSystem; + } + // Switch to eye just in case another mod warps there. + else if (scene == OWScene.EyeOfTheUniverse) Main.Instance._currentStarSystem = "EyeOfTheUniverse"; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(LoadManager.LoadSceneImmediate))] + public static void LoadManager_LoadSceneImmediate(OWScene scene) => OnLoadScene(scene); + + [HarmonyPrefix] + [HarmonyPatch(nameof(LoadManager.StartAsyncSceneLoad))] + public static void LoadManager_StartAsyncSceneLoad(OWScene scene) => OnLoadScene(scene); + } +} diff --git a/NewHorizons/Patches/EyeScenePatches/SubmitActionLoadScenePatches.cs b/NewHorizons/Patches/EyeScenePatches/SubmitActionLoadScenePatches.cs new file mode 100644 index 000000000..33bdb2362 --- /dev/null +++ b/NewHorizons/Patches/EyeScenePatches/SubmitActionLoadScenePatches.cs @@ -0,0 +1,21 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.EyeScenePatches +{ + [HarmonyPatch(typeof(SubmitActionLoadScene))] + public static class SubmitActionLoadScenePatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(SubmitActionLoadScene.ConfirmSubmit))] + public static void SubmitActionLoadScene_ConfirmSubmit(SubmitActionLoadScene __instance) + { + // Title screen can warp you to eye and cause problems. + if (__instance._sceneToLoad == SubmitActionLoadScene.LoadableScenes.EYE) + { + Utility.Logger.LogWarning("Warping to solar system and then back to eye"); + Main.Instance.IsWarpingBackToEye = true; + __instance._sceneToLoad = SubmitActionLoadScene.LoadableScenes.GAME; + } + } + } +} diff --git a/NewHorizons/Patches/HUDPatches.cs b/NewHorizons/Patches/HUDPatches.cs deleted file mode 100644 index bb9a1c4fc..000000000 --- a/NewHorizons/Patches/HUDPatches.cs +++ /dev/null @@ -1,124 +0,0 @@ -using HarmonyLib; -using NewHorizons.Handlers; - -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public static class HUDPatches - { - [HarmonyPostfix] - [HarmonyPatch(typeof(HUDMarker), nameof(HUDMarker.Awake))] - public static void HUDMarker_Awake(HUDMarker __instance) - { - GlobalMessenger.AddListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility); - GlobalMessenger.AddListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility); - GlobalMessenger.AddListener("PlayerEnterCloakField", __instance.OnPlayerEnterCloakField); - GlobalMessenger.AddListener("PlayerExitCloakField", __instance.OnPlayerExitCloakField); - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(HUDMarker), nameof(HUDMarker.OnDestroy))] - public static void HUDMarker_OnDestroy(HUDMarker __instance) - { - GlobalMessenger.RemoveListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility); - GlobalMessenger.RemoveListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility); - GlobalMessenger.RemoveListener("PlayerEnterCloakField", __instance.OnPlayerEnterCloakField); - GlobalMessenger.RemoveListener("PlayerExitCloakField", __instance.OnPlayerExitCloakField); - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(ProbeHUDMarker), nameof(ProbeHUDMarker.Awake))] - public static void ProbeHUDMarker_Awake(ProbeHUDMarker __instance) - { - GlobalMessenger.AddListener("ProbeEnterCloakField", __instance.RefreshOwnVisibility); - GlobalMessenger.AddListener("ProbeExitCloakField", __instance.RefreshOwnVisibility); - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(ProbeHUDMarker), nameof(ProbeHUDMarker.OnDestroy))] - public static void ProbeHUDMarker_OnDestroy(ProbeHUDMarker __instance) - { - GlobalMessenger.RemoveListener("ProbeEnterCloakField", __instance.RefreshOwnVisibility); - GlobalMessenger.RemoveListener("ProbeExitCloakField", __instance.RefreshOwnVisibility); - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(ShipHUDMarker), nameof(ShipHUDMarker.Awake))] - public static void ShipHUDMarker_Awake(ShipHUDMarker __instance) - { - GlobalMessenger.AddListener("ShipEnterCloakField", __instance.RefreshOwnVisibility); - GlobalMessenger.AddListener("ShipExitCloakField", __instance.RefreshOwnVisibility); - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(ShipHUDMarker), nameof(ShipHUDMarker.OnDestroy))] - public static void ShipHUDMarker_OnDestroy(ShipHUDMarker __instance) - { - GlobalMessenger.RemoveListener("ShipEnterCloakField", __instance.RefreshOwnVisibility); - GlobalMessenger.RemoveListener("ShipExitCloakField", __instance.RefreshOwnVisibility); - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ProbeHUDMarker), nameof(ProbeHUDMarker.RefreshOwnVisibility))] - public static bool ProbeHUDMarker_RefreshOwnVisibility(ProbeHUDMarker __instance) - { - bool insideEYE = Locator.GetEyeStateManager() != null && Locator.GetEyeStateManager().IsInsideTheEye(); - bool insideQM = __instance._quantumMoon != null && (__instance._quantumMoon.IsPlayerInside() || __instance._quantumMoon.IsProbeInside()); - bool insideRW = Locator.GetRingWorldController() != null && Locator.GetRingWorldController().isPlayerInside == Locator.GetRingWorldController().isProbeInside; - bool insideIP = Locator.GetCloakFieldController() != null && Locator.GetCloakFieldController().isPlayerInsideCloak == Locator.GetCloakFieldController().isProbeInsideCloak; - bool insideCloak = Components.CloakSectorController.isPlayerInside == Components.CloakSectorController.isProbeInside; - bool sameInterference = InterferenceHandler.IsPlayerSameAsProbe(); - bool isActive = __instance.gameObject.activeInHierarchy || __instance._isTLCDuplicate; - - __instance._isVisible = isActive && !insideEYE && !insideQM && !__instance._translatorEquipped && !__instance._inConversation && __instance._launched && (__instance._isWearingHelmet || __instance._atFlightConsole) && insideRW && insideIP && insideCloak && sameInterference; - - if (__instance._canvasMarker != null) __instance._canvasMarker.SetVisibility(__instance._isVisible); - - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ShipHUDMarker), nameof(ShipHUDMarker.RefreshOwnVisibility))] - public static bool ShipHUDMarker_RefreshOwnVisibility(ShipHUDMarker __instance) - { - bool insideEYE = Locator.GetEyeStateManager() != null && Locator.GetEyeStateManager().IsInsideTheEye(); - bool insideQM = __instance._quantumMoon != null && (__instance._quantumMoon.IsPlayerInside() || __instance._quantumMoon.IsShipInside()); - bool insideRW = Locator.GetRingWorldController() != null && Locator.GetRingWorldController().isPlayerInside; - bool insideIP = Locator.GetCloakFieldController() != null && Locator.GetCloakFieldController().isPlayerInsideCloak == Locator.GetCloakFieldController().isShipInsideCloak; - bool insideCloak = Components.CloakSectorController.isPlayerInside == Components.CloakSectorController.isShipInside; - bool sameInterference = InterferenceHandler.IsPlayerSameAsShip(); - - __instance._isVisible = !insideEYE && !insideQM && !insideRW && !__instance._translatorEquipped && !__instance._inConversation && !__instance._shipDestroyed && !__instance._playerInShip && PlayerState.HasPlayerEnteredShip() && __instance._isWearingHelmet && insideIP && insideCloak && sameInterference; - - if (__instance._canvasMarker != null) __instance._canvasMarker.SetVisibility(__instance._isVisible); - - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ShipLogEntryHUDMarker), nameof(ShipLogEntryHUDMarker.RefreshOwnVisibility))] - public static bool ShipLogEntryHUDMarker_RefreshOwnVisibility(ShipLogEntryHUDMarker __instance) - { - bool hasEntryLocation = ShipLogEntryHUDMarker.s_entryLocation != null; - bool insideEYE = Locator.GetEyeStateManager() != null && Locator.GetEyeStateManager().IsInsideTheEye(); - bool insideQM = __instance._quantumMoon != null && __instance._quantumMoon.IsPlayerInside(); - bool insideRW = Locator.GetRingWorldController() != null && Locator.GetRingWorldController().isPlayerInside && ShipLogEntryHUDMarker.s_entryLocationID == "IP_RING_WORLD"; - bool insideIP = (hasEntryLocation && ShipLogEntryHUDMarker.s_entryLocation.IsWithinCloakField()) || !(Locator.GetCloakFieldController() != null && Locator.GetCloakFieldController().isPlayerInsideCloak); - bool insideCloak = (hasEntryLocation && ShipLogEntryHUDMarker.s_entryLocation.IsWithinCloakField()) || !Components.CloakSectorController.isPlayerInside; - - __instance._isVisible = (!insideEYE && !insideQM && !insideRW && !__instance._translatorEquipped && !__instance._inConversation && hasEntryLocation && (__instance._isWearingHelmet || __instance._atFlightConsole) && insideIP && insideCloak); - - if (__instance._canvasMarker != null) __instance._canvasMarker.SetVisibility(__instance._isVisible); - - return false; - } - - - [HarmonyPostfix] - [HarmonyPatch(typeof(ProbeCamera), nameof(ProbeCamera.HasInterference))] - public static void ProbeCamera_HasInterference(ProbeCamera __instance, ref bool __result) - { - __result = __result || (__instance._id != ProbeCamera.ID.PreLaunch && (Components.CloakSectorController.isPlayerInside != Components.CloakSectorController.isProbeInside || !InterferenceHandler.IsPlayerSameAsProbe())); - } - } -} diff --git a/NewHorizons/Patches/HUDPatches/HUDMarkerPatches.cs b/NewHorizons/Patches/HUDPatches/HUDMarkerPatches.cs new file mode 100644 index 000000000..f82459ac6 --- /dev/null +++ b/NewHorizons/Patches/HUDPatches/HUDMarkerPatches.cs @@ -0,0 +1,28 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.HUDPatches +{ + [HarmonyPatch(typeof(HUDMarker))] + public static class HUDMarkerPatches + { + [HarmonyPostfix] + [HarmonyPatch(nameof(HUDMarker.Awake))] + public static void HUDMarker_Awake(HUDMarker __instance) + { + GlobalMessenger.AddListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility); + GlobalMessenger.AddListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility); + GlobalMessenger.AddListener("PlayerEnterCloakField", __instance.OnPlayerEnterCloakField); + GlobalMessenger.AddListener("PlayerExitCloakField", __instance.OnPlayerExitCloakField); + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(HUDMarker.OnDestroy))] + public static void HUDMarker_OnDestroy(HUDMarker __instance) + { + GlobalMessenger.RemoveListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility); + GlobalMessenger.RemoveListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility); + GlobalMessenger.RemoveListener("PlayerEnterCloakField", __instance.OnPlayerEnterCloakField); + GlobalMessenger.RemoveListener("PlayerExitCloakField", __instance.OnPlayerExitCloakField); + } + } +} diff --git a/NewHorizons/Patches/HUDPatches/ProbeHUDMarkerPatches.cs b/NewHorizons/Patches/HUDPatches/ProbeHUDMarkerPatches.cs new file mode 100644 index 000000000..dc464f3c8 --- /dev/null +++ b/NewHorizons/Patches/HUDPatches/ProbeHUDMarkerPatches.cs @@ -0,0 +1,44 @@ +using HarmonyLib; +using NewHorizons.Handlers; + +namespace NewHorizons.Patches.HUDPatches +{ + [HarmonyPatch(typeof(ProbeHUDMarker))] + public static class ProbeHUDMarkerPatches + { + [HarmonyPostfix] + [HarmonyPatch(nameof(ProbeHUDMarker.Awake))] + public static void ProbeHUDMarker_Awake(ProbeHUDMarker __instance) + { + GlobalMessenger.AddListener("ProbeEnterCloakField", __instance.RefreshOwnVisibility); + GlobalMessenger.AddListener("ProbeExitCloakField", __instance.RefreshOwnVisibility); + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(ProbeHUDMarker.OnDestroy))] + public static void ProbeHUDMarker_OnDestroy(ProbeHUDMarker __instance) + { + GlobalMessenger.RemoveListener("ProbeEnterCloakField", __instance.RefreshOwnVisibility); + GlobalMessenger.RemoveListener("ProbeExitCloakField", __instance.RefreshOwnVisibility); + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(ProbeHUDMarker.RefreshOwnVisibility))] + public static bool ProbeHUDMarker_RefreshOwnVisibility(ProbeHUDMarker __instance) + { + bool insideEYE = Locator.GetEyeStateManager() != null && Locator.GetEyeStateManager().IsInsideTheEye(); + bool insideQM = __instance._quantumMoon != null && (__instance._quantumMoon.IsPlayerInside() || __instance._quantumMoon.IsProbeInside()); + bool insideRW = Locator.GetRingWorldController() != null && Locator.GetRingWorldController().isPlayerInside == Locator.GetRingWorldController().isProbeInside; + bool insideIP = Locator.GetCloakFieldController() != null && Locator.GetCloakFieldController().isPlayerInsideCloak == Locator.GetCloakFieldController().isProbeInsideCloak; + bool insideCloak = Components.CloakSectorController.isPlayerInside == Components.CloakSectorController.isProbeInside; + bool sameInterference = InterferenceHandler.IsPlayerSameAsProbe(); + bool isActive = __instance.gameObject.activeInHierarchy || __instance._isTLCDuplicate; + + __instance._isVisible = isActive && !insideEYE && !insideQM && !__instance._translatorEquipped && !__instance._inConversation && __instance._launched && (__instance._isWearingHelmet || __instance._atFlightConsole) && insideRW && insideIP && insideCloak && sameInterference; + + if (__instance._canvasMarker != null) __instance._canvasMarker.SetVisibility(__instance._isVisible); + + return false; + } + } +} diff --git a/NewHorizons/Patches/HUDPatches/ShipHUDMarkerPatches.cs b/NewHorizons/Patches/HUDPatches/ShipHUDMarkerPatches.cs new file mode 100644 index 000000000..c44f46dc6 --- /dev/null +++ b/NewHorizons/Patches/HUDPatches/ShipHUDMarkerPatches.cs @@ -0,0 +1,43 @@ +using HarmonyLib; +using NewHorizons.Handlers; + +namespace NewHorizons.Patches.HUDPatches +{ + [HarmonyPatch(typeof(ShipHUDMarker))] + public static class ShipHUDMarkerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(ShipHUDMarker.RefreshOwnVisibility))] + public static bool ShipHUDMarker_RefreshOwnVisibility(ShipHUDMarker __instance) + { + bool insideEYE = Locator.GetEyeStateManager() != null && Locator.GetEyeStateManager().IsInsideTheEye(); + bool insideQM = __instance._quantumMoon != null && (__instance._quantumMoon.IsPlayerInside() || __instance._quantumMoon.IsShipInside()); + bool insideRW = Locator.GetRingWorldController() != null && Locator.GetRingWorldController().isPlayerInside; + bool insideIP = Locator.GetCloakFieldController() != null && Locator.GetCloakFieldController().isPlayerInsideCloak == Locator.GetCloakFieldController().isShipInsideCloak; + bool insideCloak = Components.CloakSectorController.isPlayerInside == Components.CloakSectorController.isShipInside; + bool sameInterference = InterferenceHandler.IsPlayerSameAsShip(); + + __instance._isVisible = !insideEYE && !insideQM && !insideRW && !__instance._translatorEquipped && !__instance._inConversation && !__instance._shipDestroyed && !__instance._playerInShip && PlayerState.HasPlayerEnteredShip() && __instance._isWearingHelmet && insideIP && insideCloak && sameInterference; + + if (__instance._canvasMarker != null) __instance._canvasMarker.SetVisibility(__instance._isVisible); + + return false; + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(ShipHUDMarker.OnDestroy))] + public static void ShipHUDMarker_OnDestroy(ShipHUDMarker __instance) + { + GlobalMessenger.RemoveListener("ShipEnterCloakField", __instance.RefreshOwnVisibility); + GlobalMessenger.RemoveListener("ShipExitCloakField", __instance.RefreshOwnVisibility); + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(ShipHUDMarker.Awake))] + public static void ShipHUDMarker_Awake(ShipHUDMarker __instance) + { + GlobalMessenger.AddListener("ShipEnterCloakField", __instance.RefreshOwnVisibility); + GlobalMessenger.AddListener("ShipExitCloakField", __instance.RefreshOwnVisibility); + } + } +} diff --git a/NewHorizons/Patches/HUDPatches/ShipLogEntryHUDMarkerPatches.cs b/NewHorizons/Patches/HUDPatches/ShipLogEntryHUDMarkerPatches.cs new file mode 100644 index 000000000..75800339d --- /dev/null +++ b/NewHorizons/Patches/HUDPatches/ShipLogEntryHUDMarkerPatches.cs @@ -0,0 +1,26 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.HUDPatches +{ + [HarmonyPatch(typeof(ShipLogEntryHUDMarker))] + public static class ShipLogEntryHUDMarkerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(ShipLogEntryHUDMarker.RefreshOwnVisibility))] + public static bool ShipLogEntryHUDMarker_RefreshOwnVisibility(ShipLogEntryHUDMarker __instance) + { + bool hasEntryLocation = ShipLogEntryHUDMarker.s_entryLocation != null; + bool insideEYE = Locator.GetEyeStateManager() != null && Locator.GetEyeStateManager().IsInsideTheEye(); + bool insideQM = __instance._quantumMoon != null && __instance._quantumMoon.IsPlayerInside(); + bool insideRW = Locator.GetRingWorldController() != null && Locator.GetRingWorldController().isPlayerInside && ShipLogEntryHUDMarker.s_entryLocationID == "IP_RING_WORLD"; + bool insideIP = hasEntryLocation && ShipLogEntryHUDMarker.s_entryLocation.IsWithinCloakField() || !(Locator.GetCloakFieldController() != null && Locator.GetCloakFieldController().isPlayerInsideCloak); + bool insideCloak = hasEntryLocation && ShipLogEntryHUDMarker.s_entryLocation.IsWithinCloakField() || !Components.CloakSectorController.isPlayerInside; + + __instance._isVisible = !insideEYE && !insideQM && !insideRW && !__instance._translatorEquipped && !__instance._inConversation && hasEntryLocation && (__instance._isWearingHelmet || __instance._atFlightConsole) && insideIP && insideCloak; + + if (__instance._canvasMarker != null) __instance._canvasMarker.SetVisibility(__instance._isVisible); + + return false; + } + } +} diff --git a/NewHorizons/Patches/LocatorPatches.cs b/NewHorizons/Patches/LocatorPatches.cs index a9a901e08..b1d32bd8c 100644 --- a/NewHorizons/Patches/LocatorPatches.cs +++ b/NewHorizons/Patches/LocatorPatches.cs @@ -2,7 +2,7 @@ namespace NewHorizons.Patches { - [HarmonyPatch] + [HarmonyPatch(typeof(Locator))] public static class LocatorPatches { public static AstroObject _attlerock; @@ -13,7 +13,7 @@ public static class LocatorPatches public static AstroObject _sunStation; [HarmonyPrefix] - [HarmonyPatch(typeof(Locator), nameof(Locator.RegisterCloakFieldController))] + [HarmonyPatch(nameof(Locator.RegisterCloakFieldController))] public static bool Locator_RegisterCloakFieldController() { return Locator._cloakFieldController == null; @@ -22,7 +22,7 @@ public static bool Locator_RegisterCloakFieldController() // Locator Fixes // Vanilla doesn't register these AstroObjects for some reason. So here is a fix. [HarmonyPrefix] - [HarmonyPatch(typeof(Locator), nameof(Locator.GetAstroObject))] + [HarmonyPatch(nameof(Locator.GetAstroObject))] public static bool Locator_GetAstroObject(AstroObject.Name astroObjectName, ref AstroObject __result) { switch (astroObjectName) @@ -52,7 +52,7 @@ public static bool Locator_GetAstroObject(AstroObject.Name astroObjectName, ref } [HarmonyPrefix] - [HarmonyPatch(typeof(Locator), nameof(Locator.RegisterAstroObject))] + [HarmonyPatch(nameof(Locator.RegisterAstroObject))] public static bool Locator_RegisterAstroObject(AstroObject astroObject) { if (astroObject.GetAstroObjectName() == AstroObject.Name.None) return false; @@ -98,7 +98,7 @@ public static bool Locator_RegisterAstroObject(AstroObject astroObject) } [HarmonyPostfix] - [HarmonyPatch(typeof(Locator), nameof(Locator.ClearReferences))] + [HarmonyPatch(nameof(Locator.ClearReferences))] public static void Locator_ClearReferences() { _attlerock = null; diff --git a/NewHorizons/Patches/MapPatches/CanvasMapMarkerPatches.cs b/NewHorizons/Patches/MapPatches/CanvasMapMarkerPatches.cs new file mode 100644 index 000000000..8339d26eb --- /dev/null +++ b/NewHorizons/Patches/MapPatches/CanvasMapMarkerPatches.cs @@ -0,0 +1,19 @@ +using HarmonyLib; +using NewHorizons.Handlers; +using System; +using UnityEngine; + +namespace NewHorizons.Patches.MapPatches +{ + [HarmonyPatch(typeof(CanvasMapMarker))] + public static class CanvasMapMarkerPatches + { + [HarmonyPostfix] + [HarmonyPatch(nameof(CanvasMapMarker.Init), new Type[] { typeof(Canvas), typeof(Transform), typeof(string) })] + [HarmonyPatch(nameof(CanvasMapMarker.SetLabel))] + public static void CanvasMapMarker_LocalizeLabel(CanvasMapMarker __instance) + { + __instance._label = TranslationHandler.GetTranslation(__instance._label, TranslationHandler.TextType.UI); + } + } +} diff --git a/NewHorizons/Patches/MapControllerPatches.cs b/NewHorizons/Patches/MapPatches/MapControllerPatches.cs similarity index 64% rename from NewHorizons/Patches/MapControllerPatches.cs rename to NewHorizons/Patches/MapPatches/MapControllerPatches.cs index 3c13673e1..c17fba0f7 100644 --- a/NewHorizons/Patches/MapControllerPatches.cs +++ b/NewHorizons/Patches/MapPatches/MapControllerPatches.cs @@ -2,13 +2,13 @@ using UnityEngine; using UnityEngine.SceneManagement; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.MapPatches { - [HarmonyPatch] + [HarmonyPatch(typeof(MapController))] public static class MapControllerPatches { [HarmonyPostfix] - [HarmonyPatch(typeof(MapController), nameof(MapController.Awake))] + [HarmonyPatch(nameof(MapController.Awake))] public static void MapController_Awake(MapController __instance) { __instance._maxPanDistance = Mathf.Max(__instance._maxPanDistance, Main.FurthestOrbit * 1.5f); @@ -19,14 +19,15 @@ public static void MapController_Awake(MapController __instance) } [HarmonyPostfix] - [HarmonyPatch(typeof(MapController), nameof(MapController.OnTargetReferenceFrame))] - public static void MapController_OnTargetReferenceFrame(MapController __instance, ReferenceFrame __0) + [HarmonyPatch(nameof(MapController.OnTargetReferenceFrame))] + public static void MapController_OnTargetReferenceFrame(MapController __instance, ReferenceFrame referenceFrame) { + // Locked onto map satellite just means it will move vertically up from the plane of the solar system __instance._isLockedOntoMapSatellite = true; } [HarmonyPrefix] - [HarmonyPatch(typeof(MapController), nameof(MapController.MapInoperable))] + [HarmonyPatch(nameof(MapController.MapInoperable))] public static bool MapController_MapInoperable(MapController __instance, ref bool __result) { if (SceneManager.GetActiveScene().name != "SolarSystem") return true; @@ -44,12 +45,5 @@ public static bool MapController_MapInoperable(MapController __instance, ref boo return true; } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ReferenceFrameTracker), nameof(ReferenceFrameTracker.UntargetReferenceFrame), new System.Type[] { typeof(bool) })] - public static bool ReferenceFrameTracker_UntargetReferenceFrame(ReferenceFrameTracker __instance, bool playAudio) - { - return __instance != null && __instance._hasTarget && __instance._currentReferenceFrame != null; - } } } diff --git a/NewHorizons/Patches/TranslationPatches.cs b/NewHorizons/Patches/MapPatches/ReferenceFramePatches.cs similarity index 50% rename from NewHorizons/Patches/TranslationPatches.cs rename to NewHorizons/Patches/MapPatches/ReferenceFramePatches.cs index c6ea4fc5c..a9efb8b1d 100644 --- a/NewHorizons/Patches/TranslationPatches.cs +++ b/NewHorizons/Patches/MapPatches/ReferenceFramePatches.cs @@ -1,15 +1,14 @@ using HarmonyLib; using NewHorizons.Components.Orbital; using NewHorizons.Handlers; -using System; -using UnityEngine; -namespace NewHorizons.Patches + +namespace NewHorizons.Patches.MapPatches { - [HarmonyPatch] - public static class TranslationPatches + [HarmonyPatch(typeof(ReferenceFrame))] + public static class ReferenceFramePatches { [HarmonyPrefix] - [HarmonyPatch(typeof(ReferenceFrame), nameof(ReferenceFrame.GetHUDDisplayName))] + [HarmonyPatch(nameof(ReferenceFrame.GetHUDDisplayName))] public static bool ReferenceFrame_GetHUDDisplayName(ReferenceFrame __instance, ref string __result) { var ao = __instance.GetAstroObject(); @@ -35,19 +34,5 @@ public static bool ReferenceFrame_GetHUDDisplayName(ReferenceFrame __instance, r return false; } - - [HarmonyPostfix] - [HarmonyPatch(typeof(CanvasMapMarker), nameof(CanvasMapMarker.Init), new Type[] { typeof(Canvas), typeof(Transform), typeof(string) })] - public static void CanvasMapMarker_Init(CanvasMapMarker __instance) - { - __instance._label = TranslationHandler.GetTranslation(__instance._label, TranslationHandler.TextType.UI); - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(CanvasMapMarker), nameof(CanvasMapMarker.SetLabel))] - public static void CanvasMapMarker_SetLabel(CanvasMapMarker __instance) - { - __instance._label = TranslationHandler.GetTranslation(__instance._label, TranslationHandler.TextType.UI); - } } } diff --git a/NewHorizons/Patches/MapPatches/ReferenceFrameTrackerPatches.cs b/NewHorizons/Patches/MapPatches/ReferenceFrameTrackerPatches.cs new file mode 100644 index 000000000..8184ef787 --- /dev/null +++ b/NewHorizons/Patches/MapPatches/ReferenceFrameTrackerPatches.cs @@ -0,0 +1,15 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.MapPatches +{ + [HarmonyPatch(typeof(ReferenceFrameTracker))] + public static class ReferenceFrameTrackerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(ReferenceFrameTracker.UntargetReferenceFrame), new System.Type[] { typeof(bool) })] + public static bool ReferenceFrameTracker_UntargetReferenceFrame(ReferenceFrameTracker __instance, bool playAudio) + { + return __instance != null && __instance._hasTarget && __instance._currentReferenceFrame != null; + } + } +} diff --git a/NewHorizons/Patches/MeteorPatches.cs b/NewHorizons/Patches/MeteorControllerPatches.cs similarity index 60% rename from NewHorizons/Patches/MeteorPatches.cs rename to NewHorizons/Patches/MeteorControllerPatches.cs index 31eb73fa9..4c080de62 100644 --- a/NewHorizons/Patches/MeteorPatches.cs +++ b/NewHorizons/Patches/MeteorControllerPatches.cs @@ -2,14 +2,15 @@ namespace NewHorizons.Patches { - [HarmonyPatch] - public static class MeteorPatches + [HarmonyPatch(typeof(MeteorController))] + public static class MeteorControllerPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(MeteorController), nameof(MeteorController.Suspend), new System.Type[0])] + [HarmonyPatch(nameof(MeteorController.Suspend), new System.Type[0])] public static void MeteorController_Suspend(MeteorController __instance) { // Meteors launch inactive because of prefab. So let's fix that. + // how tf does this work __instance.gameObject.SetActive(true); } } diff --git a/NewHorizons/Patches/PlayerPatches/PlayerCameraControllerPatches.cs b/NewHorizons/Patches/PlayerPatches/PlayerCameraControllerPatches.cs new file mode 100644 index 000000000..12ae0e8cb --- /dev/null +++ b/NewHorizons/Patches/PlayerPatches/PlayerCameraControllerPatches.cs @@ -0,0 +1,28 @@ +using HarmonyLib; +using NewHorizons.Utility.OWMLUtilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.Patches.PlayerPatches +{ + [HarmonyPatch(typeof(PlayerCameraController))] + public static class PlayerCameraControllerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(PlayerCameraController.SnapToDegreesOverSeconds))] + public static bool PlayerCameraController_SnapToDegreesOverSeconds(PlayerCameraController __instance, float targetX, float targetY, float duration, bool smoothStep) + { + // AlignPlayerWithForce.OnSuitUp snaps the camera to center, but it never unsnaps because duration == 0f + if (duration <= 0f) + { + __instance._degreesX = targetX; + __instance._degreesY = targetY; + return false; + } + return true; + } + } +} diff --git a/NewHorizons/Patches/PlayerDataPatches.cs b/NewHorizons/Patches/PlayerPatches/PlayerDataPatches.cs similarity index 50% rename from NewHorizons/Patches/PlayerDataPatches.cs rename to NewHorizons/Patches/PlayerPatches/PlayerDataPatches.cs index 7c4b3fc6f..fc170a1ab 100644 --- a/NewHorizons/Patches/PlayerDataPatches.cs +++ b/NewHorizons/Patches/PlayerPatches/PlayerDataPatches.cs @@ -1,25 +1,24 @@ using HarmonyLib; -using NewHorizons.OtherMods.AchievementsPlus; -using NewHorizons.OtherMods.AchievementsPlus.NH; using NewHorizons.Builder.Props; using NewHorizons.External; using NewHorizons.Handlers; +using NewHorizons.OtherMods.AchievementsPlus; +using NewHorizons.OtherMods.AchievementsPlus.NH; +using NewHorizons.Utility; using System.Collections.Generic; using System.Linq; -using NewHorizons.Utility; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.PlayerPatches { - [HarmonyPatch] + [HarmonyPatch(typeof(PlayerData))] public static class PlayerDataPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(PlayerData), nameof(PlayerData.KnowsFrequency))] - public static bool OnPlayerDataKnowsFrequency(SignalFrequency __0, ref bool __result) + [HarmonyPatch(nameof(PlayerData.KnowsFrequency))] + public static bool PlayerData_KnowsFrequency(SignalFrequency frequency, ref bool __result) { - var freqString = SignalBuilder.GetCustomFrequencyName(__0); - - if (freqString != null && freqString != "") + var freqString = SignalBuilder.GetCustomFrequencyName(frequency); + if (!string.IsNullOrEmpty(freqString)) { __result = NewHorizonsData.KnowsFrequency(freqString); return false; @@ -28,11 +27,11 @@ public static bool OnPlayerDataKnowsFrequency(SignalFrequency __0, ref bool __re } [HarmonyPrefix] - [HarmonyPatch(typeof(PlayerData), nameof(PlayerData.LearnFrequency))] - public static bool OnPlayerDataLearnFrequency(SignalFrequency __0) + [HarmonyPatch(nameof(PlayerData.LearnFrequency))] + public static bool PlayerData_LearnFrequency(SignalFrequency frequency) { - var freqString = SignalBuilder.GetCustomFrequencyName(__0); - if (freqString != null && freqString != "") + var freqString = SignalBuilder.GetCustomFrequencyName(frequency); + if (!string.IsNullOrEmpty(freqString)) { NewHorizonsData.LearnFrequency(freqString); NewFrequencyAchievement.Earn(); @@ -42,11 +41,11 @@ public static bool OnPlayerDataLearnFrequency(SignalFrequency __0) } [HarmonyPrefix] - [HarmonyPatch(typeof(PlayerData), nameof(PlayerData.KnowsSignal))] - public static bool OnPlayerDataKnowsSignal(SignalName __0, ref bool __result) + [HarmonyPatch(nameof(PlayerData.KnowsSignal))] + public static bool PlayerData_KnowsSignal(SignalName signalName, ref bool __result) { - var customSignalName = SignalBuilder.GetCustomSignalName(__0); - if (customSignalName != null) + var customSignalName = SignalBuilder.GetCustomSignalName(signalName); + if (!string.IsNullOrEmpty(customSignalName)) { __result = NewHorizonsData.KnowsSignal(customSignalName); return false; @@ -55,13 +54,13 @@ public static bool OnPlayerDataKnowsSignal(SignalName __0, ref bool __result) } [HarmonyPrefix] - [HarmonyPatch(typeof(PlayerData), nameof(PlayerData.LearnSignal))] - public static bool OnPlayerDataLearnSignal(SignalName __0) + [HarmonyPatch(nameof(PlayerData.LearnSignal))] + public static bool PlayerData_LearnSignal(SignalName signalName) { - var customSignalName = SignalBuilder.GetCustomSignalName(__0); - if (customSignalName != null) + var customSignalName = SignalBuilder.GetCustomSignalName(signalName); + if (!string.IsNullOrEmpty(customSignalName)) { - if (!NewHorizonsData.KnowsSignal(customSignalName)) + if (!NewHorizonsData.KnowsSignal(customSignalName)) { NewHorizonsData.LearnSignal(customSignalName); } @@ -74,8 +73,8 @@ public static bool OnPlayerDataLearnSignal(SignalName __0) } [HarmonyPrefix] - [HarmonyPatch(typeof(PlayerData), nameof(PlayerData.KnowsMultipleFrequencies))] - public static bool OnPlayerDataKnowsMultipleFrequencies(ref bool __result) + [HarmonyPatch(nameof(PlayerData.KnowsMultipleFrequencies))] + public static bool PlayerData_KnowsMultipleFrequencies(ref bool __result) { if (NewHorizonsData.KnowsMultipleFrequencies()) { @@ -86,23 +85,20 @@ public static bool OnPlayerDataKnowsMultipleFrequencies(ref bool __result) } [HarmonyPrefix] - [HarmonyPatch(typeof(PlayerData), nameof(PlayerData.AddNewlyRevealedFactID))] - public static bool OnPlayerDataAddNewlyRevealedFactID(string __0) + [HarmonyPatch(nameof(PlayerData.AddNewlyRevealedFactID))] + public static bool PlayerData_AddNewlyRevealedFactID(string id) { - if (ShipLogHandler.IsModdedFact(__0)) + if (ShipLogHandler.IsModdedFact(id)) { - NewHorizonsData.AddNewlyRevealedFactID(__0); + NewHorizonsData.AddNewlyRevealedFactID(id); return false; } - else - { - return true; - } + return true; } [HarmonyPrefix] - [HarmonyPatch(typeof(PlayerData), nameof(PlayerData.GetNewlyRevealedFactIDs))] - public static bool OnPlayerDataGetNewlyRevealedFactIDs(ref List __result) + [HarmonyPatch(nameof(PlayerData.GetNewlyRevealedFactIDs))] + public static bool PlayerData_GetNewlyRevealedFactIDs_Prefix(ref List __result) { var newHorizonsNewlyRevealedFactIDs = NewHorizonsData.GetNewlyRevealedFactIDs(); if (newHorizonsNewlyRevealedFactIDs != null) @@ -110,35 +106,30 @@ public static bool OnPlayerDataGetNewlyRevealedFactIDs(ref List __result __result = PlayerData._currentGameSave.newlyRevealedFactIDs.Concat(newHorizonsNewlyRevealedFactIDs).ToList(); return false; } - else - { - Logger.LogError("Newly Revealed Fact IDs is null!"); - return true; - } + Logger.LogError("Newly Revealed Fact IDs is null!"); + return true; } - [HarmonyPrefix] - [HarmonyPatch(typeof(PlayerData), nameof(PlayerData.ClearNewlyRevealedFactIDs))] - public static bool OnPlayerDataClearNewlyRevealedFactIDs() + [HarmonyPostfix] + [HarmonyPatch(nameof(PlayerData.GetNewlyRevealedFactIDs))] + public static void PlayerData_GetNewlyRevealedFactIDs_Postfix(ref List __result) { - PlayerData._currentGameSave.newlyRevealedFactIDs.Clear(); - NewHorizonsData.ClearNewlyRevealedFactIDs(); - return false; + var manager = Locator.GetShipLogManager(); + __result = __result.Where(id => manager.GetFact(id) != null).ToList(); } [HarmonyPostfix] - [HarmonyPatch(typeof(PlayerData), nameof(PlayerData.ResetGame))] - public static void OnPlayerDataResetGame() + [HarmonyPatch(nameof(PlayerData.ClearNewlyRevealedFactIDs))] + public static void PlayerData_ClearNewlyRevealedFactIDs() { - NewHorizonsData.Reset(); + NewHorizonsData.ClearNewlyRevealedFactIDs(); } [HarmonyPostfix] - [HarmonyPatch(typeof(PlayerData), nameof(PlayerData.GetNewlyRevealedFactIDs))] - public static void PlayerData_GetNewlyRevealedFactIDs(ref List __result) + [HarmonyPatch(nameof(PlayerData.ResetGame))] + public static void PlayerData_ResetGame() { - ShipLogManager manager = Locator.GetShipLogManager(); - __result = __result.Where(e => manager.GetFact(e) != null).ToList(); + NewHorizonsData.Reset(); } } } diff --git a/NewHorizons/Patches/PlayerPatches/PlayerSpawnerPatches.cs b/NewHorizons/Patches/PlayerPatches/PlayerSpawnerPatches.cs new file mode 100644 index 000000000..11bcc7c16 --- /dev/null +++ b/NewHorizons/Patches/PlayerPatches/PlayerSpawnerPatches.cs @@ -0,0 +1,30 @@ +using HarmonyLib; +using NewHorizons.Utility; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Patches.PlayerPatches +{ + [HarmonyPatch(typeof(PlayerSpawner))] + public static class PlayerSpawnerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(PlayerSpawner.SpawnPlayer))] + public static bool PlayerSpawner_SpawnPlayer(PlayerSpawner __instance) + { + if (Main.Instance.IsWarpingFromVessel || Main.Instance.DidWarpFromVessel) + { + Logger.LogWarning("Abort player spawn. Vessel will handle it."); + return false; + } + else if (Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint != null) + { + Logger.LogVerbose($"Player spawning at {Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint.transform.GetPath()}"); + __instance.SetInitialSpawnPoint(Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint); + } else if (Main.Instance.CurrentStarSystem != "SolarSystem" && Main.Instance.CurrentStarSystem != "EyeOfTheUniverse") + { + Logger.LogWarning("No player spawn point set."); + } + return true; + } + } +} diff --git a/NewHorizons/Patches/PlayerStatePatches.cs b/NewHorizons/Patches/PlayerPatches/PlayerStatePatches.cs similarity index 81% rename from NewHorizons/Patches/PlayerStatePatches.cs rename to NewHorizons/Patches/PlayerPatches/PlayerStatePatches.cs index 0fe139187..adc39008d 100644 --- a/NewHorizons/Patches/PlayerStatePatches.cs +++ b/NewHorizons/Patches/PlayerPatches/PlayerStatePatches.cs @@ -1,12 +1,12 @@ -using HarmonyLib; +using HarmonyLib; using UnityEngine; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.PlayerPatches { - [HarmonyPatch] + [HarmonyPatch(typeof(PlayerState))] public static class PlayerStatePatches { [HarmonyPrefix] - [HarmonyPatch(typeof(PlayerState), nameof(PlayerState.CheckShipOutsideSolarSystem))] + [HarmonyPatch(nameof(PlayerState.CheckShipOutsideSolarSystem))] public static bool PlayerState_CheckShipOutsideSolarSystem(PlayerState __instance, ref bool __result) { if (PlayerState._inBrambleDimension) return false; diff --git a/NewHorizons/Patches/PlayerSpawnerPatches.cs b/NewHorizons/Patches/PlayerSpawnerPatches.cs deleted file mode 100644 index 3eef005c0..000000000 --- a/NewHorizons/Patches/PlayerSpawnerPatches.cs +++ /dev/null @@ -1,25 +0,0 @@ -using HarmonyLib; -using Logger = NewHorizons.Utility.Logger; -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public static class PlayerSpawnerPatches - { - [HarmonyPrefix] - [HarmonyPatch(typeof(PlayerSpawner), nameof(PlayerSpawner.SpawnPlayer))] - public static bool PlayerSpawner_SpawnPlayer(PlayerSpawner __instance) - { - if (Main.Instance.IsWarpingFromVessel || Main.Instance.DidWarpFromVessel) - { - Logger.LogWarning("Abort player spawn. Vessel will handle it."); - return false; - } - else - { - Logger.LogVerbose("Player spawning"); - __instance.SetInitialSpawnPoint(Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint); - return true; - } - } - } -} diff --git a/NewHorizons/Patches/ProbeLauncherPatches.cs b/NewHorizons/Patches/ProbeLauncherPatches.cs deleted file mode 100644 index 0f1ef17ec..000000000 --- a/NewHorizons/Patches/ProbeLauncherPatches.cs +++ /dev/null @@ -1,14 +0,0 @@ -using HarmonyLib; -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public static class ProbeLauncherPatches - { - [HarmonyPrefix] - [HarmonyPatch(typeof(ProbeLauncher), nameof(ProbeLauncher.UpdateOrbitalLaunchValues))] - public static bool ProbeLauncher_UpdateOrbitalLaunchValues(ProbeLauncher __instance) - { - return (Locator.GetPlayerRulesetDetector()?.GetPlanetoidRuleset()?.GetGravityVolume() != null); - } - } -} diff --git a/NewHorizons/Patches/ProxyPatches/ProxyBodyPatches.cs b/NewHorizons/Patches/ProxyPatches/ProxyBodyPatches.cs new file mode 100644 index 000000000..5ff71810d --- /dev/null +++ b/NewHorizons/Patches/ProxyPatches/ProxyBodyPatches.cs @@ -0,0 +1,15 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.ProxyPatches +{ + [HarmonyPatch(typeof(ProxyBody))] + public static class ProxyBodyPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(ProxyBody.IsObjectInSupernova))] + public static bool ProxyBody_IsObjectInSupernova(ProxyBody __instance) + { + return Locator.GetSunController() != null; + } + } +} diff --git a/NewHorizons/Patches/ProxyBodyPatches.cs b/NewHorizons/Patches/ProxyPatches/ProxyPlanetPatches.cs similarity index 89% rename from NewHorizons/Patches/ProxyBodyPatches.cs rename to NewHorizons/Patches/ProxyPatches/ProxyPlanetPatches.cs index 8040d8052..b59bdfcf0 100644 --- a/NewHorizons/Patches/ProxyBodyPatches.cs +++ b/NewHorizons/Patches/ProxyPatches/ProxyPlanetPatches.cs @@ -1,23 +1,15 @@ using HarmonyLib; -using NewHorizons.Components; -using NewHorizons.Handlers; using NewHorizons.Utility; using System; using System.Runtime.CompilerServices; using UnityEngine; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.ProxyPatches { [HarmonyPatch] - public static class ProxyBodyPatches + public static class ProxyPlanetPatches { - [HarmonyPrefix] - [HarmonyPatch(typeof(ProxyBody), nameof(ProxyBody.IsObjectInSupernova))] - public static bool ProxyBody_IsObjectInSupernova(ProxyBody __instance) - { - return Locator.GetSunController() != null; - } - + // To call the base method [HarmonyReversePatch] [HarmonyPatch(typeof(ProxyPlanet), nameof(ProxyPlanet.Initialize))] [MethodImpl(MethodImplOptions.NoInlining)] diff --git a/NewHorizons/Patches/ProxyPatches/SunProxyEffectControllerPatches.cs b/NewHorizons/Patches/ProxyPatches/SunProxyEffectControllerPatches.cs new file mode 100644 index 000000000..24e22d07e --- /dev/null +++ b/NewHorizons/Patches/ProxyPatches/SunProxyEffectControllerPatches.cs @@ -0,0 +1,22 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.ProxyPatches +{ + [HarmonyPatch(typeof(SunProxyEffectController))] + public static class SunProxyEffectControllerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(SunProxyEffectController.UpdateScales))] + public static bool SunProxyEffectController_UpdateScales(SunProxyEffectController __instance) + { + return __instance != null && __instance._surface != null && __instance._fog != null && __instance._fogMaterial != null && __instance._solarFlareEmitter != null && __instance._atmosphere != null; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(SunProxyEffectController.UpdateAtmosphereRadii))] + public static bool SunProxyEffectController_UpdateAtmosphereRadii(SunProxyEffectController __instance) + { + return __instance != null && __instance.transform != null && __instance.transform.parent != null && __instance._atmosphereMaterial != null; + } + } +} diff --git a/NewHorizons/Patches/RemotePatches.cs b/NewHorizons/Patches/RemotePatches.cs deleted file mode 100644 index 40c6a5c25..000000000 --- a/NewHorizons/Patches/RemotePatches.cs +++ /dev/null @@ -1,153 +0,0 @@ -using HarmonyLib; -using NewHorizons.Components; -using NewHorizons.Handlers; -using UnityEngine; - -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public class RemotePatches - { - [HarmonyPrefix] - [HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.IDToPlanetString))] - public static bool NomaiRemoteCameraPlatform_IDToPlanetString(NomaiRemoteCameraPlatform.ID id, out string __result) - { - switch (id) - { - case NomaiRemoteCameraPlatform.ID.None: - __result = "None"; - break; - case NomaiRemoteCameraPlatform.ID.SunStation: - __result = UITextLibrary.GetString(UITextType.LocationSS); - break; - case NomaiRemoteCameraPlatform.ID.HGT_TimeLoop: - __result = UITextLibrary.GetString(UITextType.LocationTT); - break; - case NomaiRemoteCameraPlatform.ID.TH_Mine: - __result = UITextLibrary.GetString(UITextType.LocationTH); - break; - case NomaiRemoteCameraPlatform.ID.THM_EyeLocator: - __result = UITextLibrary.GetString(UITextType.LocationTHMoon); - break; - case NomaiRemoteCameraPlatform.ID.BH_Observatory: - case NomaiRemoteCameraPlatform.ID.BH_GravityCannon: - case NomaiRemoteCameraPlatform.ID.BH_QuantumFragment: - case NomaiRemoteCameraPlatform.ID.BH_BlackHoleForge: - case NomaiRemoteCameraPlatform.ID.BH_NorthPole: - __result = UITextLibrary.GetString(UITextType.LocationBH); - break; - case NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland1: - case NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland2: - case NomaiRemoteCameraPlatform.ID.GD_StatueIsland: - __result = UITextLibrary.GetString(UITextType.LocationGD); - break; - case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonSunkenModule: - __result = UITextLibrary.GetString(UITextType.LocationOPC_Module3); - break; - case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonDamagedModule: - __result = UITextLibrary.GetString(UITextType.LocationOPC_Module2); - break; - case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonIntactModule: - __result = UITextLibrary.GetString(UITextType.LocationOPC_Module1); - break; - case NomaiRemoteCameraPlatform.ID.VM_Interior: - __result = UITextLibrary.GetString(UITextType.LocationBHMoon); - break; - case NomaiRemoteCameraPlatform.ID.HGT_TLE: - __result = UITextLibrary.GetString(UITextType.LocationCT); - break; - default: - __result = RemoteHandler.GetPlatformIDName(id); - break; - } - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(NomaiRemoteCameraStreaming), nameof(NomaiRemoteCameraStreaming.NomaiRemoteCameraPlatformIDToSceneName))] - public static bool NomaiRemoteCameraStreaming_NomaiRemoteCameraPlatformIDToSceneName(NomaiRemoteCameraPlatform.ID id, out string __result) - { - switch (id) - { - case NomaiRemoteCameraPlatform.ID.SunStation: - __result = "SolarSystem"; - break; - case NomaiRemoteCameraPlatform.ID.HGT_TimeLoop: - case NomaiRemoteCameraPlatform.ID.HGT_TLE: - __result = "HourglassTwins"; - break; - case NomaiRemoteCameraPlatform.ID.TH_Mine: - case NomaiRemoteCameraPlatform.ID.THM_EyeLocator: - __result = "TimberHearth"; - break; - case NomaiRemoteCameraPlatform.ID.BH_Observatory: - case NomaiRemoteCameraPlatform.ID.BH_GravityCannon: - case NomaiRemoteCameraPlatform.ID.BH_QuantumFragment: - case NomaiRemoteCameraPlatform.ID.BH_BlackHoleForge: - case NomaiRemoteCameraPlatform.ID.BH_NorthPole: - case NomaiRemoteCameraPlatform.ID.VM_Interior: - __result = "BrittleHollow"; - break; - case NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland1: - case NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland2: - case NomaiRemoteCameraPlatform.ID.GD_StatueIsland: - case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonSunkenModule: - case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonDamagedModule: - case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonIntactModule: - __result = "GiantsDeep"; - break; - case NomaiRemoteCameraPlatform.ID.None: - __result = ""; - break; - default: - var key = RemoteHandler.GetPlatformIDKey(id); - var _ = key.IndexOf("_"); - switch ((_ == -1) ? key : key.Substring(0, _)) - { - case "SS": - __result = "SolarSystem"; - break; - case "HGT": - case "CT": - case "TT": - __result = "HourglassTwins"; - break; - case "CO": - __result = "Comet"; - break; - case "QM": - __result = "QuantumMoon"; - break; - case "GD": - __result = "GiantsDeep"; - break; - case "BH": - case "VM": - __result = "BrittleHollow"; - break; - case "TH": - case "THM": - __result = "TimberHearth"; - break; - case "DB": - __result = "DarkBramble"; - break; - case "WH": - __result = "WhiteHole"; - break; - case "RW": - __result = "RingWorld"; - break; - case "DW": - __result = "DreamWorld"; - break; - default: - __result = key; - break; - } - break; - } - return false; - } - } -} diff --git a/NewHorizons/Patches/ShapePatches.cs b/NewHorizons/Patches/ShapeManagerPatches.cs similarity index 85% rename from NewHorizons/Patches/ShapePatches.cs rename to NewHorizons/Patches/ShapeManagerPatches.cs index cf4d19d0a..ea6a61905 100644 --- a/NewHorizons/Patches/ShapePatches.cs +++ b/NewHorizons/Patches/ShapeManagerPatches.cs @@ -3,11 +3,11 @@ namespace NewHorizons.Patches { - [HarmonyPatch] - public class ShapePatches + [HarmonyPatch(typeof(ShapeManager))] + public class ShapeManagerPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(ShapeManager), nameof(ShapeManager.Initialize))] + [HarmonyPatch(nameof(ShapeManager.Initialize))] public static bool ShapeManager_Initialize() { ShapeManager._exists = true; diff --git a/NewHorizons/Patches/ShipLogPatches.cs b/NewHorizons/Patches/ShipLogPatches.cs deleted file mode 100644 index 8fe329c1a..000000000 --- a/NewHorizons/Patches/ShipLogPatches.cs +++ /dev/null @@ -1,254 +0,0 @@ -using HarmonyLib; -using NewHorizons.OtherMods.AchievementsPlus; -using NewHorizons.Builder.ShipLog; -using NewHorizons.Handlers; -using NewHorizons.Utility; -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using Logger = NewHorizons.Utility.Logger; -using Object = UnityEngine.Object; -using NewHorizons.Components.ShipLog; - -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public static class ShipLogPatches - { - [HarmonyPrefix] - [HarmonyPatch(typeof(ShipLogManager), nameof(ShipLogManager.Awake))] - public static void ShipLogManager_Awake_Prefix(ShipLogManager __instance) - { - if (Main.Instance.IsWarpingBackToEye) return; - - RumorModeBuilder.Init(); - ShipLogHandler.Init(); - - var currentStarSystem = Main.Instance.CurrentStarSystem; - - if (!Main.SystemDict.ContainsKey(currentStarSystem) || !Main.BodyDict.ContainsKey(currentStarSystem)) - { - currentStarSystem = Main.Instance.DefaultStarSystem; - } - - Logger.Log($"Beginning Ship Log Generation For: {currentStarSystem}"); - - if (currentStarSystem != "SolarSystem") - { - __instance._shipLogXmlAssets = new TextAsset[] { }; - foreach (ShipLogEntryLocation logEntryLocation in GameObject.FindObjectsOfType()) - { - logEntryLocation._initialized = true; - } - } - - var curiosities = Main.SystemDict[currentStarSystem].Config.curiosities; - if (curiosities != null) - { - RumorModeBuilder.AddCuriosityColors(curiosities); - } - - foreach (NewHorizonsBody body in Main.BodyDict[currentStarSystem]) - { - if (body.Config.ShipLog?.xmlFile != null) - { - RumorModeBuilder.AddBodyToShipLog(__instance, body); - } - } - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(ShipLogManager), nameof(ShipLogManager.Awake))] - public static void ShipLogManager_Awake_Postfix(ShipLogManager __instance) - { - if (Main.Instance.IsWarpingBackToEye) return; - - ShipLogHandler.CheckForModdedFacts(__instance); - RumorModeBuilder.GenerateEntryData(__instance); - for (var i = 0; i < __instance._entryList.Count; i++) - { - ShipLogEntry logEntry = __instance._entryList[i]; - RumorModeBuilder.UpdateEntryCuriosity(ref logEntry); - } - - Logger.Log($"Ship Log Generation Complete For: {Main.Instance.CurrentStarSystem}"); - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ShipLogManager), nameof(ShipLogManager.IsFactRevealed))] - public static bool ShipLogManager_IsFactRevealed(ShipLogManager __instance, ref bool __result, string __0) - { - if (__instance._factDict != null && __instance._factDict.ContainsKey(__0)) - { - __result = __instance._factDict[__0].IsRevealed(); - } - else - { - __result = false; - } - - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ShipLogManager), nameof(ShipLogManager.CheckForCompletionAchievement))] - public static bool ShipLogManager_CheckForCompletionAchievement(ShipLogManager __instance) - { - foreach (KeyValuePair keyValuePair in __instance._factDict) - { - if (!ShipLogHandler.IsModdedFact(keyValuePair.Key) && !keyValuePair.Value.IsRumor() && !keyValuePair.Value.IsRevealed() && !keyValuePair.Key.Equals("TH_VILLAGE_X3") && !keyValuePair.Key.Equals("GD_GABBRO_ISLAND_X1") && __instance.GetEntry(keyValuePair.Value.GetEntryID()).GetCuriosityName() != CuriosityName.InvisiblePlanet) - { - return false; - } - } - Achievements.Earn(Achievements.Type.STUDIOUS); - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ShipLogManager), nameof(ShipLogManager.Start))] - public static bool ShipLogManager_Start(ShipLogManager __instance) - { - var initialReveal = Main.SystemDict[Main.Instance.CurrentStarSystem].Config.initialReveal ?? Array.Empty(); - foreach (string fact in initialReveal) - { - __instance.RevealFact(fact, false, false); - } - - if (Main.Instance.CurrentStarSystem == "SolarSystem") - { - return true; - } - else - { - EntryLocationBuilder.InitializeLocations(); - return false; - } - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(UIStyleManager), nameof(UIStyleManager.GetCuriosityColor))] - public static bool UIStyleManager_GetCuriosityColor(UIStyleManager __instance, CuriosityName __0, bool __1, ref Color __result) - { - if ((int)__0 < 7) - { - return true; - } - else - { - __result = RumorModeBuilder.GetCuriosityColor(__0, __1, __instance._neutralColor, __instance._neutralHighlight); - return false; - } - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(ShipLogMapMode), nameof(ShipLogMapMode.Initialize))] - public static void ShipLogMapMode_Initialize(ShipLogMapMode __instance) - { - GameObject panRoot = SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH); - GameObject sunObject = SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/Sun"); - ShipLogAstroObject[][] navMatrix = MapModeBuilder.ConstructMapMode(Main.Instance.CurrentStarSystem, panRoot, __instance._astroObjects, sunObject.layer); - if (navMatrix == null || navMatrix.Length <= 1) - { - Logger.LogWarning("Skipping Map Mode Generation."); - } - else - { - __instance._astroObjects = navMatrix; - __instance._startingAstroObjectID = navMatrix[1][0].GetID(); - if (Main.Instance.CurrentStarSystem != "SolarSystem") - { - 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)); - } - if (SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + "SandFunnel") == null) - { - __instance._sandFunnel = __instance.gameObject.AddComponent(); - } - } - } - - Logger.Log("Map Mode Construction Complete"); - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ShipLogAstroObject), nameof(ShipLogAstroObject.GetName))] - public static bool ShipLogAstroObject_GetName(ShipLogAstroObject __instance, ref string __result) - { - if (ShipLogHandler.IsVanillaAstroID(__instance.GetID())) - { - return true; - } - else - { - __result = MapModeBuilder.GetAstroBodyShipLogName(__instance.GetID()); - return false; - } - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(ShipLogAstroObject), nameof(ShipLogAstroObject.UpdateState))] - public static void ShipLogAstroObject_UpdateState(ShipLogAstroObject __instance) - { - Transform detailsParent = __instance.transform.Find("Details"); - if (detailsParent != null) - { - foreach (GameObject child in detailsParent.gameObject.GetAllChildren()) - { - if (child.TryGetComponent(typeof(ShipLogDetail), out Component detail)) - { - (detail as ShipLogDetail)?.UpdateState(__instance._state); - } - } - } - - Transform lineObject = __instance.transform.Find("Line_ShipLog"); - if (lineObject != null) - { - ShipLogDetail lineDetail = lineObject.gameObject.GetComponent(); - lineDetail.UpdateState(__instance._state); - } - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ShipLogSandFunnel), nameof(ShipLogSandFunnel.UpdateState))] - public static bool ShipLogSandFunnel_UpdateState() - { - return Main.Instance.CurrentStarSystem == "SolarSystem"; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ShipLogSandFunnel), nameof(ShipLogSandFunnel.Awake))] - public static bool ShipLogSandFunnel_Awake() - { - return Main.Instance.CurrentStarSystem == "SolarSystem"; - } - - [HarmonyPostfix] - [HarmonyPatch(typeof(ShipLogManager), nameof(ShipLogManager.RevealFact))] - public static void ShipLogManager_RevealFact(string __0) - { - StarChartHandler.OnRevealFact(__0); - - AchievementHandler.OnRevealFact(); - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(ShipLogFact), nameof(ShipLogFact.GetText))] - public static bool ShipLogFact_GetText(ShipLogFact __instance, ref string __result) - { - if (ShipLogHandler.IsModdedFact(__instance.GetID())) - { - __result = TranslationHandler.GetTranslation(__instance._text, TranslationHandler.TextType.SHIPLOG); - return false; - } - else - { - return true; - } - } - } -} \ No newline at end of file diff --git a/NewHorizons/Patches/ShipLogPatches/ShipLogAstroObjectPatches.cs b/NewHorizons/Patches/ShipLogPatches/ShipLogAstroObjectPatches.cs new file mode 100644 index 000000000..ba3c0e337 --- /dev/null +++ b/NewHorizons/Patches/ShipLogPatches/ShipLogAstroObjectPatches.cs @@ -0,0 +1,52 @@ +using HarmonyLib; +using NewHorizons.Builder.ShipLog; +using NewHorizons.Components.ShipLog; +using NewHorizons.Handlers; +using NewHorizons.Utility; +using UnityEngine; + +namespace NewHorizons.Patches.ShipLogPatches +{ + [HarmonyPatch(typeof(ShipLogAstroObject))] + public static class ShipLogAstroObjectPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(ShipLogAstroObject.GetName))] + public static bool ShipLogAstroObject_GetName(ShipLogAstroObject __instance, ref string __result) + { + if (ShipLogHandler.IsVanillaAstroID(__instance.GetID())) + { + return true; + } + else + { + __result = MapModeBuilder.GetAstroBodyShipLogName(__instance.GetID()); + return false; + } + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(ShipLogAstroObject.UpdateState))] + public static void ShipLogAstroObject_UpdateState(ShipLogAstroObject __instance) + { + Transform detailsParent = __instance.transform.Find("Details"); + if (detailsParent != null) + { + foreach (GameObject child in detailsParent.gameObject.GetAllChildren()) + { + if (child.TryGetComponent(typeof(ShipLogDetail), out Component detail)) + { + (detail as ShipLogDetail)?.UpdateState(__instance._state); + } + } + } + + Transform lineObject = __instance.transform.Find("Line_ShipLog"); + if (lineObject != null) + { + ShipLogDetail lineDetail = lineObject.gameObject.GetComponent(); + lineDetail.UpdateState(__instance._state); + } + } + } +} diff --git a/NewHorizons/Patches/ShipLogPatches/ShipLogFactPatches.cs b/NewHorizons/Patches/ShipLogPatches/ShipLogFactPatches.cs new file mode 100644 index 000000000..39f7647cd --- /dev/null +++ b/NewHorizons/Patches/ShipLogPatches/ShipLogFactPatches.cs @@ -0,0 +1,24 @@ +using HarmonyLib; +using NewHorizons.Handlers; + +namespace NewHorizons.Patches.ShipLogPatches +{ + [HarmonyPatch(typeof(ShipLogFact))] + public static class ShipLogFactPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(ShipLogFact.GetText))] + public static bool ShipLogFact_GetText(ShipLogFact __instance, ref string __result) + { + if (ShipLogHandler.IsModdedFact(__instance.GetID())) + { + __result = TranslationHandler.GetTranslation(__instance._text, TranslationHandler.TextType.SHIPLOG); + return false; + } + else + { + return true; + } + } + } +} diff --git a/NewHorizons/Patches/ShipLogPatches/ShipLogManagerPatches.cs b/NewHorizons/Patches/ShipLogPatches/ShipLogManagerPatches.cs new file mode 100644 index 000000000..8276ccc70 --- /dev/null +++ b/NewHorizons/Patches/ShipLogPatches/ShipLogManagerPatches.cs @@ -0,0 +1,135 @@ +using HarmonyLib; +using NewHorizons.Builder.ShipLog; +using NewHorizons.Handlers; +using NewHorizons.OtherMods.AchievementsPlus; +using NewHorizons.Utility; +using System.Collections.Generic; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Patches.ShipLogPatches +{ + [HarmonyPatch(typeof(ShipLogManager))] + public static class ShipLogManagerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(ShipLogManager.Awake))] + public static void ShipLogManager_Awake_Prefix(ShipLogManager __instance) + { + if (Main.Instance.IsWarpingBackToEye) return; + + RumorModeBuilder.Init(); + ShipLogHandler.Init(); + + var currentStarSystem = Main.Instance.CurrentStarSystem; + + if (!Main.SystemDict.ContainsKey(currentStarSystem) || !Main.BodyDict.ContainsKey(currentStarSystem)) + { + currentStarSystem = Main.Instance.DefaultStarSystem; + } + + Logger.Log($"Beginning Ship Log Generation For: {currentStarSystem}"); + + if (currentStarSystem != "SolarSystem") + { + __instance._shipLogXmlAssets = new TextAsset[] { }; + foreach (ShipLogEntryLocation logEntryLocation in Object.FindObjectsOfType()) + { + logEntryLocation._initialized = true; + } + } + + var curiosities = Main.SystemDict[currentStarSystem].Config.curiosities; + if (curiosities != null) + { + RumorModeBuilder.AddCuriosityColors(curiosities); + } + + foreach (NewHorizonsBody body in Main.BodyDict[currentStarSystem]) + { + if (body.Config.ShipLog?.xmlFile != null) + { + RumorModeBuilder.AddBodyToShipLog(__instance, body); + } + } + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(ShipLogManager.Awake))] + public static void ShipLogManager_Awake_Postfix(ShipLogManager __instance) + { + if (Main.Instance.IsWarpingBackToEye) return; + + ShipLogHandler.CheckForModdedFacts(__instance); + RumorModeBuilder.GenerateEntryData(__instance); + for (var i = 0; i < __instance._entryList.Count; i++) + { + ShipLogEntry logEntry = __instance._entryList[i]; + RumorModeBuilder.UpdateEntryCuriosity(ref logEntry); + } + + Logger.Log($"Ship Log Generation Complete For: {Main.Instance.CurrentStarSystem}"); + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(ShipLogManager.IsFactRevealed))] + public static bool ShipLogManager_IsFactRevealed(ShipLogManager __instance, ref bool __result, string __0) + { + if (__instance._factDict != null && __instance._factDict.ContainsKey(__0)) + { + __result = __instance._factDict[__0].IsRevealed(); + } + else + { + __result = false; + } + + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(ShipLogManager.CheckForCompletionAchievement))] + public static bool ShipLogManager_CheckForCompletionAchievement(ShipLogManager __instance) + { + foreach (KeyValuePair keyValuePair in __instance._factDict) + { + if (!ShipLogHandler.IsModdedFact(keyValuePair.Key) && !keyValuePair.Value.IsRumor() && !keyValuePair.Value.IsRevealed() && !keyValuePair.Key.Equals("TH_VILLAGE_X3") && !keyValuePair.Key.Equals("GD_GABBRO_ISLAND_X1") && __instance.GetEntry(keyValuePair.Value.GetEntryID()).GetCuriosityName() != CuriosityName.InvisiblePlanet) + { + return false; + } + } + Achievements.Earn(Achievements.Type.STUDIOUS); + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(ShipLogManager.Start))] + public static bool ShipLogManager_Start(ShipLogManager __instance) + { + var initialReveal = Main.SystemDict[Main.Instance.CurrentStarSystem].Config.initialReveal ?? System.Array.Empty(); + foreach (string fact in initialReveal) + { + __instance.RevealFact(fact, false, false); + } + + if (Main.Instance.CurrentStarSystem == "SolarSystem") + { + return true; + } + else + { + EntryLocationBuilder.InitializeLocations(); + return false; + } + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(ShipLogManager.RevealFact))] + public static void ShipLogManager_RevealFact(string __0) + { + StarChartHandler.OnRevealFact(__0); + + AchievementHandler.OnRevealFact(); + } + } +} \ No newline at end of file diff --git a/NewHorizons/Patches/ShipLogPatches/ShipLogMapModePatches.cs b/NewHorizons/Patches/ShipLogPatches/ShipLogMapModePatches.cs new file mode 100644 index 000000000..b946c3c67 --- /dev/null +++ b/NewHorizons/Patches/ShipLogPatches/ShipLogMapModePatches.cs @@ -0,0 +1,47 @@ +using HarmonyLib; +using NewHorizons.Builder.ShipLog; +using NewHorizons.Handlers; +using NewHorizons.Utility; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Patches.ShipLogPatches +{ + [HarmonyPatch(typeof(ShipLogMapMode))] + public static class ShipLogMapModePatches + { + [HarmonyPostfix] + [HarmonyPatch(nameof(ShipLogMapMode.Initialize))] + public static void ShipLogMapMode_Initialize(ShipLogMapMode __instance) + { + GameObject panRoot = SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH); + GameObject sunObject = SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/Sun"); + ShipLogAstroObject[][] navMatrix = MapModeBuilder.ConstructMapMode(Main.Instance.CurrentStarSystem, panRoot, __instance._astroObjects, sunObject.layer); + if (navMatrix == null || navMatrix.Length <= 1) + { + Logger.LogWarning("Skipping Map Mode Generation."); + } + else + { + __instance._astroObjects = navMatrix; + __instance._startingAstroObjectID = navMatrix[1][0].GetID(); + if (Main.Instance.CurrentStarSystem != "SolarSystem") + { + 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)); + } + if (SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + "SandFunnel") == null) + { + __instance._sandFunnel = __instance.gameObject.AddComponent(); + } + } + } + + Logger.Log("Map Mode Construction Complete"); + } + } +} diff --git a/NewHorizons/Patches/ShipLogPatches/ShipLogSandFunnelPatches.cs b/NewHorizons/Patches/ShipLogPatches/ShipLogSandFunnelPatches.cs new file mode 100644 index 000000000..1f56a1523 --- /dev/null +++ b/NewHorizons/Patches/ShipLogPatches/ShipLogSandFunnelPatches.cs @@ -0,0 +1,22 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.ShipLogPatches +{ + [HarmonyPatch(typeof(ShipLogSandFunnel))] + public static class ShipLogSandFunnelPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(ShipLogSandFunnel.UpdateState))] + public static bool ShipLogSandFunnel_UpdateState() + { + return Main.Instance.CurrentStarSystem == "SolarSystem"; + } + + [HarmonyPrefix] + [HarmonyPatch(nameof(ShipLogSandFunnel.Awake))] + public static bool ShipLogSandFunnel_Awake() + { + return Main.Instance.CurrentStarSystem == "SolarSystem"; + } + } +} diff --git a/NewHorizons/Patches/ShipLogPatches/UIStyleManagerPatches.cs b/NewHorizons/Patches/ShipLogPatches/UIStyleManagerPatches.cs new file mode 100644 index 000000000..7941299f6 --- /dev/null +++ b/NewHorizons/Patches/ShipLogPatches/UIStyleManagerPatches.cs @@ -0,0 +1,25 @@ +using HarmonyLib; +using NewHorizons.Builder.ShipLog; +using UnityEngine; + +namespace NewHorizons.Patches.ShipLogPatches +{ + [HarmonyPatch(typeof(UIStyleManager))] + public static class UIStyleManagerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(UIStyleManager.GetCuriosityColor))] + public static bool UIStyleManager_GetCuriosityColor(UIStyleManager __instance, CuriosityName curiosityName, bool highlight, ref Color __result) + { + if ((int)curiosityName < 7) + { + return true; + } + else + { + __result = RumorModeBuilder.GetCuriosityColor(curiosityName, highlight, __instance._neutralColor, __instance._neutralHighlight); + return false; + } + } + } +} diff --git a/NewHorizons/Patches/AudioSignalPatches.cs b/NewHorizons/Patches/SignalPatches/AudioSignalPatches.cs similarity index 63% rename from NewHorizons/Patches/AudioSignalPatches.cs rename to NewHorizons/Patches/SignalPatches/AudioSignalPatches.cs index 9811bc77a..32318a5c7 100644 --- a/NewHorizons/Patches/AudioSignalPatches.cs +++ b/NewHorizons/Patches/SignalPatches/AudioSignalPatches.cs @@ -5,16 +5,16 @@ using System; using UnityEngine; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.SignalPatches { - [HarmonyPatch] + [HarmonyPatch(typeof(AudioSignal))] public static class AudioSignalPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(AudioSignal), nameof(AudioSignal.SignalNameToString))] - public static bool AudioSignal_SignalNameToString(SignalName __0, ref string __result) + [HarmonyPatch(nameof(AudioSignal.SignalNameToString))] + public static bool AudioSignal_SignalNameToString(SignalName name, ref string __result) { - var customSignalName = SignalBuilder.GetCustomSignalName(__0); + var customSignalName = SignalBuilder.GetCustomSignalName(name); if (!string.IsNullOrEmpty(customSignalName)) { __result = TranslationHandler.GetTranslation(customSignalName, TranslationHandler.TextType.UI, false).ToUpper(); @@ -24,86 +24,48 @@ public static bool AudioSignal_SignalNameToString(SignalName __0, ref string __r } [HarmonyPrefix] - [HarmonyPatch(typeof(AudioSignal), nameof(AudioSignal.FrequencyToIndex))] - public static bool AudioSignal_FrequencyToIndex(SignalFrequency __0, ref int __result) + [HarmonyPatch(nameof(AudioSignal.FrequencyToIndex))] + public static bool AudioSignal_FrequencyToIndex(SignalFrequency frequency, out int __result) { - switch (__0) + __result = frequency switch { - case (SignalFrequency.Default): - __result = 0; - break; - case (SignalFrequency.Traveler): - __result = 1; - break; - case (SignalFrequency.Quantum): - __result = 2; - break; - case (SignalFrequency.EscapePod): - __result = 3; - break; - case (SignalFrequency.WarpCore): - __result = 4; - break; - case (SignalFrequency.HideAndSeek): - __result = 5; - break; - case (SignalFrequency.Radio): - __result = 6; - break; - case (SignalFrequency.Statue): - __result = 7; - break; - default: - // Frequencies are in powers of 2 - __result = (int)(Mathf.Log((float)__0) / Mathf.Log(2f)); - break; - } - + SignalFrequency.Default => 0, + SignalFrequency.Traveler => 1, + SignalFrequency.Quantum => 2, + SignalFrequency.EscapePod => 3, + SignalFrequency.WarpCore => 4, + SignalFrequency.HideAndSeek => 5, + SignalFrequency.Radio => 6, + SignalFrequency.Statue => 7, + _ => (int)(Mathf.Log((float)frequency) / Mathf.Log(2f)),// Frequencies are in powers of 2 + }; return false; } [HarmonyPrefix] - [HarmonyPatch(typeof(AudioSignal), nameof(AudioSignal.IndexToFrequency))] - public static bool AudioSignal_IndexToFrequency(int __0, ref SignalFrequency __result) + [HarmonyPatch(nameof(AudioSignal.IndexToFrequency))] + public static bool AudioSignal_IndexToFrequency(int index, out SignalFrequency __result) { - switch (__0) + __result = index switch { - case 0: - __result = SignalFrequency.Default; - break; - case 1: - __result = SignalFrequency.Traveler; - break; - case 2: - __result = SignalFrequency.Quantum; - break; - case 3: - __result = SignalFrequency.EscapePod; - break; - case 4: - __result = SignalFrequency.WarpCore; - break; - case 5: - __result = SignalFrequency.HideAndSeek; - break; - case 6: - __result = SignalFrequency.Radio; - break; - case 7: - __result = SignalFrequency.Statue; - break; - default: - __result = (SignalFrequency)(Math.Pow(2, __0)); - break; - } + 0 => SignalFrequency.Default, + 1 => SignalFrequency.Traveler, + 2 => SignalFrequency.Quantum, + 3 => SignalFrequency.EscapePod, + 4 => SignalFrequency.WarpCore, + 5 => SignalFrequency.HideAndSeek, + 6 => SignalFrequency.Radio, + 7 => SignalFrequency.Statue, + _ => (SignalFrequency)Math.Pow(2, index), + }; return false; } [HarmonyPrefix] - [HarmonyPatch(typeof(AudioSignal), nameof(AudioSignal.FrequencyToString))] - public static bool AudioSignal_FrequencyToString(SignalFrequency __0, ref string __result) + [HarmonyPatch(nameof(AudioSignal.FrequencyToString))] + public static bool AudioSignal_FrequencyToString(SignalFrequency frequency, ref string __result) { - var customName = SignalBuilder.GetCustomFrequencyName(__0); + var customName = SignalBuilder.GetCustomFrequencyName(frequency); if (!string.IsNullOrEmpty(customName)) { if (NewHorizonsData.KnowsFrequency(customName)) __result = TranslationHandler.GetTranslation(customName, TranslationHandler.TextType.UI, false).ToUpper(); @@ -114,13 +76,13 @@ public static bool AudioSignal_FrequencyToString(SignalFrequency __0, ref string } [HarmonyPrefix] - [HarmonyPatch(typeof(AudioSignal), nameof(AudioSignal.UpdateSignalStrength))] + [HarmonyPatch(nameof(AudioSignal.UpdateSignalStrength))] public static bool AudioSignal_UpdateSignalStrength(AudioSignal __instance, Signalscope scope, float distToClosestScopeObstruction) { if (!SignalBuilder.Initialized) return true; - var isCloaked = SignalBuilder.IsCloaked(__instance._name); - var isOnQuantumMoon = SignalBuilder.IsOnQuantumMoon(__instance._name); + var isCloaked = __instance._name.IsCloaked(); + var isOnQuantumMoon = __instance._name.IsOnQuantumMoon(); if (!isCloaked && !isOnQuantumMoon) return true; @@ -213,12 +175,5 @@ public static bool AudioSignal_UpdateSignalStrength(AudioSignal __instance, Sign return false; } - - [HarmonyPrefix] - [HarmonyPatch(typeof(TravelerAudioManager), nameof(TravelerAudioManager.Update))] - public static void TravelerAudioManager_Update(TravelerAudioManager __instance) - { - __instance._signals.RemoveAll(signal => signal == null || signal.gameObject == null || signal._owAudioSource == null || signal._owAudioSource._audioSource == null); - } } } diff --git a/NewHorizons/Patches/SignalScopePatches.cs b/NewHorizons/Patches/SignalPatches/SignalscopePatches.cs similarity index 55% rename from NewHorizons/Patches/SignalScopePatches.cs rename to NewHorizons/Patches/SignalPatches/SignalscopePatches.cs index 6f1cdb2d2..6b401d452 100644 --- a/NewHorizons/Patches/SignalScopePatches.cs +++ b/NewHorizons/Patches/SignalPatches/SignalscopePatches.cs @@ -1,33 +1,33 @@ -using HarmonyLib; +using HarmonyLib; using NewHorizons.Builder.Props; -namespace NewHorizons.Patches + +namespace NewHorizons.Patches.SignalPatches { - [HarmonyPatch] + [HarmonyPatch(typeof(Signalscope))] public static class SignalScopePatches { [HarmonyPrefix] - [HarmonyPatch(typeof(Signalscope), nameof(Signalscope.Awake))] - public static bool Signalscope_Awake(Signalscope __instance) + [HarmonyPatch(nameof(Signalscope.Awake))] + public static void Signalscope_Awake(Signalscope __instance) { __instance._strongestSignals = new AudioSignal[8]; - return true; } [HarmonyPrefix] - [HarmonyPatch(typeof(Signalscope), nameof(Signalscope.SwitchFrequencyFilter))] - public static bool Signalscope_SwitchFrequencyFilter(Signalscope __instance, int __0) + [HarmonyPatch(nameof(Signalscope.SwitchFrequencyFilter))] + public static bool Signalscope_SwitchFrequencyFilter(Signalscope __instance, int increment) { - var increment = __0; var count = SignalBuilder.NumberOfFrequencies; __instance._frequencyFilterIndex += increment; - __instance._frequencyFilterIndex = ((__instance._frequencyFilterIndex >= count) ? 0 : __instance._frequencyFilterIndex); - __instance._frequencyFilterIndex = ((__instance._frequencyFilterIndex < 0) ? count - 1 : __instance._frequencyFilterIndex); + __instance._frequencyFilterIndex = __instance._frequencyFilterIndex >= count ? 0 : __instance._frequencyFilterIndex; + __instance._frequencyFilterIndex = __instance._frequencyFilterIndex < 0 ? count - 1 : __instance._frequencyFilterIndex; SignalFrequency signalFrequency = AudioSignal.IndexToFrequency(__instance._frequencyFilterIndex); if (!PlayerData.KnowsFrequency(signalFrequency) && (!__instance._isUnknownFreqNearby || __instance._unknownFrequency != signalFrequency)) { __instance.SwitchFrequencyFilter(increment); } + return false; } } diff --git a/NewHorizons/Patches/SignalPatches/TravelerAudioManagerPatches.cs b/NewHorizons/Patches/SignalPatches/TravelerAudioManagerPatches.cs new file mode 100644 index 000000000..af33b3f5f --- /dev/null +++ b/NewHorizons/Patches/SignalPatches/TravelerAudioManagerPatches.cs @@ -0,0 +1,15 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.SignalPatches +{ + [HarmonyPatch(typeof(TravelerAudioManager))] + public static class TravelerAudioManagerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(TravelerAudioManager.Update))] + public static void TravelerAudioManager_Update(TravelerAudioManager __instance) + { + __instance._signals.RemoveAll(signal => signal == null || signal.gameObject == null || signal._owAudioSource == null || signal._owAudioSource._audioSource == null); + } + } +} diff --git a/NewHorizons/Patches/SingularityPatches.cs b/NewHorizons/Patches/SingularityPatches.cs deleted file mode 100644 index e172c9e1c..000000000 --- a/NewHorizons/Patches/SingularityPatches.cs +++ /dev/null @@ -1,51 +0,0 @@ -using HarmonyLib; -using System; -using System.Collections.Generic; -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public static class SingularityPatches - { - // For our custom black holes that don't link to anything - [HarmonyPrefix] - [HarmonyPatch(typeof(BlackHoleVolume), nameof(BlackHoleVolume.Start))] - public static bool BlackHoleVolume_Start(BlackHoleVolume __instance) - { - return __instance._whiteHole == null; - } - - // To fix custom white holes - [HarmonyPrefix] - [HarmonyPatch(typeof(WhiteHoleVolume), nameof(WhiteHoleVolume.Awake))] - public static bool WhiteHoleVolume_Awake(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; - } - - // This is to stop the game throwing too many errors if the probe is destroyed by a blackhole - [HarmonyPrefix] - [HarmonyPatch(typeof(SurveyorProbe), nameof(SurveyorProbe.IsLaunched))] - public static bool SurveyorProbe_IsLaunched(SurveyorProbe __instance, ref bool __result) - { - try - { - __result = __instance.gameObject.activeSelf; - } - catch (Exception) - { - __result = true; - } - return false; - } - } -} diff --git a/NewHorizons/Patches/StreamingPatches.cs b/NewHorizons/Patches/StreamingPatches.cs deleted file mode 100644 index 85acd0abe..000000000 --- a/NewHorizons/Patches/StreamingPatches.cs +++ /dev/null @@ -1,26 +0,0 @@ -using HarmonyLib; -using NewHorizons.Handlers; -using OWML.Logging; - -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public static class StreamingPatches - { - [HarmonyPrefix] - [HarmonyPatch(typeof(StreamingManager), nameof(StreamingManager.UnloadStreamingAssets))] - public static bool StreamingManager_UnloadStreamingAssets(string assetBundleName) - { - // Only let it unload stuff that isn't being used - return !StreamingHandler.IsBundleInUse(assetBundleName); - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(UnityLogger), "OnLogMessageReceived")] - public static bool UnityLogger_OnLogMessageReceived(string message) - { - // Filter out goofy error that doesn't actually break anything - return !message.EndsWith(") is out of bounds (size=0)"); - } - } -} diff --git a/NewHorizons/Patches/StreamingPatches/NomaiRemoteCameraStreamingPatches.cs b/NewHorizons/Patches/StreamingPatches/NomaiRemoteCameraStreamingPatches.cs new file mode 100644 index 000000000..e520a99fc --- /dev/null +++ b/NewHorizons/Patches/StreamingPatches/NomaiRemoteCameraStreamingPatches.cs @@ -0,0 +1,47 @@ +using HarmonyLib; +using NewHorizons.Handlers; + +namespace NewHorizons.Patches.StreamingPatches +{ + [HarmonyPatch(typeof(NomaiRemoteCameraStreaming))] + public class NomaiRemoteCameraStreamingPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(NomaiRemoteCameraStreaming.NomaiRemoteCameraPlatformIDToSceneName))] + public static bool NomaiRemoteCameraStreaming_NomaiRemoteCameraPlatformIDToSceneName(NomaiRemoteCameraPlatform.ID id, out string __result) + { + __result = id switch + { + NomaiRemoteCameraPlatform.ID.SunStation => "SolarSystem", + NomaiRemoteCameraPlatform.ID.HGT_TimeLoop or NomaiRemoteCameraPlatform.ID.HGT_TLE => "HourglassTwins", + NomaiRemoteCameraPlatform.ID.TH_Mine or NomaiRemoteCameraPlatform.ID.THM_EyeLocator => "TimberHearth", + NomaiRemoteCameraPlatform.ID.BH_Observatory or NomaiRemoteCameraPlatform.ID.BH_GravityCannon or NomaiRemoteCameraPlatform.ID.BH_QuantumFragment or NomaiRemoteCameraPlatform.ID.BH_BlackHoleForge or NomaiRemoteCameraPlatform.ID.BH_NorthPole or NomaiRemoteCameraPlatform.ID.VM_Interior => "BrittleHollow", + NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland1 or NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland2 or NomaiRemoteCameraPlatform.ID.GD_StatueIsland or NomaiRemoteCameraPlatform.ID.GD_ProbeCannonSunkenModule or NomaiRemoteCameraPlatform.ID.GD_ProbeCannonDamagedModule or NomaiRemoteCameraPlatform.ID.GD_ProbeCannonIntactModule => "GiantsDeep", + NomaiRemoteCameraPlatform.ID.None => "", + _ => PlatformKeyToSceneName(id), + }; + return false; + } + + private static string PlatformKeyToSceneName(NomaiRemoteCameraPlatform.ID id) + { + var key = RemoteHandler.GetPlatformIDKey(id); + var _ = key.IndexOf("_"); + return (_ == -1 ? key : key.Substring(0, _)) switch + { + "SS" => "SolarSystem", + "HGT" or "CT" or "TT" => "HourglassTwins", + "CO" => "Comet", + "QM" => "QuantumMoon", + "GD" => "GiantsDeep", + "BH" or "VM" => "BrittleHollow", + "TH" or "THM" => "TimberHearth", + "DB" => "DarkBramble", + "WH" => "WhiteHole", + "RW" => "RingWorld", + "DW" => "DreamWorld", + _ => key, + }; + } + } +} diff --git a/NewHorizons/Patches/StreamingPatches/StreamingManagerPatches.cs b/NewHorizons/Patches/StreamingPatches/StreamingManagerPatches.cs new file mode 100644 index 000000000..db34067cf --- /dev/null +++ b/NewHorizons/Patches/StreamingPatches/StreamingManagerPatches.cs @@ -0,0 +1,18 @@ +using HarmonyLib; +using NewHorizons.Handlers; +using OWML.Logging; + +namespace NewHorizons.Patches.StreamingPatches +{ + [HarmonyPatch(typeof(StreamingManager))] + public static class StreamingManagerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(StreamingManager.UnloadStreamingAssets))] + public static bool StreamingManager_UnloadStreamingAssets(string assetBundleName) + { + // Only let it unload stuff that isn't being used + return !StreamingHandler.IsBundleInUse(assetBundleName); + } + } +} diff --git a/NewHorizons/Patches/StreamingPatches/UnityLoggerPatches.cs b/NewHorizons/Patches/StreamingPatches/UnityLoggerPatches.cs new file mode 100644 index 000000000..ac772441b --- /dev/null +++ b/NewHorizons/Patches/StreamingPatches/UnityLoggerPatches.cs @@ -0,0 +1,17 @@ +using HarmonyLib; +using OWML.Logging; + +namespace NewHorizons.Patches.StreamingPatches +{ + [HarmonyPatch(typeof(UnityLogger))] + public static class UnityLoggerPatches + { + [HarmonyPrefix] + [HarmonyPatch("OnLogMessageReceived")] + public static bool UnityLogger_OnLogMessageReceived(string message) + { + // Filter out goofy error that doesn't actually break anything + return !message.EndsWith(") is out of bounds (size=0)"); + } + } +} diff --git a/NewHorizons/Patches/SunPatches.cs b/NewHorizons/Patches/SunPatches.cs deleted file mode 100644 index 447028bd7..000000000 --- a/NewHorizons/Patches/SunPatches.cs +++ /dev/null @@ -1,65 +0,0 @@ -using HarmonyLib; -using UnityEngine; -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public static class SunPatches - { - [HarmonyPrefix] - [HarmonyPatch(typeof(SunLightParamUpdater), nameof(SunLightParamUpdater.LateUpdate))] - public static bool SunLightParamUpdater_LateUpdate(SunLightParamUpdater __instance) - { - if (__instance.sunLight) - { - Vector3 position = __instance.transform.position; - float w = 2000f; - if (__instance._sunController != null) - { - w = (__instance._sunController.HasSupernovaStarted() ? __instance._sunController.GetSupernovaRadius() : __instance._sunController.GetSurfaceRadius()); - } - float range = __instance.sunLight.range; - Color color = (__instance._sunLightController != null) ? __instance._sunLightController.sunColor : __instance.sunLight.color; - float w2 = (__instance._sunLightController != null) ? __instance._sunLightController.sunIntensity : __instance.sunLight.intensity; - Shader.SetGlobalVector(__instance._propID_SunPosition, new Vector4(position.x, position.y, position.z, w)); - Shader.SetGlobalVector(__instance._propID_OWSunPositionRange, new Vector4(position.x, position.y, position.z, 1f / (range * range))); - Shader.SetGlobalVector(__instance._propID_OWSunColorIntensity, new Vector4(color.r, color.g, color.b, w2)); - } - - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(SunSurfaceAudioController), nameof(SunSurfaceAudioController.Update))] - public static bool SunSurfaceAudioController_Update(SunSurfaceAudioController __instance) - { - if (__instance._sunController != null) return true; - - var surfaceRadius = __instance.transform.parent.parent.localScale.magnitude; - float value = Mathf.Max(0f, Vector3.Distance(Locator.GetPlayerCamera().transform.position, __instance.transform.position) - surfaceRadius); - float num = Mathf.InverseLerp(1600f, 100f, value); - __instance._audioSource.SetLocalVolume(num * num * __instance._fade); - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(SunProxyEffectController), nameof(SunProxyEffectController.UpdateScales))] - public static bool SunProxyEffectController_UpdateScales(SunProxyEffectController __instance) - { - return __instance != null && __instance._surface != null && __instance._fog != null && __instance._fogMaterial != null && __instance._solarFlareEmitter != null && __instance._atmosphere != null; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(SunProxyEffectController), nameof(SunProxyEffectController.UpdateAtmosphereRadii))] - public static bool SunProxyEffectController_UpdateAtmosphereRadii(SunProxyEffectController __instance) - { - return __instance != null && __instance.transform != null && __instance.transform.parent != null && __instance._atmosphereMaterial != null; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(VanishVolume), nameof(VanishVolume.Shrink))] - public static bool VanishVolume_Shrink(VanishVolume __instance, OWRigidbody bodyToShrink) - { - return __instance != null && __instance.transform != null && __instance._shrinkingBodies != null && __instance._shrinkingBodyLocationData != null && bodyToShrink != null; - } - } -} diff --git a/NewHorizons/Patches/SunPatches/SunControllerPatches.cs b/NewHorizons/Patches/SunPatches/SunControllerPatches.cs new file mode 100644 index 000000000..222b87f01 --- /dev/null +++ b/NewHorizons/Patches/SunPatches/SunControllerPatches.cs @@ -0,0 +1,18 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.SunPatches +{ + [HarmonyPatch(typeof(SunController))] + public static class SunControllerPatches + { + /// + /// Disables sun logic if no time loop + /// + [HarmonyPrefix] + [HarmonyPatch(nameof(SunController.Update))] + [HarmonyPatch(nameof(SunController.UpdateScale))] + [HarmonyPatch(nameof(SunController.OnTriggerSupernova))] + public static bool SunController_DisableWithoutTimeLoop(SunController __instance) => Main.Instance.TimeLoopEnabled && __instance.isActiveAndEnabled; + + } +} diff --git a/NewHorizons/Patches/SunPatches/SunLightParamUpdaterPatches.cs b/NewHorizons/Patches/SunPatches/SunLightParamUpdaterPatches.cs new file mode 100644 index 000000000..45d68e3e9 --- /dev/null +++ b/NewHorizons/Patches/SunPatches/SunLightParamUpdaterPatches.cs @@ -0,0 +1,31 @@ +using HarmonyLib; +using UnityEngine; +namespace NewHorizons.Patches.SunPatches +{ + [HarmonyPatch(typeof(SunLightParamUpdater))] + public static class SunLightParamUpdaterPatches + { + [HarmonyPrefix] + [HarmonyPatch(typeof(SunLightParamUpdater), nameof(SunLightParamUpdater.LateUpdate))] + public static bool SunLightParamUpdater_LateUpdate(SunLightParamUpdater __instance) + { + if (__instance.sunLight) + { + Vector3 position = __instance.transform.position; + float w = 2000f; + if (__instance._sunController != null) + { + w = __instance._sunController.HasSupernovaStarted() ? __instance._sunController.GetSupernovaRadius() : __instance._sunController.GetSurfaceRadius(); + } + float range = __instance.sunLight.range; + Color color = __instance._sunLightController != null ? __instance._sunLightController.sunColor : __instance.sunLight.color; + float w2 = __instance._sunLightController != null ? __instance._sunLightController.sunIntensity : __instance.sunLight.intensity; + Shader.SetGlobalVector(__instance._propID_SunPosition, new Vector4(position.x, position.y, position.z, w)); + Shader.SetGlobalVector(__instance._propID_OWSunPositionRange, new Vector4(position.x, position.y, position.z, 1f / (range * range))); + Shader.SetGlobalVector(__instance._propID_OWSunColorIntensity, new Vector4(color.r, color.g, color.b, w2)); + } + + return false; + } + } +} diff --git a/NewHorizons/Patches/SunPatches/SunSurfaceAudioControllerPatches.cs b/NewHorizons/Patches/SunPatches/SunSurfaceAudioControllerPatches.cs new file mode 100644 index 000000000..d4040f3ff --- /dev/null +++ b/NewHorizons/Patches/SunPatches/SunSurfaceAudioControllerPatches.cs @@ -0,0 +1,22 @@ +using HarmonyLib; +using UnityEngine; + +namespace NewHorizons.Patches.SunPatches +{ + [HarmonyPatch(typeof(SunSurfaceAudioController))] + public static class SunSurfaceAudioControllerPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(SunSurfaceAudioController.Update))] + public static bool SunSurfaceAudioController_Update(SunSurfaceAudioController __instance) + { + if (__instance._sunController != null) return true; + + var surfaceRadius = __instance.transform.parent.parent.localScale.magnitude; + float value = Mathf.Max(0f, Vector3.Distance(Locator.GetPlayerCamera().transform.position, __instance.transform.position) - surfaceRadius); + float num = Mathf.InverseLerp(1600f, 100f, value); + __instance._audioSource.SetLocalVolume(num * num * __instance._fade); + return false; + } + } +} diff --git a/NewHorizons/Patches/TimeLoopPatches.cs b/NewHorizons/Patches/TimeLoopPatches.cs index d627d2b40..5628fa155 100644 --- a/NewHorizons/Patches/TimeLoopPatches.cs +++ b/NewHorizons/Patches/TimeLoopPatches.cs @@ -6,52 +6,13 @@ namespace NewHorizons.Patches public static class TimeLoopPatches { /// - /// Disables starfield updates + /// Disable certain behaviours without timeloop /// [HarmonyPrefix] [HarmonyPatch(typeof(StarfieldController), nameof(StarfieldController.Update))] - public static bool StarfieldController_Update() => Main.Instance.TimeLoopEnabled; - - /// - /// Disables interloper destruction - /// - [HarmonyPrefix] [HarmonyPatch(typeof(TempCometCollisionFix), nameof(TempCometCollisionFix.Update))] - public static bool TempCometCollisionFix_Update() => Main.Instance.TimeLoopEnabled; - - /// - /// Disables sun logic - /// - [HarmonyPrefix] - [HarmonyPatch(typeof(SunController), nameof(SunController.Update))] - public static bool SunController_Update(SunController __instance) => Main.Instance.TimeLoopEnabled && __instance.isActiveAndEnabled; - - /// - /// Disables sun expansion - /// - [HarmonyPrefix] - [HarmonyPatch(typeof(SunController), nameof(SunController.UpdateScale))] - public static bool SunController_UpdateScale(SunController __instance) => Main.Instance.TimeLoopEnabled && __instance.isActiveAndEnabled; - - /// - /// Disables sun collapse SFX - /// - [HarmonyPrefix] - [HarmonyPatch(typeof(SunController), nameof(SunController.OnTriggerSupernova))] - public static bool SunController_OnTriggerSupernova(SunController __instance) => Main.Instance.TimeLoopEnabled && __instance.isActiveAndEnabled; - - /// - /// Disables end times music - /// - [HarmonyPrefix] [HarmonyPatch(typeof(GlobalMusicController), nameof(GlobalMusicController.UpdateEndTimesMusic))] - public static bool GlobalMusicController_UpdateEndTimesMusic() => Main.Instance.TimeLoopEnabled; - - /// - /// Disables supernova trigger - /// - [HarmonyPrefix] [HarmonyPatch(typeof(TimeLoop), nameof(TimeLoop.Update))] - public static bool TimeLoop_Update() => Main.Instance.TimeLoopEnabled; + public static bool DisableWithoutTimeLoop() => Main.Instance.TimeLoopEnabled; } } diff --git a/NewHorizons/Patches/ToolPatches/ProbeLauncherPatches.cs b/NewHorizons/Patches/ToolPatches/ProbeLauncherPatches.cs new file mode 100644 index 000000000..a2e38c286 --- /dev/null +++ b/NewHorizons/Patches/ToolPatches/ProbeLauncherPatches.cs @@ -0,0 +1,15 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.ToolPatches +{ + [HarmonyPatch(typeof(ProbeLauncher))] + public static class ProbeLauncherPatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(ProbeLauncher.UpdateOrbitalLaunchValues))] + public static bool ProbeLauncher_UpdateOrbitalLaunchValues(ProbeLauncher __instance) + { + return Locator.GetPlayerRulesetDetector()?.GetPlanetoidRuleset()?.GetGravityVolume() != null; + } + } +} diff --git a/NewHorizons/Patches/ToolPatches/SurveyorProbePatches.cs b/NewHorizons/Patches/ToolPatches/SurveyorProbePatches.cs new file mode 100644 index 000000000..a5f33f20a --- /dev/null +++ b/NewHorizons/Patches/ToolPatches/SurveyorProbePatches.cs @@ -0,0 +1,18 @@ +using HarmonyLib; +using System; + +namespace NewHorizons.Patches.ToolPatches +{ + [HarmonyPatch(typeof(SurveyorProbe))] + public static class SurveyorProbePatches + { + // This is to stop the game throwing too many errors if the probe is destroyed by a blackhole + [HarmonyPrefix] + [HarmonyPatch(nameof(SurveyorProbe.IsLaunched))] + public static bool SurveyorProbe_IsLaunched(SurveyorProbe __instance, out bool __result) + { + __result = __instance?.gameObject?.activeSelf ?? false; + return false; + } + } +} diff --git a/NewHorizons/Patches/ToolModeSwapperPatches.cs b/NewHorizons/Patches/ToolPatches/ToolModeSwapperPatches.cs similarity index 73% rename from NewHorizons/Patches/ToolModeSwapperPatches.cs rename to NewHorizons/Patches/ToolPatches/ToolModeSwapperPatches.cs index ec5e4a935..63986a2a4 100644 --- a/NewHorizons/Patches/ToolModeSwapperPatches.cs +++ b/NewHorizons/Patches/ToolPatches/ToolModeSwapperPatches.cs @@ -1,16 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using HarmonyLib; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.ToolPatches { - [HarmonyPatch] + [HarmonyPatch(typeof(ToolModeSwapper))] public static class ToolModeSwapperPatches { - // Patches ToolModeSwapper.EquipToolMode(ToolMode mode) to deny swaps if you're holding a vision torch. // This is critical for preventing swapping to the scout launcher (causes memory slides to fail) but it // just doesn't look right when you switch to other stuff (eg the signalscope), so I'm disabling swapping tools entirely @@ -19,15 +13,15 @@ public static class ToolModeSwapperPatches // to include a check for "is holding vision torch", but I'm not copy/pasting an entire function, no sir // if (((_currentToolMode == ToolMode.None || _currentToolMode == ToolMode.Item) && Locator.GetPlayerSuit().IsWearingSuit(includeTrainingSuit: false)) || ((_currentToolMode == ToolMode.None || _currentToolMode == ToolMode.SignalScope) && OWInput.IsInputMode(InputMode.ShipCockpit))) [HarmonyPrefix] - [HarmonyPatch(typeof(ToolModeSwapper), nameof(ToolModeSwapper.EquipToolMode))] + [HarmonyPatch(nameof(ToolModeSwapper.EquipToolMode))] public static bool ToolModeSwapper_EquipToolMode(ToolModeSwapper __instance, ToolMode mode) { var isHoldingVisionTorch = __instance.GetItemCarryTool()?.GetHeldItemType() == ItemType.VisionTorch; - var swappingToRestrictedTool = - mode == ToolMode.Probe || - mode == ToolMode.SignalScope || + var swappingToRestrictedTool = + mode == ToolMode.Probe || + mode == ToolMode.SignalScope || mode == ToolMode.Translator; - var isInShip = UnityEngine.GameObject.FindObjectOfType()?._playerAtFlightConsole ?? false; + var isInShip = UnityEngine.Object.FindObjectOfType()?._playerAtFlightConsole ?? false; if (!isInShip && isHoldingVisionTorch && swappingToRestrictedTool) return false; diff --git a/NewHorizons/Patches/VisionTorchPatches.cs b/NewHorizons/Patches/VisionTorchPatches.cs deleted file mode 100644 index 9a0b7b56f..000000000 --- a/NewHorizons/Patches/VisionTorchPatches.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using HarmonyLib; -using NewHorizons.Builder.Props; -using UnityEngine; - -namespace NewHorizons.Patches -{ - - [HarmonyPatch] - public static class MindProjectorTriggerPatches - { - [HarmonyPrefix] - [HarmonyPatch(typeof(MindProjectorTrigger), nameof(MindProjectorTrigger.OnTriggerVolumeEntry))] - public static bool MindProjectorTrigger_OnTriggerVolumeEntry(MindProjectorTrigger __instance, GameObject hitObj) - { - var t = hitObj.GetComponent(); - if (t != null) //(hitObj.CompareTag("PrisonerDetector")) - { - __instance._mindProjector.OnProjectionStart += t.onSlidesStart; - __instance._mindProjector.OnProjectionComplete += t.onSlidesComplete; - __instance._mindProjector.SetMindSlideCollection(t.slideCollection); - - __instance.OnBeamStartHitPrisoner.Invoke(); - __instance._mindProjector.Play(reset: true); - __instance._mindProjector.OnProjectionStart += __instance.OnProjectionStart; - __instance._mindProjector.OnProjectionComplete += __instance.OnProjectionComplete; - - Locator.GetPlayerTransform().GetComponent().LockOn(hitObj.transform, Vector3.zero); - __instance._playerLockedOn = true; - return false; - } - - return true; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(MindProjectorTrigger), nameof(MindProjectorTrigger.OnTriggerVolumeExit))] - private static bool MindProjectorTrigger_OnTriggerVolumeExit(MindProjectorTrigger __instance, GameObject hitObj) - { - var t = hitObj.GetComponent(); - if (t != null) //(hitObj.CompareTag("PrisonerDetector")) - { - __instance._mindProjector.OnProjectionStart -= t.onSlidesStart; - __instance._mindProjector.OnProjectionComplete -= t.onSlidesComplete; - } - return true; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(MindSlideProjector), nameof(MindSlideProjector.SetMindSlideCollection))] - private static bool MindSlideProjector_SetMindSlideCollection(MindSlideProjector __instance, MindSlideCollection mindSlideCollection) - { - if (mindSlideCollection == null) return false; - - if (__instance._mindSlideCollection == mindSlideCollection) return false; - - // Original method didn't check if old _slideCollectionItem was null. - if (__instance._slideCollectionItem != null) - { - __instance._slideCollectionItem.onSlideTextureUpdated -= __instance.OnSlideTextureUpdated; - __instance._slideCollectionItem.onPlayBeatAudio -= __instance.OnPlayBeatAudio; - } - - __instance._mindSlideCollection = mindSlideCollection; - __instance._defaultSlideDuration = mindSlideCollection.defaultSlideDuration; - - __instance._slideCollectionItem = mindSlideCollection.slideCollectionContainer; - __instance._slideCollectionItem.onSlideTextureUpdated += __instance.OnSlideTextureUpdated; - __instance._slideCollectionItem.onPlayBeatAudio += __instance.OnPlayBeatAudio; - __instance._slideCollectionItem.Initialize(); - __instance._slideCollectionItem.enabled = false; - - return false; - } - } - - [HarmonyPatch] - public static class VisionTorchItemPatches - { - // This is some dark magic - // this creates a method called base_DropItem that basically just calls OWItem.PickUpItem whenever it (VisionTorchItemPatches.base_PickUpItem) is called - [HarmonyReversePatch] - [HarmonyPatch(typeof(OWItem), nameof(OWItem.DropItem))] - private static void base_DropItem(OWItem instance, Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) { } - - - // Make the vision torch droppable. In the base game you can only drop it if you're in the dream world. - [HarmonyPrefix] - [HarmonyPatch(typeof(VisionTorchItem), nameof(VisionTorchItem.DropItem))] - public static bool VisionTorchItem_DropItem(VisionTorchItem __instance, Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) - { - if (!Locator.GetDreamWorldController().IsInDream()) - { - base_DropItem(__instance, position, normal, parent, sector, customDropTarget); - } - - if (__instance._wasProjecting) __instance._mindProjectorTrigger.SetProjectorActive(false); - - __instance.gameObject.GetComponent().enabled = true; - - return true; - } - } -} diff --git a/NewHorizons/Patches/VolumePatches/BlackHoleVolumePatches.cs b/NewHorizons/Patches/VolumePatches/BlackHoleVolumePatches.cs new file mode 100644 index 000000000..65cd95b7f --- /dev/null +++ b/NewHorizons/Patches/VolumePatches/BlackHoleVolumePatches.cs @@ -0,0 +1,15 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.VolumePatches +{ + [HarmonyPatch(typeof(BlackHoleVolume))] + public static class BlackHoleVolumePatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(BlackHoleVolume.Start))] + public static bool BlackHoleVolume_Start(BlackHoleVolume __instance) + { + return __instance._whiteHole == null; + } + } +} diff --git a/NewHorizons/Patches/DestructionVolumePatches.cs b/NewHorizons/Patches/VolumePatches/DestructionVolumePatches.cs similarity index 77% rename from NewHorizons/Patches/DestructionVolumePatches.cs rename to NewHorizons/Patches/VolumePatches/DestructionVolumePatches.cs index e29e3d024..3203e3359 100644 --- a/NewHorizons/Patches/DestructionVolumePatches.cs +++ b/NewHorizons/Patches/VolumePatches/DestructionVolumePatches.cs @@ -6,16 +6,16 @@ using System.Text; using System.Threading.Tasks; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.VolumePatches { - [HarmonyPatch] + [HarmonyPatch(typeof(DestructionVolume))] public static class DestructionVolumePatches { [HarmonyPrefix] - [HarmonyPatch(typeof(DestructionVolume), nameof(DestructionVolume.Vanish))] - public static bool DestructionVolume_Vanish(OWRigidbody __0) + [HarmonyPatch(nameof(DestructionVolume.Vanish))] + public static bool DestructionVolume_Vanish(OWRigidbody bodyToVanish) { - var quantumPlanet = __0.gameObject.GetComponent(); + var quantumPlanet = bodyToVanish.gameObject.GetComponent(); if (quantumPlanet == null) return true; diff --git a/NewHorizons/Patches/VolumePatches/FluidVolumePatches.cs b/NewHorizons/Patches/VolumePatches/FluidVolumePatches.cs new file mode 100644 index 000000000..a85acc0f3 --- /dev/null +++ b/NewHorizons/Patches/VolumePatches/FluidVolumePatches.cs @@ -0,0 +1,20 @@ +using HarmonyLib; +using UnityEngine; + +namespace NewHorizons.Patches.VolumePatches +{ + [HarmonyPatch(typeof(FluidVolume))] + public static class FluidVolumePatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(FluidVolume.GetDepthAtPosition))] + public static bool FluidVolume_GetDepthAtPosition(FluidVolume __instance, ref float __result, Vector3 worldPosition) + { + if (__instance is not RadialFluidVolume radialFluidVolume) return true; + + Vector3 vector = radialFluidVolume.transform.InverseTransformPoint(worldPosition); + __result = Mathf.Sqrt(vector.x * vector.x + vector.z * vector.z + vector.y * vector.y) - radialFluidVolume._radius; + return false; + } + } +} diff --git a/NewHorizons/Patches/BramblePatches.cs b/NewHorizons/Patches/VolumePatches/FogWarpVolumePatches.cs similarity index 75% rename from NewHorizons/Patches/BramblePatches.cs rename to NewHorizons/Patches/VolumePatches/FogWarpVolumePatches.cs index fcec7f303..f63bad812 100644 --- a/NewHorizons/Patches/BramblePatches.cs +++ b/NewHorizons/Patches/VolumePatches/FogWarpVolumePatches.cs @@ -1,20 +1,14 @@ using HarmonyLib; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using UnityEngine; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.VolumePatches { [HarmonyPatch] - public static class BramblePatches + public static class FogWarpVolumePatches { - [HarmonyPrefix] [HarmonyPatch(typeof(SphericalFogWarpVolume), nameof(SphericalFogWarpVolume.IsProbeOnly))] - public static bool SphericalFogWarpVolume_IsProbeOnly(SphericalFogWarpVolume __instance, ref bool __result) + public static bool SphericalFogWarpVolume_IsProbeOnly(SphericalFogWarpVolume __instance, out bool __result) { __result = Mathf.Approximately(__instance._exitRadius / __instance._warpRadius, 2f); // Check the ratio between these to determine if seed, instead of just < 10 return false; @@ -22,7 +16,7 @@ public static bool SphericalFogWarpVolume_IsProbeOnly(SphericalFogWarpVolume __i [HarmonyPrefix] [HarmonyPatch(typeof(FogWarpVolume), nameof(FogWarpVolume.GetFogThickness))] - public static bool FogWarpVolume_GetFogThickness(FogWarpVolume __instance, ref float __result) + public static bool FogWarpVolume_GetFogThickness(FogWarpVolume __instance, out float __result) { if (__instance is InnerFogWarpVolume sph) __result = sph._exitRadius; else __result = 50; // 50f is hardcoded as the return value in the base game diff --git a/NewHorizons/Patches/VolumePatches/VanishVolumePatches.cs b/NewHorizons/Patches/VolumePatches/VanishVolumePatches.cs new file mode 100644 index 000000000..9b1b8ab21 --- /dev/null +++ b/NewHorizons/Patches/VolumePatches/VanishVolumePatches.cs @@ -0,0 +1,15 @@ +using HarmonyLib; + +namespace NewHorizons.Patches.VolumePatches +{ + [HarmonyPatch(typeof(VanishVolume))] + public static class VanishVolumePatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(VanishVolume.Shrink))] + public static bool VanishVolume_Shrink(VanishVolume __instance, OWRigidbody bodyToShrink) + { + return __instance != null && __instance.transform != null && __instance._shrinkingBodies != null && __instance._shrinkingBodyLocationData != null && bodyToShrink != null; + } + } +} diff --git a/NewHorizons/Patches/VolumePatches/WhiteHoleVolumePatches.cs b/NewHorizons/Patches/VolumePatches/WhiteHoleVolumePatches.cs new file mode 100644 index 000000000..0abf582f3 --- /dev/null +++ b/NewHorizons/Patches/VolumePatches/WhiteHoleVolumePatches.cs @@ -0,0 +1,28 @@ +using HarmonyLib; +using System; +using System.Collections.Generic; + +namespace NewHorizons.Patches.VolumePatches +{ + [HarmonyPatch(typeof(WhiteHoleVolume))] + public static class WhiteHoleVolumePatches + { + // To fix custom white holes + [HarmonyPrefix] + [HarmonyPatch(nameof(WhiteHoleVolume.Awake))] + public static bool WhiteHoleVolume_Awake(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; + } + } +} diff --git a/NewHorizons/Patches/EyeCoordinatePromptTriggerPatches.cs b/NewHorizons/Patches/WarpPatches/EyeCoordinatePromptTriggerPatches.cs similarity index 74% rename from NewHorizons/Patches/EyeCoordinatePromptTriggerPatches.cs rename to NewHorizons/Patches/WarpPatches/EyeCoordinatePromptTriggerPatches.cs index ed827a6f7..af2cb69bb 100644 --- a/NewHorizons/Patches/EyeCoordinatePromptTriggerPatches.cs +++ b/NewHorizons/Patches/WarpPatches/EyeCoordinatePromptTriggerPatches.cs @@ -2,13 +2,13 @@ using NewHorizons.Handlers; using UnityEngine; -namespace NewHorizons.Patches +namespace NewHorizons.Patches.WarpPatches { - [HarmonyPatch] + [HarmonyPatch(typeof(EyeCoordinatePromptTrigger))] public static class EyeCoordinatePromptTriggerPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(EyeCoordinatePromptTrigger), nameof(EyeCoordinatePromptTrigger.Update))] + [HarmonyPatch(nameof(EyeCoordinatePromptTrigger.Update))] public static bool EyeCoordinatePromptTrigger_Update(EyeCoordinatePromptTrigger __instance) { var showPrompts = __instance._warpController.HasPower(); @@ -22,10 +22,10 @@ public static bool EyeCoordinatePromptTrigger_Update(EyeCoordinatePromptTrigger } [HarmonyPrefix] - [HarmonyPatch(typeof(EyeCoordinatePromptTrigger), nameof(EyeCoordinatePromptTrigger.OnExit))] - public static void EyeCoordinatePromptTrigger_OnExit(GameObject __0) + [HarmonyPatch(nameof(EyeCoordinatePromptTrigger.OnExit))] + public static void EyeCoordinatePromptTrigger_OnExit(GameObject hitObj) { - if (__0.CompareTag("PlayerDetector")) + if (hitObj.CompareTag("PlayerDetector")) { VesselCoordinatePromptHandler.SetPromptVisibility(false); } diff --git a/NewHorizons/Patches/WarpPatches/NomaiCoordinateInterfacePatches.cs b/NewHorizons/Patches/WarpPatches/NomaiCoordinateInterfacePatches.cs new file mode 100644 index 000000000..38d1aa36f --- /dev/null +++ b/NewHorizons/Patches/WarpPatches/NomaiCoordinateInterfacePatches.cs @@ -0,0 +1,22 @@ +using HarmonyLib; +using NewHorizons.Utility; + +namespace NewHorizons.Patches.WarpPatches +{ + [HarmonyPatch(typeof(NomaiCoordinateInterface))] + public static class NomaiCoordinateInterfacePatches + { + [HarmonyPrefix] + [HarmonyPatch(nameof(NomaiCoordinateInterface.SetPillarRaised), new System.Type[] { typeof(bool) })] + public static bool NomaiCoordinateInterface_SetPillarRaised(NomaiCoordinateInterface __instance, bool raised) + { + if (raised) + return !( + !__instance._powered || + __instance.CheckEyeCoordinates() && Main.Instance.CurrentStarSystem != "EyeOfTheUniverse" || + __instance.CheckAllCoordinates(out var targetSystem) && Main.Instance.CurrentStarSystem != targetSystem + ); + return true; + } + } +} \ No newline at end of file diff --git a/NewHorizons/Patches/WarpDrivePatches.cs b/NewHorizons/Patches/WarpPatches/ShipCockpitControllerPatches.cs similarity index 77% rename from NewHorizons/Patches/WarpDrivePatches.cs rename to NewHorizons/Patches/WarpPatches/ShipCockpitControllerPatches.cs index 4520fa977..b17b02486 100644 --- a/NewHorizons/Patches/WarpDrivePatches.cs +++ b/NewHorizons/Patches/WarpPatches/ShipCockpitControllerPatches.cs @@ -1,14 +1,13 @@ using HarmonyLib; using NewHorizons.Handlers; -using NewHorizons.Utility; -using UnityEngine; -namespace NewHorizons.Patches + +namespace NewHorizons.Patches.WarpPatches { - [HarmonyPatch] - public static class WarpDrivePatches + [HarmonyPatch(typeof(ShipCockpitController))] + public static class ShipCockpitControllerPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(ShipCockpitController), nameof(ShipCockpitController.Update))] + [HarmonyPatch(nameof(ShipCockpitController.Update))] public static bool ShipCockpitController_Update(ShipCockpitController __instance) { if (!Main.HasWarpDrive) return true; diff --git a/NewHorizons/Patches/NomaiCoordinatePatches.cs b/NewHorizons/Patches/WarpPatches/VesselWarpControllerPatches.cs similarity index 69% rename from NewHorizons/Patches/NomaiCoordinatePatches.cs rename to NewHorizons/Patches/WarpPatches/VesselWarpControllerPatches.cs index 5191ceca8..39eb3d729 100644 --- a/NewHorizons/Patches/NomaiCoordinatePatches.cs +++ b/NewHorizons/Patches/WarpPatches/VesselWarpControllerPatches.cs @@ -1,22 +1,14 @@ using HarmonyLib; using NewHorizons.Utility; -using UnityEngine; -namespace NewHorizons.Patches +using NewHorizons.Utility.OWUtilities; + +namespace NewHorizons.Patches.WarpPatches { - [HarmonyPatch] - public static class NomaiCoordinatePatches + [HarmonyPatch(typeof(VesselWarpController))] + public static class VesselWarpControllerPatches { [HarmonyPrefix] - [HarmonyPatch(typeof(NomaiCoordinateInterface), nameof(NomaiCoordinateInterface.SetPillarRaised), new System.Type[] { typeof(bool) })] - public static bool NomaiCoordinateInterface_SetPillarRaised(NomaiCoordinateInterface __instance, bool raised) - { - if (raised) - return !(!__instance._powered || (__instance.CheckEyeCoordinates() && Main.Instance.CurrentStarSystem != "EyeOfTheUniverse") || (__instance.CheckAllCoordinates(out string targetSystem) && Main.Instance.CurrentStarSystem != targetSystem)); - return true; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(VesselWarpController), nameof(VesselWarpController.WarpVessel))] + [HarmonyPatch(nameof(VesselWarpController.WarpVessel))] public static bool VesselWarpController_WarpVessel(VesselWarpController __instance, bool debugWarp) { if (!Main.Instance.IsWarpingFromVessel && TimeLoop.GetLoopCount() < 2) @@ -29,11 +21,12 @@ public static bool VesselWarpController_WarpVessel(VesselWarpController __instan PlayerData.SaveWarpedToTheEye(TimeLoopUtilities.GetVanillaSecondsRemaining()); LoadManager.EnableAsyncLoadTransition(); + return false; } [HarmonyPrefix] - [HarmonyPatch(typeof(VesselWarpController), nameof(VesselWarpController.CheckSystemActivation))] + [HarmonyPatch(nameof(VesselWarpController.CheckSystemActivation))] public static void VesselWarpController_CheckSystemActivation(VesselWarpController __instance) { if (Locator.GetEyeStateManager() == null && Main.Instance.CurrentStarSystem != "EyeOfTheUniverse") @@ -46,19 +39,19 @@ public static void VesselWarpController_CheckSystemActivation(VesselWarpControll } [HarmonyPrefix] - [HarmonyPatch(typeof(VesselWarpController), nameof(VesselWarpController.OnSlotActivated))] + [HarmonyPatch(nameof(VesselWarpController.OnSlotActivated))] public static bool VesselWarpController_OnSlotActivated(VesselWarpController __instance, NomaiInterfaceSlot slot) { bool canWarpToEye = __instance._coordinateInterface.CheckEyeCoordinates(); bool canWarpToStarSystem = __instance._coordinateInterface.CheckAllCoordinates(out string targetSystem); - if (slot == __instance._warpVesselSlot && __instance._hasPower && ((canWarpToEye && Main.Instance.CurrentStarSystem != "EyeOfTheUniverse") || (canWarpToStarSystem && targetSystem != Main.Instance.CurrentStarSystem)) && __instance._blackHole.GetState() == SingularityController.State.Collapsed) + if (slot == __instance._warpVesselSlot && __instance._hasPower && (canWarpToEye && Main.Instance.CurrentStarSystem != "EyeOfTheUniverse" || canWarpToStarSystem && targetSystem != Main.Instance.CurrentStarSystem) && __instance._blackHole.GetState() == SingularityController.State.Collapsed) { __instance._blackHole.Create(); RumbleManager.StartVesselWarp(); __instance._openingBlackHole = true; __instance.enabled = true; Locator.GetPauseCommandListener().AddPauseCommandLock(); - if (canWarpToEye || (canWarpToStarSystem && targetSystem == "EyeOfTheUniverse")) + if (canWarpToEye || canWarpToStarSystem && targetSystem == "EyeOfTheUniverse") { Main.Instance._currentStarSystem = "EyeOfTheUniverse"; LoadManager.LoadSceneAsync(OWScene.EyeOfTheUniverse, false, LoadManager.FadeType.ToWhite); diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index 624fc8218..b21da199d 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -658,14 +658,33 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The physical position of the node", + "rotation": { + "description": "Rotation of the object", "$ref": "#/definitions/MVector3" }, - "rotation": { - "description": "The physical rotation of the node", + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", "$ref": "#/definitions/MVector3" }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, "scale": { "type": "number", "description": "The physical scale of the node, as a multiplier of the original size. \nNodes are 150m across, seeds are 10m across.", @@ -997,7 +1016,7 @@ "type": "array", "description": "Add translatable text to this planet", "items": { - "$ref": "#/definitions/NomaiTextInfo" + "$ref": "#/definitions/TranslatorTextInfo" } }, "proxyDetails": { @@ -1069,6 +1088,20 @@ "items": { "$ref": "#/definitions/RemoteInfo" } + }, + "warpReceivers": { + "type": "array", + "description": "Add warp pad receivers to this planet. These are the warp pads you are sent to from Ash Twin.", + "items": { + "$ref": "#/definitions/NomaiWarpReceiverInfo" + } + }, + "warpTransmitters": { + "type": "array", + "description": "Add warp pad transmitters to this planet. These are the warp pads seen on the Ash Twin.", + "items": { + "$ref": "#/definitions/NomaiWarpTransmitterInfo" + } } } }, @@ -1076,13 +1109,32 @@ "type": "object", "additionalProperties": false, "properties": { - "rename": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { "type": "string", - "description": "An optional rename of the detail" + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, - "alignToNormal": { + "isRelativeToParent": { "type": "boolean", - "description": "Do we override rotation and try to automatically align this object to stand upright on the body's surface?" + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" }, "assetBundle": { "type": "string", @@ -1092,10 +1144,6 @@ "type": "string", "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle" }, - "position": { - "description": "Position of this prop relative to the body's center", - "$ref": "#/definitions/MVector3" - }, "removeChildren": { "type": "array", "description": "A list of children to remove from this detail", @@ -1107,10 +1155,6 @@ "type": "boolean", "description": "Do we reset all the components on this object? Useful for certain props that have dialogue components attached to\nthem." }, - "rotation": { - "description": "Rotate this prop", - "$ref": "#/definitions/MVector3" - }, "scale": { "type": "number", "description": "Scale the prop", @@ -1125,14 +1169,6 @@ "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)." - }, - "isRelativeToParent": { - "type": "boolean", - "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." - }, "keepLoaded": { "type": "boolean", "description": "Should this detail stay loaded even if you're outside the sector (good for very large props)" @@ -1159,6 +1195,22 @@ "type": "object", "additionalProperties": false, "properties": { + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, "blockAfterPersistentCondition": { "type": "string", "description": "Prevents the dialogue from being created after a specific persistent condition is set. Useful for remote dialogue\ntriggers that you want to have happen only once." @@ -1172,54 +1224,60 @@ "type": "string", "description": "If this dialogue is meant for a character, this is the relative path from the planet to that character's\nCharacterAnimController, TravelerController, TravelerEyeController (eye of the universe), FacePlayerWhenTalking, or SolanumAnimController.\n\nIf none of those components are present it will add a FacePlayerWhenTalking component." }, - "position": { - "description": "When you enter into dialogue, you will look here.", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", - "description": "Radius of the spherical collision volume where you get the \"talk to\" prompt when looking at. If you use a\nremoteTriggerPosition, you can set this to 0 to make the dialogue only trigger remotely.", + "description": "Radius of the spherical collision volume where you get the \"talk to\" prompt when looking at. If you use a\nremoteTrigger, you can set this to 0 to make the dialogue only trigger remotely.", "format": "float" }, - "remoteTriggerPosition": { - "description": "Allows you to trigger dialogue from a distance when you walk into an area.", - "$ref": "#/definitions/MVector3" - }, "range": { "type": "number", "description": "Distance from radius the prompt appears", "format": "float", "default": 2.0 }, - "remoteTriggerRadius": { - "type": "number", - "description": "The radius of the remote trigger volume.", - "format": "float" - }, - "remoteTriggerPrereqCondition": { - "type": "string", - "description": "If setting up a remote trigger volume, this conditions must be met for it to trigger. Note: This is a dialogue condition, not a persistent condition." + "remoteTrigger": { + "description": "Allows you to trigger dialogue from a distance when you walk into an area.", + "$ref": "#/definitions/RemoteTriggerInfo" }, "xmlFile": { "type": "string", "description": "Relative path to the xml file defining the dialogue." }, + "flashlightToggle": { + "description": "What type of flashlight toggle to do when dialogue is interacted with", + "default": "none", + "$ref": "#/definitions/FlashlightToggle" + } + } + }, + "RemoteTriggerInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional and rotational coordinates are relative to the animation controller instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "Optionally rename the dialogue object. The remote trigger volume will be renamed to have this as a prefix." + "description": "An optional rename of this object" }, - "parentPath": { - "type": "string", - "description": "Optionally set the parent object that the dialogue and remote trigger will be attached to" + "radius": { + "type": "number", + "description": "The radius of the remote trigger volume.", + "format": "float" }, - "flashlightToggle": { - "description": "What type of flashlight toggle to do when dialogue is interacted with", - "default": "none", - "$ref": "#/definitions/FlashlightToggle" + "prereqCondition": { + "type": "string", + "description": "This condition must be met for the remote trigger volume to trigger." } } }, @@ -1241,16 +1299,8 @@ "type": "object", "additionalProperties": false, "properties": { - "cloaked": { - "type": "boolean", - "description": "Whether this location is cloaked" - }, - "id": { - "type": "string", - "description": "ID of the entry this location relates to" - }, "position": { - "description": "The position of this entry location", + "description": "Position of the object", "$ref": "#/definitions/MVector3" }, "parentPath": { @@ -1264,6 +1314,14 @@ "rename": { "type": "string", "description": "An optional rename of this object" + }, + "cloaked": { + "type": "boolean", + "description": "Whether this location is cloaked" + }, + "id": { + "type": "string", + "description": "ID of the entry this location relates to" } } }, @@ -1271,10 +1329,33 @@ "type": "object", "additionalProperties": false, "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, "position": { - "description": "Position of the geyser", + "description": "Position of the object", "$ref": "#/definitions/MVector3" }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, "offset": { "type": "number", "description": "Vertical offset of the geyser. From 0, the bubbles start at a height of 10, the shaft at 67, and the spout at 97.5.", @@ -1320,21 +1401,40 @@ "description": "Loudness of the geyser", "format": "float", "default": 0.7 + } + } + }, + "TranslatorTextInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, "rename": { "type": "string", "description": "An optional rename of this object" - } - } - }, - "NomaiTextInfo": { - "type": "object", - "additionalProperties": false, - "properties": { + }, "arcInfo": { "type": "array", "description": "Additional information about each arc in the text", @@ -1342,48 +1442,28 @@ "$ref": "#/definitions/NomaiTextArcInfo" } }, - "normal": { - "description": "The normal vector for this object. Used for writing on walls and positioning computers.", - "$ref": "#/definitions/MVector3" - }, - "position": { - "description": "Position of the root of this text", - "$ref": "#/definitions/MVector3" - }, - "rotation": { - "description": "The euler angle rotation of this object. Not required if setting the normal. Computers and cairns will orient\nthemselves to the surface of the planet automatically.", - "$ref": "#/definitions/MVector3" - }, "seed": { "type": "integer", "description": "The random seed used to pick what the text arcs will look like.", "format": "int32" }, + "normal": { + "description": "Only for wall text. Aligns wall text to face towards the given direction, with 'up' oriented relative to its current rotation or alignment.", + "$ref": "#/definitions/MVector3" + }, "type": { "description": "The type of object this is.", "default": "wall", "$ref": "#/definitions/NomaiTextType" }, "location": { - "description": "The location of this object. ", + "description": "The location of this object. Arcs will be blue if their locations match the wall, else orange.", "default": "unspecified", "$ref": "#/definitions/NomaiTextLocation" }, "xmlFile": { "type": "string", "description": "The relative path to the xml file for this object." - }, - "parentPath": { - "type": "string", - "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." - }, - "isRelativeToParent": { - "type": "boolean", - "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." - }, - "rename": { - "type": "string", - "description": "An optional rename of this object" } } }, @@ -1391,49 +1471,31 @@ "type": "object", "additionalProperties": false, "properties": { - "keepAutoPlacement": { - "type": "boolean", - "description": "Whether to skip modifying this spiral's placement, and instead keep the automatically determined placement." - }, - "mirror": { - "type": "boolean", - "description": "Whether to flip the spiral from left-curling to right-curling or vice versa." - }, - "position": { - "description": "The local position of this object on the wall.", - "$ref": "#/definitions/MVector2" - }, "type": { "description": "The type of text to display.", "default": "adult", "$ref": "#/definitions/NomaiTextArcType" }, - "variation": { - "type": "integer", - "description": "Which variation of the chosen type to place. If not specified, a random variation will be selected based on the seed provided in the parent module.", - "format": "int32", - "default": -1 + "position": { + "description": "The local position of this object on the wall. If specified, auto spiral will not touch this arc.", + "$ref": "#/definitions/MVector2" }, "zRotation": { - "type": "number", - "description": "The z euler angle for this arc.", + "type": [ + "null", + "number" + ], + "description": "The z euler angle for this arc. If specified, auto spiral will not touch this arc.", "format": "float", "maximum": 360.0, "minimum": 0.0 - } - } - }, - "MVector2": { - "type": "object", - "additionalProperties": false, - "properties": { - "x": { - "type": "number", - "format": "float" }, - "y": { - "type": "number", - "format": "float" + "mirror": { + "type": [ + "boolean", + "null" + ], + "description": "Whether to flip the spiral from left-curling to right-curling or vice versa. If specified, auto spiral will not touch this arc." } } }, @@ -1451,6 +1513,20 @@ "stranger" ] }, + "MVector2": { + "type": "object", + "additionalProperties": false, + "properties": { + "x": { + "type": "number", + "format": "float" + }, + "y": { + "type": "number", + "format": "float" + } + } + }, "NomaiTextType": { "type": "string", "description": "", @@ -1463,7 +1539,8 @@ "PreCrashRecorder", "PreCrashComputer", "Trailmarker", - "CairnVariant" + "CairnVariant", + "Whiteboard" ], "enum": [ "wall", @@ -1474,7 +1551,8 @@ "preCrashRecorder", "preCrashComputer", "trailmarker", - "cairnVariant" + "cairnVariant", + "whiteboard" ] }, "NomaiTextLocation": { @@ -1495,15 +1573,20 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "Position of the raft", + "rotation": { + "description": "Rotation of the object", "$ref": "#/definitions/MVector3" }, - "acceleration": { - "type": "number", - "description": "Acceleration of the raft. Default acceleration is 5.", - "format": "float", - "default": 5.0 + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" }, "parentPath": { "type": "string", @@ -1516,6 +1599,12 @@ "rename": { "type": "string", "description": "An optional rename of this object" + }, + "acceleration": { + "type": "number", + "description": "Acceleration of the raft. Default acceleration is 5.", + "format": "float", + "default": 5.0 } } }, @@ -1590,10 +1679,33 @@ "type": "object", "additionalProperties": false, "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, "position": { - "description": "The position of this slideshow.", + "description": "Position of the object", "$ref": "#/definitions/MVector3" }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, "reveals": { "type": "array", "description": "The ship log facts revealed after finishing this slide reel.", @@ -1608,10 +1720,6 @@ "type": "string" } }, - "rotation": { - "description": "The rotation of this slideshow.", - "$ref": "#/definitions/MVector3" - }, "slides": { "type": "array", "description": "The list of slides for this object.", @@ -1623,18 +1731,6 @@ "description": "The type of object this is.", "default": "slideReel", "$ref": "#/definitions/SlideShowType" - }, - "parentPath": { - "type": "string", - "description": "The relative path from the planet to the parent of this slideshow. Optional (will default to the root sector)." - }, - "isRelativeToParent": { - "type": "boolean", - "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." - }, - "rename": { - "type": "string", - "description": "An optional rename of this object" } } }, @@ -1767,14 +1863,33 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this socket", + "rotation": { + "description": "Rotation of the object", "$ref": "#/definitions/MVector3" }, - "rotation": { - "description": "The rotation the quantum object will take if it's occupying this socket", + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", "$ref": "#/definitions/MVector3" }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, "probability": { "type": "number", "description": "The probability any props that are part of this group will occupy this socket", @@ -1787,6 +1902,33 @@ "type": "object", "additionalProperties": false, "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, "elevation": { "type": "number", "description": "Alternative to setting the position. Will choose a random place at this elevation.", @@ -1798,10 +1940,6 @@ "format": "float", "default": 30.0 }, - "position": { - "description": "Position of the tornado", - "$ref": "#/definitions/MVector3" - }, "tint": { "description": "The colour of the tornado.", "$ref": "#/definitions/MColor" @@ -1837,18 +1975,6 @@ "description": "Fluid type for sounds/effects when colliding with this tornado.", "default": "cloud", "$ref": "#/definitions/FluidType" - }, - "parentPath": { - "type": "string", - "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." - }, - "isRelativeToParent": { - "type": "boolean", - "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." - }, - "rename": { - "type": "string", - "description": "An optional rename of this object" } } }, @@ -1870,6 +1996,33 @@ "type": "object", "additionalProperties": false, "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, "lavaTint": { "description": "The colour of the meteor's lava.", "$ref": "#/definitions/MColor" @@ -1898,10 +2051,6 @@ "format": "float", "default": 50.0 }, - "position": { - "description": "Position of this volcano.", - "$ref": "#/definitions/MVector3" - }, "scale": { "type": "number", "description": "Scale of the meteors.", @@ -1910,6 +2059,27 @@ "stoneTint": { "description": "The colour of the meteor's stone.", "$ref": "#/definitions/MColor" + } + } + }, + "SingularityModule": { + "type": "object", + "additionalProperties": false, + "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" }, "parentPath": { "type": "string", @@ -1922,13 +2092,7 @@ "rename": { "type": "string", "description": "An optional rename of this object" - } - } - }, - "SingularityModule": { - "type": "object", - "additionalProperties": false, - "properties": { + }, "curve": { "type": "array", "description": "Scale this object over time", @@ -1944,14 +2108,6 @@ "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" - }, - "rotation": { - "description": "Rotation of the singularity. Determines the direction you come out of a white hole", - "$ref": "#/definitions/MVector3" - }, "horizonRadius": { "type": "number", "description": "Radius of the event horizon (solid part)", @@ -1982,18 +2138,6 @@ "format": "int32", "maximum": 3500.0, "minimum": 2501.0 - }, - "parentPath": { - "type": "string", - "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." - }, - "isRelativeToParent": { - "type": "boolean", - "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." - }, - "rename": { - "type": "string", - "description": "An optional rename of this object" } } }, @@ -2013,6 +2157,22 @@ "type": "object", "additionalProperties": false, "properties": { + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, "audio": { "type": "string", "description": "The audio to use. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list." @@ -2047,10 +2207,6 @@ "description": "`false` if the player can hear the signal without equipping the signal-scope.", "default": true }, - "position": { - "description": "Position of the signal's source", - "$ref": "#/definitions/MVector3" - }, "reveals": { "type": "string", "description": "A ship log fact to reveal when the signal is identified.", @@ -2061,14 +2217,6 @@ "description": "Radius of the sphere giving off the signal.", "format": "float", "default": 1.0 - }, - "parentPath": { - "type": "string", - "description": "The relative path from the planet to the parent of this signal. Optional (will default to the root sector)." - }, - "isRelativeToParent": { - "type": "boolean", - "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." } } }, @@ -2105,19 +2253,19 @@ "type": "object", "additionalProperties": false, "properties": { - "nomaiText": { - "type": "array", - "description": "The text for each stone", - "items": { - "$ref": "#/definitions/SharedNomaiTextInfo" - } - }, - "position": { - "description": "The location of this platform.", + "rotation": { + "description": "Rotation of the object", "$ref": "#/definitions/MVector3" }, - "rotation": { - "description": "The rotation of this platform.", + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", "$ref": "#/definitions/MVector3" }, "parentPath": { @@ -2132,6 +2280,13 @@ "type": "string", "description": "An optional rename of this object" }, + "nomaiText": { + "type": "array", + "description": "The text for each stone", + "items": { + "$ref": "#/definitions/SharedNomaiTextInfo" + } + }, "disableWall": { "type": "boolean", "description": "Disable the wall, leaving only the pedestal and text." @@ -2159,7 +2314,7 @@ "format": "int32" }, "location": { - "description": "The location of this object. ", + "description": "The location of this object. Arcs will be blue if their locations match the wall, else orange.", "default": "unspecified", "$ref": "#/definitions/NomaiTextLocation" }, @@ -2173,16 +2328,150 @@ } } }, - "PlatformInfo": { + "PlatformInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, + "reveals": { + "type": "string", + "description": "A ship log fact to reveal when the platform is connected to.", + "default": "" + }, + "disableStructure": { + "type": "boolean", + "description": "Disable the structure, leaving only the pedestal." + }, + "disablePool": { + "type": "boolean", + "description": "Disable the pool that rises when you place a stone." + } + } + }, + "StoneInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + } + } + }, + "NomaiWarpReceiverInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "frequency": { + "type": "string" + }, + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, + "alignmentTargetBody": { + "type": "string", + "description": "The body the transmitter must be aligned with to warp to this receiver.\nDefaults to the body the receiver is on." + }, + "computer": { + "description": "Will create a modern Nomai computer linked to this receiver.", + "$ref": "#/definitions/NomaiWarpComputerLoggerInfo" + }, + "detailed": { + "type": "boolean", + "description": "Set to true if you want to include Nomai ruin details around the warp pad." + } + } + }, + "NomaiWarpComputerLoggerInfo": { "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this platform.", + "rotation": { + "description": "Rotation of the object", "$ref": "#/definitions/MVector3" }, - "rotation": { - "description": "The rotation of this platform.", + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", "$ref": "#/definitions/MVector3" }, "parentPath": { @@ -2196,32 +2485,29 @@ "rename": { "type": "string", "description": "An optional rename of this object" - }, - "reveals": { - "type": "string", - "description": "A ship log fact to reveal when the platform is connected to.", - "default": "" - }, - "disableStructure": { - "type": "boolean", - "description": "Disable the structure, leaving only the pedestal." - }, - "disablePool": { - "type": "boolean", - "description": "Disable the pool that rises when you place a stone." } } }, - "StoneInfo": { + "NomaiWarpTransmitterInfo": { "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this stone.", - "$ref": "#/definitions/MVector3" + "frequency": { + "type": "string" }, "rotation": { - "description": "The rotation of this stone.", + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", "$ref": "#/definitions/MVector3" }, "parentPath": { @@ -2235,6 +2521,16 @@ "rename": { "type": "string", "description": "An optional rename of this object" + }, + "alignmentWindow": { + "type": "number", + "description": "In degrees. Gives a margin of error for alignments.", + "format": "float", + "default": 5.0 + }, + "flipAlignment": { + "type": "boolean", + "description": "This makes the alignment happen if the destination planet is BELOW you rather than above." } } }, @@ -2490,25 +2786,87 @@ "type": "object", "additionalProperties": false, "properties": { - "playerSpawnPoint": { - "description": "If you want the player to spawn on the new body, set a value for this. Press `P` in game with Debug mode on to have\nthe game log the position you're looking at to find a good value for this.", - "$ref": "#/definitions/MVector3" - }, - "playerSpawnRotation": { - "description": "Euler angles by which the player will be oriented.", - "$ref": "#/definitions/MVector3" + "playerSpawn": { + "description": "If you want the player to spawn on the new body, set a value for this.", + "$ref": "#/definitions/PlayerSpawnPoint" }, - "shipSpawnPoint": { + "shipSpawn": { "description": "Required for the system to be accessible by warp drive.", + "$ref": "#/definitions/ShipSpawnPoint" + } + } + }, + "PlayerSpawnPoint": { + "type": "object", + "additionalProperties": false, + "properties": { + "rotation": { + "description": "Rotation of the object", "$ref": "#/definitions/MVector3" }, - "shipSpawnRotation": { - "description": "Euler angles by which the ship will be oriented.", + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", "$ref": "#/definitions/MVector3" }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, "startWithSuit": { "type": "boolean", "description": "If you spawn on a planet with no oxygen, you probably want to set this to true ;;)" + }, + "isDefault": { + "type": "boolean", + "description": "Whether this planet's spawn point is the one the player will initially spawn at, if multiple spawn points exist." + } + } + }, + "ShipSpawnPoint": { + "type": "object", + "additionalProperties": false, + "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" } } }, @@ -2833,27 +3191,27 @@ "format": "int32", "default": 1 }, - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "audio": { "type": "string", @@ -2968,27 +3326,27 @@ "type": "boolean", "description": "Whether this volume only affects the player and ship." }, - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "deathType": { "description": "The type of death the player will have if they enter this volume.", @@ -3051,27 +3409,27 @@ "format": "int32", "default": 1 }, - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "density": { "type": "number", @@ -3124,27 +3482,27 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "type": { "description": "The type of hazard for this volume.", @@ -3214,26 +3572,26 @@ "additionalProperties": false, "properties": { "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", + "description": "Position of the object", "$ref": "#/definitions/MVector3" }, - "radius": { - "type": "number", - "description": "The radius of this volume.", - "format": "float", - "default": 1.0 - }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" + }, + "radius": { + "type": "number", + "description": "The radius of this volume.", + "format": "float", + "default": 1.0 } } }, @@ -3241,27 +3599,27 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "target": { "description": "What the notification will show for.", @@ -3312,27 +3670,27 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "treeVolume": { "type": "boolean", @@ -3369,27 +3727,27 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "maxAngle": { "type": "number", @@ -3492,27 +3850,27 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "minImpactSpeed": { "type": "number", @@ -3532,27 +3890,27 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "overrideProbeSpeed": { "type": "boolean", @@ -3582,27 +3940,27 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "thrustLimit": { "type": "number", @@ -3626,27 +3984,27 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "speedLimit": { "type": "number", @@ -3698,27 +4056,27 @@ "format": "int32", "default": 1 }, - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "frostRate": { "type": "number", @@ -3752,27 +4110,27 @@ "format": "int32", "default": 1 }, - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "dropletRate": { "type": "number", @@ -3792,27 +4150,27 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "layer": { "type": "integer", @@ -3832,27 +4190,27 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "targetStarSystem": { "type": "string", @@ -3865,31 +4223,40 @@ "type": "object", "additionalProperties": false, "properties": { - "position": { - "description": "The location of this volume. Optional (will default to 0,0,0).", - "$ref": "#/definitions/MVector3" - }, "radius": { "type": "number", "description": "The radius of this volume.", "format": "float", "default": 1.0 }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, "isRelativeToParent": { "type": "boolean", - "description": "Whether the positional coordinates are relative to parent instead of the root planet object." + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." }, "rename": { "type": "string", - "description": "An optional rename of this volume." + "description": "An optional rename of this object" }, "creditsType": { "default": "fast", "$ref": "#/definitions/CreditsType" + }, + "gameOverText": { + "type": "string", + "description": "Text displayed in orange on game over. For localization, put translations under UI." + }, + "deathType": { + "description": "The type of death the player will have if they enter this volume.", + "default": "default", + "$ref": "#/definitions/DeathType" } } }, diff --git a/NewHorizons/Schemas/star_system_schema.json b/NewHorizons/Schemas/star_system_schema.json index a4185c828..f7d281b89 100644 --- a/NewHorizons/Schemas/star_system_schema.json +++ b/NewHorizons/Schemas/star_system_schema.json @@ -139,25 +139,39 @@ "description": "Coordinates that the vessel can use to warp to your solar system.", "$ref": "#/definitions/NomaiCoordinates" }, - "vesselPosition": { - "description": "The position in the solar system the vessel will warp to.", - "$ref": "#/definitions/MVector3" + "promptFact": { + "type": "string", + "description": "A ship log fact which will make a prompt appear showing the coordinates when you're in the Vessel." }, - "vesselRotation": { - "description": "Euler angles by which the vessel will be oriented.", - "$ref": "#/definitions/MVector3" + "alwaysPresent": { + "type": "boolean", + "description": "Whether the vessel should spawn in this system even if it wasn't used to warp to it. This will automatically power on the vessel." }, - "warpExitPosition": { - "description": "The relative position to the vessel that you will be teleported to when you exit the vessel through the black hole.", - "$ref": "#/definitions/MVector3" + "spawnOnVessel": { + "type": "boolean", + "description": "Whether to always spawn the player on the vessel, even if it wasn't used to warp to the system." }, - "warpExitRotation": { - "description": "Euler angles by which the warp exit will be oriented.", - "$ref": "#/definitions/MVector3" + "hasPhysics": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the vessel should have physics enabled. Defaults to false if parentBody is set, and true otherwise." }, - "promptFact": { - "type": "string", - "description": "A ship log fact which will make a prompt appear showing the coordinates when you're in the Vessel." + "hasZeroGravityVolume": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the vessel should have a zero-gravity volume around it. Defaults to false if parentBody is set, and true otherwise." + }, + "vesselSpawn": { + "description": "The location that the vessel will warp to.", + "$ref": "#/definitions/VesselInfo" + }, + "warpExit": { + "description": "The location that you will be teleported to when you exit the vessel through the black hole.", + "$ref": "#/definitions/WarpExitInfo" } } }, @@ -197,6 +211,43 @@ } } }, + "VesselInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "parentBody": { + "type": "string", + "description": "The name of the planet that will be used with `parentPath`. Must be set if `parentPath` is set." + }, + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + } + } + }, "MVector3": { "type": "object", "additionalProperties": false, @@ -215,6 +266,47 @@ } } }, + "WarpExitInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "parentBody": { + "type": "string", + "description": "The name of the planet that will be used with `parentPath`. Must be set if `parentPath` is set." + }, + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, + "attachToVessel": { + "type": "boolean", + "description": "If set, keeps the warp exit attached to the vessel. Overrides `parentPath`." + } + } + }, "EntryPositionInfo": { "type": "object", "additionalProperties": false, diff --git a/NewHorizons/UsedInUnityProjectAttribute.cs b/NewHorizons/UsedInUnityProjectAttribute.cs index 057b3388e..26a19e7d9 100644 --- a/NewHorizons/UsedInUnityProjectAttribute.cs +++ b/NewHorizons/UsedInUnityProjectAttribute.cs @@ -1,5 +1,7 @@ using System; +namespace NewHorizons; + /// /// denotes that the given type is used in the unity project /// and therefore caution should be used when moving/renaming/deleting diff --git a/NewHorizons/Utility/Cache.cs b/NewHorizons/Utility/Cache.cs index 0c98d0211..f19aaceda 100644 --- a/NewHorizons/Utility/Cache.cs +++ b/NewHorizons/Utility/Cache.cs @@ -1,10 +1,8 @@ using Newtonsoft.Json; using OWML.Common; -using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.Serialization; namespace NewHorizons.Utility { diff --git a/NewHorizons/Utility/DebugMenu/DebugMenuPropPlacer.cs b/NewHorizons/Utility/DebugMenu/DebugMenuPropPlacer.cs index e6f5d8fe8..a518c844e 100644 --- a/NewHorizons/Utility/DebugMenu/DebugMenuPropPlacer.cs +++ b/NewHorizons/Utility/DebugMenu/DebugMenuPropPlacer.cs @@ -2,6 +2,8 @@ using NewHorizons.External.Configs; using NewHorizons.External.Modules; using NewHorizons.Utility.DebugUtilities; +using NewHorizons.Utility.Geometry; +using NewHorizons.Utility.OWUtilities; using Newtonsoft.Json; using System; using System.Collections.Generic; diff --git a/NewHorizons/Utility/DebugUtilities/DebugPropPlacer.cs b/NewHorizons/Utility/DebugUtilities/DebugPropPlacer.cs index 04554fd14..da3ceeef6 100644 --- a/NewHorizons/Utility/DebugUtilities/DebugPropPlacer.cs +++ b/NewHorizons/Utility/DebugUtilities/DebugPropPlacer.cs @@ -2,6 +2,7 @@ using NewHorizons.External.Configs; using NewHorizons.External.Modules; using NewHorizons.Handlers; +using NewHorizons.Utility.OWUtilities; using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -272,7 +273,7 @@ private PropPlacementData RegisterProp_WithReturn(AstroObject body, GameObject p // So we can't use local position/rotation here, we have to inverse transform the global position/rotation relative to root object prop.detailInfo.position = rootTransform.InverseTransformPoint(prop.gameObject.transform.position); prop.detailInfo.scale = prop.gameObject.transform.localScale.x; - if (!prop.detailInfo.alignToNormal) prop.detailInfo.rotation = rootTransform.InverseTransformRotation(prop.gameObject.transform.rotation).eulerAngles; + if (!prop.detailInfo.alignRadial.GetValueOrDefault()) prop.detailInfo.rotation = rootTransform.InverseTransformRotation(prop.gameObject.transform.rotation).eulerAngles; infoArray[i] = prop.detailInfo; } diff --git a/NewHorizons/Utility/DebugUtilities/DebugRaycaster.cs b/NewHorizons/Utility/DebugUtilities/DebugRaycaster.cs index 9433eda9e..03542ecc5 100644 --- a/NewHorizons/Utility/DebugUtilities/DebugRaycaster.cs +++ b/NewHorizons/Utility/DebugUtilities/DebugRaycaster.cs @@ -1,6 +1,5 @@ -using NewHorizons.Builder.Props; -using NewHorizons.External.Modules; using NewHorizons.Handlers; +using NewHorizons.Utility.Geometry; using UnityEngine; using UnityEngine.InputSystem; @@ -31,7 +30,7 @@ private void Start() Locator.GetPromptManager().AddScreenPrompt(_raycastPrompt, PromptPosition.UpperRight, false); } } - + private void OnDestroy() { if (_raycastPrompt != null) @@ -78,14 +77,14 @@ internal void PrintRaycast() var posText = Vector3ToString(data.pos); var normText = Vector3ToString(data.norm); var rotText = Vector3ToString(data.rot.eulerAngles); - - if(_surfaceSphere != null) GameObject.Destroy(_surfaceSphere); - if(_normalSphere1 != null) GameObject.Destroy(_normalSphere1); - if(_normalSphere2 != null) GameObject.Destroy(_normalSphere2); - if(_planeUpRightSphere != null) GameObject.Destroy(_planeUpRightSphere ); - if(_planeUpLeftSphere != null) GameObject.Destroy(_planeUpLeftSphere ); - if(_planeDownLeftSphere != null) GameObject.Destroy(_planeDownLeftSphere ); - if(_planeDownRightSphere != null) GameObject.Destroy(_planeDownRightSphere); + + if (_surfaceSphere != null) GameObject.Destroy(_surfaceSphere); + if (_normalSphere1 != null) GameObject.Destroy(_normalSphere1); + if (_normalSphere2 != null) GameObject.Destroy(_normalSphere2); + if (_planeUpRightSphere != null) GameObject.Destroy(_planeUpRightSphere); + if (_planeUpLeftSphere != null) GameObject.Destroy(_planeUpLeftSphere); + if (_planeDownLeftSphere != null) GameObject.Destroy(_planeDownLeftSphere); + if (_planeDownRightSphere != null) GameObject.Destroy(_planeDownRightSphere); _surfaceSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, 0.1f, Color.green); _normalSphere1 = AddDebugShape.AddSphere(data.hitBodyGameObject, 0.01f, Color.red); @@ -94,22 +93,22 @@ internal void PrintRaycast() _surfaceSphere.transform.localPosition = data.pos; _normalSphere1.transform.localPosition = data.pos + data.norm * 0.5f; _normalSphere2.transform.localPosition = data.pos + data.norm; - + // plane corners var planeSize = 0.5f; var planePointSize = 0.05f; - _planeUpRightSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.green); - _planeUpLeftSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.cyan) ; - _planeDownLeftSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.blue) ; - _planeDownRightSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.cyan) ; - - _planeUpRightSphere .transform.localPosition = data.plane.origin + data.plane.u*1*planeSize + data.plane.v*1*planeSize; - _planeUpLeftSphere .transform.localPosition = data.plane.origin + data.plane.u*-1*planeSize + data.plane.v*1*planeSize; - _planeDownLeftSphere .transform.localPosition = data.plane.origin + data.plane.u*-1*planeSize + data.plane.v*-1*planeSize; - _planeDownRightSphere.transform.localPosition = data.plane.origin + data.plane.u*1*planeSize + data.plane.v*-1*planeSize; + _planeUpRightSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.green); + _planeUpLeftSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.cyan); + _planeDownLeftSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.blue); + _planeDownRightSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.cyan); + + _planeUpRightSphere.transform.localPosition = data.plane.origin + data.plane.u * 1 * planeSize + data.plane.v * 1 * planeSize; + _planeUpLeftSphere.transform.localPosition = data.plane.origin + data.plane.u * -1 * planeSize + data.plane.v * 1 * planeSize; + _planeDownLeftSphere.transform.localPosition = data.plane.origin + data.plane.u * -1 * planeSize + data.plane.v * -1 * planeSize; + _planeDownRightSphere.transform.localPosition = data.plane.origin + data.plane.u * 1 * planeSize + data.plane.v * -1 * planeSize; Logger.Log($"Raycast hit\n\n\"position\": {posText},\n\"rotation\": {rotText},\n\"normal\": {normText}\n\non collider [{data.colliderPath}] " + - (data.bodyPath != null? $"at rigidbody [{data.bodyPath}]" : "not attached to a rigidbody")); + (data.bodyPath != null ? $"at rigidbody [{data.bodyPath}]" : "not attached to a rigidbody")); } internal DebugRaycastData Raycast() { @@ -131,12 +130,12 @@ internal DebugRaycastData Raycast() var toOrigin = Vector3.ProjectOnPlane((origin - hitInfo.point).normalized, hitInfo.normal); var worldSpaceRot = Quaternion.LookRotation(toOrigin, hitInfo.normal); data.rot = hitInfo.rigidbody.transform.InverseTransformRotation(worldSpaceRot); - + data.colliderPath = hitInfo.collider.transform.GetPath(); data.bodyPath = hitInfo.rigidbody.transform.GetPath(); data.hitBodyGameObject = hitInfo.rigidbody.gameObject; data.hitObject = hitInfo.collider.gameObject; - + data.plane = ConstructPlane(data); } } @@ -154,7 +153,7 @@ internal DebugRaycastPlane ConstructPlane(DebugRaycastData data) var U = data.pos - Vector3.zero; // U is the local "up" direction. the direction directly away from the center of the planet at this point. // pos is always relative to the body, so the body is considered to be at 0,0,0. var R = data.pos; // R is our origin point for the plane var N = data.norm.normalized; // N is the normal for this plane - + if (Vector3.Cross(U, N) == Vector3.zero) U = new Vector3(0, 0, 1); if (Vector3.Cross(U, N) == Vector3.zero) U = new Vector3(0, 1, 0); // if 0,0,1 was actually the same vector U already was (lol), try (0,1,0) instead @@ -162,11 +161,11 @@ internal DebugRaycastPlane ConstructPlane(DebugRaycastData data) // stackoverflow.com/a/9605695 // I don't know exactly how this works, but I'm projecting a point that is located above the plane's origin, relative to the planet, onto the plane. this gets us our v vector - var q = (2*U)-R; + var q = (2 * U) - R; var dist = Vector3.Dot(N, q); - var v_raw = 2*U - dist*N; - var v = (R-v_raw).normalized; - + var v_raw = 2 * U - dist * N; + var v = (R - v_raw).normalized; + var u = Vector3.Cross(N, v); DebugRaycastPlane p = new DebugRaycastPlane() diff --git a/NewHorizons/Utility/AddDebugShape.cs b/NewHorizons/Utility/Geometry/AddDebugShape.cs similarity index 91% rename from NewHorizons/Utility/AddDebugShape.cs rename to NewHorizons/Utility/Geometry/AddDebugShape.cs index 50fb4816a..d917d8729 100644 --- a/NewHorizons/Utility/AddDebugShape.cs +++ b/NewHorizons/Utility/Geometry/AddDebugShape.cs @@ -1,5 +1,5 @@ using UnityEngine; -namespace NewHorizons.Utility +namespace NewHorizons.Utility.Geometry { public static class AddDebugShape { @@ -20,7 +20,7 @@ public static GameObject AddSphere(GameObject obj, float radius, Color color) catch { // Something went wrong so make sure the sphere is deleted - GameObject.Destroy(sphere); + Object.Destroy(sphere); } return sphere.gameObject; diff --git a/NewHorizons/Utility/BoxShapeVisualizer.cs b/NewHorizons/Utility/Geometry/BoxShapeVisualizer.cs similarity index 70% rename from NewHorizons/Utility/BoxShapeVisualizer.cs rename to NewHorizons/Utility/Geometry/BoxShapeVisualizer.cs index df5b5af2a..77dbf6cfd 100644 --- a/NewHorizons/Utility/BoxShapeVisualizer.cs +++ b/NewHorizons/Utility/Geometry/BoxShapeVisualizer.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using UnityEngine; -using Popcron; -namespace NewHorizons.Utility +namespace NewHorizons.Utility.Geometry { public class BoxShapeVisualizer : MonoBehaviour { diff --git a/NewHorizons/Utility/CoordinateUtilities.cs b/NewHorizons/Utility/Geometry/CoordinateUtilities.cs similarity index 97% rename from NewHorizons/Utility/CoordinateUtilities.cs rename to NewHorizons/Utility/Geometry/CoordinateUtilities.cs index 62d98eb94..10f8728d6 100644 --- a/NewHorizons/Utility/CoordinateUtilities.cs +++ b/NewHorizons/Utility/Geometry/CoordinateUtilities.cs @@ -1,5 +1,5 @@ using UnityEngine; -namespace NewHorizons.Utility +namespace NewHorizons.Utility.Geometry { public static class CoordinateUtilities { diff --git a/NewHorizons/Utility/MakeMeshDoubleFaced.cs b/NewHorizons/Utility/Geometry/MakeMeshDoubleFaced.cs similarity index 96% rename from NewHorizons/Utility/MakeMeshDoubleFaced.cs rename to NewHorizons/Utility/Geometry/MakeMeshDoubleFaced.cs index ce3e036cb..6bbae8b72 100644 --- a/NewHorizons/Utility/MakeMeshDoubleFaced.cs +++ b/NewHorizons/Utility/Geometry/MakeMeshDoubleFaced.cs @@ -1,5 +1,6 @@ -using UnityEngine; -namespace NewHorizons.Utility +using UnityEngine; + +namespace NewHorizons.Utility.Geometry { public class MakeMeshDoubleFaced : MonoBehaviour { diff --git a/NewHorizons/Utility/MeshUtilities.cs b/NewHorizons/Utility/Geometry/MeshUtilities.cs similarity index 79% rename from NewHorizons/Utility/MeshUtilities.cs rename to NewHorizons/Utility/Geometry/MeshUtilities.cs index b9f2d3205..1631bffda 100644 --- a/NewHorizons/Utility/MeshUtilities.cs +++ b/NewHorizons/Utility/Geometry/MeshUtilities.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using UnityEngine; -namespace NewHorizons.Utility +namespace NewHorizons.Utility.Geometry { public class MeshUtilities { @@ -19,7 +15,7 @@ public static Mesh RectangleMeshFromCorners(Vector3[] corners) }; MVector3[] normals = new MVector3[verts.Length]; - for (int i = 0; i(this T target) where T : UnityEngine.Object { UnityEngine.Object.DontDestroyOnLoad(target); diff --git a/NewHorizons/Utility/Delay.cs b/NewHorizons/Utility/OWMLUtilities/Delay.cs similarity index 91% rename from NewHorizons/Utility/Delay.cs rename to NewHorizons/Utility/OWMLUtilities/Delay.cs index 84bff7787..3d8288f07 100644 --- a/NewHorizons/Utility/Delay.cs +++ b/NewHorizons/Utility/OWMLUtilities/Delay.cs @@ -1,6 +1,6 @@ using System; -namespace NewHorizons.Utility +namespace NewHorizons.Utility.OWMLUtilities { public static class Delay { diff --git a/NewHorizons/Utility/EnumUtilities.cs b/NewHorizons/Utility/OWMLUtilities/EnumUtilities.cs similarity index 95% rename from NewHorizons/Utility/EnumUtilities.cs rename to NewHorizons/Utility/OWMLUtilities/EnumUtilities.cs index fa202c193..aec5f721c 100644 --- a/NewHorizons/Utility/EnumUtilities.cs +++ b/NewHorizons/Utility/OWMLUtilities/EnumUtilities.cs @@ -1,9 +1,8 @@ +using OWML.Utils; using System; using System.Collections.Generic; -using System.Linq; -using OWML.Utils; -namespace NewHorizons.Utility +namespace NewHorizons.Utility.OWMLUtilities { public static class EnumUtilities { diff --git a/NewHorizons/Utility/AstroObjectLocator.cs b/NewHorizons/Utility/OWUtilities/AstroObjectLocator.cs similarity index 98% rename from NewHorizons/Utility/AstroObjectLocator.cs rename to NewHorizons/Utility/OWUtilities/AstroObjectLocator.cs index 90552bb35..cd1690531 100644 --- a/NewHorizons/Utility/AstroObjectLocator.cs +++ b/NewHorizons/Utility/OWUtilities/AstroObjectLocator.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using UnityEngine; -namespace NewHorizons.Utility +namespace NewHorizons.Utility.OWUtilities { public static class AstroObjectLocator { @@ -10,7 +10,7 @@ public static class AstroObjectLocator public static void Init() { _customAstroObjectDictionary = new Dictionary(); - foreach (AstroObject ao in GameObject.FindObjectsOfType()) + foreach (AstroObject ao in Object.FindObjectsOfType()) { // Ignore the sun station debris, we handle it as a child of the sun station if (ao.gameObject.name == "SS_Debris_Body") continue; diff --git a/NewHorizons/Utility/OWUtilities/Layer.cs b/NewHorizons/Utility/OWUtilities/Layer.cs new file mode 100644 index 000000000..a9eae8bba --- /dev/null +++ b/NewHorizons/Utility/OWUtilities/Layer.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +namespace NewHorizons.Utility.OWUtilities +{ + public static class Layer + { + public static int Default = LayerMask.NameToLayer(nameof(Default)); + public static int TransparentFX = LayerMask.NameToLayer(nameof(TransparentFX)); + public static int IgnoreRaycast = LayerMask.NameToLayer("Ignore Raycast"); + public static int Water = LayerMask.NameToLayer(nameof(Water)); + public static int UI = LayerMask.NameToLayer(nameof(UI)); + public static int PlayerSafetyCollider = LayerMask.NameToLayer(nameof(PlayerSafetyCollider)); + public static int Sun = LayerMask.NameToLayer(nameof(Sun)); + public static int ShipInterior = LayerMask.NameToLayer(nameof(ShipInterior)); + public static int HelmetUVPass = LayerMask.NameToLayer(nameof(HelmetUVPass)); + public static int AdvancedDetector = LayerMask.NameToLayer(nameof(AdvancedDetector)); + public static int Primitive = LayerMask.NameToLayer(nameof(Primitive)); + public static int IgnoreSun = LayerMask.NameToLayer(nameof(IgnoreSun)); + public static int AdvancedEffectVolume = LayerMask.NameToLayer(nameof(AdvancedEffectVolume)); + public static int BasicEffectVolume = LayerMask.NameToLayer(nameof(BasicEffectVolume)); + public static int ProxyPrimitive = LayerMask.NameToLayer(nameof(ProxyPrimitive)); + public static int ReferenceFrameVolume = LayerMask.NameToLayer(nameof(ReferenceFrameVolume)); + public static int BasicDetector = LayerMask.NameToLayer(nameof(BasicDetector)); + public static int Interactible = LayerMask.NameToLayer(nameof(Interactible)); + public static int VisibleToProbe = LayerMask.NameToLayer(nameof(VisibleToProbe)); + public static int HeadsUpDisplay = LayerMask.NameToLayer(nameof(HeadsUpDisplay)); + public static int CloseRangeRFVolume = LayerMask.NameToLayer(nameof(CloseRangeRFVolume)); + public static int ProxyPrimitive2 = LayerMask.NameToLayer(nameof(ProxyPrimitive2)); + public static int PhysicalDetector = LayerMask.NameToLayer(nameof(PhysicalDetector)); + public static int VisibleToPlayer = LayerMask.NameToLayer(nameof(VisibleToPlayer)); + public static int DreamSimulation = LayerMask.NameToLayer(nameof(DreamSimulation)); + public static int Skybox = LayerMask.NameToLayer(nameof(Skybox)); + public static int IgnoreOrbRaycast = LayerMask.NameToLayer(nameof(IgnoreOrbRaycast)); + public static int Flashback = LayerMask.NameToLayer(nameof(Flashback)); + } +} diff --git a/NewHorizons/Utility/TimeLoopUtilities.cs b/NewHorizons/Utility/OWUtilities/TimeLoopUtilities.cs similarity index 96% rename from NewHorizons/Utility/TimeLoopUtilities.cs rename to NewHorizons/Utility/OWUtilities/TimeLoopUtilities.cs index 69b3fcccb..32a9b5aa1 100644 --- a/NewHorizons/Utility/TimeLoopUtilities.cs +++ b/NewHorizons/Utility/OWUtilities/TimeLoopUtilities.cs @@ -1,6 +1,6 @@ using UnityEngine; -namespace NewHorizons.Utility +namespace NewHorizons.Utility.OWUtilities { public static class TimeLoopUtilities { diff --git a/NewHorizons/Utility/RandomUtility.cs b/NewHorizons/Utility/RandomUtility.cs index efd073f2d..971e1526c 100644 --- a/NewHorizons/Utility/RandomUtility.cs +++ b/NewHorizons/Utility/RandomUtility.cs @@ -1,5 +1,6 @@ -using System.Collections.Generic; +using System.Collections.Generic; using UnityEngine; + namespace NewHorizons.Utility { public static class RandomUtility diff --git a/NewHorizons/manifest.json b/NewHorizons/manifest.json index c5bbf50d1..5236f06a9 100644 --- a/NewHorizons/manifest.json +++ b/NewHorizons/manifest.json @@ -4,7 +4,7 @@ "author": "xen, Bwc9876, clay, MegaPiggy, John, Trifid, Hawkbar, Book", "name": "New Horizons", "uniqueName": "xen.NewHorizons", - "version": "1.9.0", + "version": "1.10.0", "owmlVersion": "2.9.0", "dependencies": [ "JohnCorby.VanillaFix", "_nebula.MenuFramework", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ], "conflicts": [ "Raicuparta.QuantumSpaceBuddies", "PacificEngine.OW_CommonResources" ],