From 532acc9500f5f385e9775b444394e72c938d3878 Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 6 Feb 2022 00:01:22 -0500 Subject: [PATCH 01/23] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index b9e1b79c..a1d089d6 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,6 @@ Now that you have created your planets folder, this is where you will put your p "Base" : { "groundSize" : 100, - "waterSize" : 101, "surfaceSize" : 101, "surfaceGravity" : 12, "hasMapMarker" : true, From f8b04c89a6864504054debc6efa568ba4dbcdf18 Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 6 Feb 2022 00:31:10 -0500 Subject: [PATCH 02/23] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index a1d089d6..20f6b954 100644 --- a/README.md +++ b/README.md @@ -584,6 +584,14 @@ Similar to above, make a config where "Name" is the name of the planet. The name Only some of the above modules are supported (currently) for existing planets. Things you cannot modify for existing planets include: heightmaps, procedural generation, gravity, or their orbits. You also can't make them into stars or binary focal points (but why would you want to, just delete them and replace them entirely). However this still means there are many things you can do: completely change their atmospheres, give them rings, asteroid belts, comet tails, lava, water, prop details, or signals. +You can also delete parts of an existing planet. Here's part of an example config which would delete the rising sand from Ember Twin: +``` +"name" : "Ember Twin", +"childrenToDestroy" : ["SandSphere_Rising"], +``` + +In `childrenToDestroy` you list the relative paths for the children of the planet's gameObject that you want to delete. + ## How to use New Horizons in other mods First create the following interface in your mod: From 9faf313d794431b7e270c2fee77a827fb79c762b Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 6 Feb 2022 15:13:57 -0500 Subject: [PATCH 03/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 20f6b954..d0d6d96f 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Check the ship's log for how to use your warp drive to travel between star syste - Zero-g volumes - Implement custom Nomai scrolls - Implement custom translatable writing -- Implement constant gravity volumes +- Implement constant gravity volumes (technically done) - Destroy planets that fall into a star - Make a template Unity project to use with NH, including all game scripts recovered using UtinyRipper to make AssetBundle creation easier From 2ddd79d4948e55af20e384468afc608fccf82c1a Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 6 Feb 2022 15:36:35 -0500 Subject: [PATCH 04/23] Add unity template info to readme --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d0d6d96f..c4fe599c 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ Check the ship's log for how to use your warp drive to travel between star syste - Implement custom translatable writing - Implement constant gravity volumes (technically done) - Destroy planets that fall into a star -- Make a template Unity project to use with NH, including all game scripts recovered using UtinyRipper to make AssetBundle creation easier +- Make a template Unity project to use with NH, including all game scripts recovered using UtinyRipper to make AssetBundle creation easier (done) ## How to create your own planets using configs @@ -366,6 +366,13 @@ A detail info object can have the following parameters: You have three options: Load from the scene hierarchy by setting "path", load from an asset bundle by setting "path" and "assetBundle", or load an obj file by setting "objFilePath" and "mtlFilePath". Asset bundles give much better results than .obj's. #### Asset Bundles + +Here is a template project: [Outer Wilds Unity Template](https://github.com/xen-42/outer-wilds-unity-template) + +The template project contains ripped versions of all the game scripts, meaning you can put things like DirectionalForceVolumes in your Unity project to have artificial gravity volumes loaded right into the game. + +If for whatever reason you want to set up a Unity project manually instead of using the template, follow these instructions: + 1. Start up a Unity 2017 project (I use Unity 2017.4.40f1 (64-bit), so if you use something else I can't guarantee it will work). The DLC updated Outer Wilds to 2019.4.27 so that probably works but I personally haven't tried it. 2. In the "Assets" folder in Unity, create a new folder called "Editor". In it create a file called "CreateAssetBundle.cs" with the following code in it: From df7b6ab1aa7d66b2a85c3d171595d8732727a3e3 Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 6 Feb 2022 15:39:00 -0500 Subject: [PATCH 05/23] Update README.md --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c4fe599c..8d0f6e64 100644 --- a/README.md +++ b/README.md @@ -62,26 +62,25 @@ Check the ship's log for how to use your warp drive to travel between star syste - Separate solar system scenes accessible via wormhole (done) - Warp drive with target set in ship's log (done) - Implement custom dialogue (done) +- Make a template Unity project to use with NH, including all game scripts recovered using UtinyRipper to make AssetBundle creation easier ([done](https://github.com/xen-42/outer-wilds-unity-template)) - Procedural terrain generation (started) - "Quantum" planet parameters - Better terrain and water LOD - Edit existing planet orbits - Implement all planet features: - - Tornados + floating islands - - Funnels (sand/water/lava/star) (done) + - Funnels (sand/water/lava/star) (done) - Variable surface height (sand/water/lava/star) (done) + - Zero-g volumes (done, with Unity template) + - Ghost matter (done, by copying props via game hierarchy) + - Tornados + floating islands - Let any star go supernova - Geysers - Meteors - - Ghost matter - Pocket dimensions - Timed position/velocity changes - - Zero-g volumes - Implement custom Nomai scrolls - Implement custom translatable writing -- Implement constant gravity volumes (technically done) - Destroy planets that fall into a star -- Make a template Unity project to use with NH, including all game scripts recovered using UtinyRipper to make AssetBundle creation easier (done) ## How to create your own planets using configs From 701f908798e4471ef6b7c18104382c2ca642a03e Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Mon, 7 Feb 2022 23:27:35 -0500 Subject: [PATCH 06/23] Brought over changes from ship log branch --- NewHorizons/AssetBundle/WarpDriveConfig.json | 3 +- NewHorizons/AssetBundle/WarpDriveDialogue.xml | 26 ----------- .../Builder/Atmosphere/EffectsBuilder.cs | 14 +++++- NewHorizons/Builder/Body/WaterBuilder.cs | 9 ++++ NewHorizons/Builder/Props/DialogueBuilder.cs | 2 + NewHorizons/External/PropModule.cs | 2 +- .../StarChartHandler.cs} | 17 ++++--- NewHorizons/Main.cs | 10 ++-- NewHorizons/Tools/Patches.cs | 6 +++ NewHorizons/Tools/WarpDrivePatches.cs | 9 ++-- NewHorizons/Utility/DebugRaycaster.cs | 46 ------------------- 11 files changed, 49 insertions(+), 95 deletions(-) rename NewHorizons/{Builder/General/ShipLogBuilder.cs => Handlers/StarChartHandler.cs} (92%) diff --git a/NewHorizons/AssetBundle/WarpDriveConfig.json b/NewHorizons/AssetBundle/WarpDriveConfig.json index eb685c70..cc45a642 100644 --- a/NewHorizons/AssetBundle/WarpDriveConfig.json +++ b/NewHorizons/AssetBundle/WarpDriveConfig.json @@ -8,7 +8,8 @@ "position":{"x": -0.3071011, "y": 2.741472, "z": -4.005298}, "radius":1, "xmlFile":"AssetBundle/WarpDriveDialogue.xml", - "remoteTriggerPosition": {"x": -0.05656214, "y": 0.5362684, "z": 0.5467669} + "remoteTriggerPosition": {"x": -0.05656214, "y": 0.5362684, "z": 0.5467669}, + "blockAfterPersistentCondition" : "KnowsAboutWarpDrive" } ] } diff --git a/NewHorizons/AssetBundle/WarpDriveDialogue.xml b/NewHorizons/AssetBundle/WarpDriveDialogue.xml index 37c2c43a..1f9ea63f 100644 --- a/NewHorizons/AssetBundle/WarpDriveDialogue.xml +++ b/NewHorizons/AssetBundle/WarpDriveDialogue.xml @@ -6,33 +6,7 @@ DEFAULT Your ship is now equiped with a warp drive! - - - - - ... - 1 - - - - - - 1 - You can use the new "Interstellar Mode" page in the ship log to lock-on your autopilot to another star system. - - - - - ... - 2 - - - - - - 2 - Then just buckle up and engage the autopilot to warp there! KnowsAboutWarpDrive diff --git a/NewHorizons/Builder/Atmosphere/EffectsBuilder.cs b/NewHorizons/Builder/Atmosphere/EffectsBuilder.cs index f53b9a18..501148c6 100644 --- a/NewHorizons/Builder/Atmosphere/EffectsBuilder.cs +++ b/NewHorizons/Builder/Atmosphere/EffectsBuilder.cs @@ -26,7 +26,12 @@ namespace NewHorizons.Atmosphere rainGO.transform.localPosition = Vector3.zero; var pvc = rainGO.GetComponent(); - pvc.SetValue("_densityByHeight", new AnimationCurve(new Keyframe[] { new Keyframe(surfaceSize, 10f), new Keyframe(atmoSize / 2f, 0f) })); + pvc._densityByHeight = new AnimationCurve(new Keyframe[] + { + new Keyframe(surfaceSize - 0.5f, 0), + new Keyframe(surfaceSize, 10f), + new Keyframe(atmoSize, 0f) + }); rainGO.GetComponent().SetValue("_activeInSector", sector); rainGO.GetComponent().SetValue("_exclusionSectors", new Sector[] { }); @@ -45,7 +50,12 @@ namespace NewHorizons.Atmosphere snowEmitter.transform.localPosition = Vector3.zero; var pvc = snowEmitter.GetComponent(); - pvc.SetValue("_densityByHeight", new AnimationCurve(new Keyframe[] { new Keyframe(surfaceSize, 10f), new Keyframe(atmoSize / 2f, 0f) })); + pvc._densityByHeight = new AnimationCurve(new Keyframe[] + { + new Keyframe(surfaceSize - 0.5f, 0), + new Keyframe(surfaceSize, 10f), + new Keyframe(atmoSize, 0f) + }); snowEmitter.GetComponent().SetValue("_activeInSector", sector); snowEmitter.GetComponent().SetValue("_exclusionSectors", new Sector[] { }); diff --git a/NewHorizons/Builder/Body/WaterBuilder.cs b/NewHorizons/Builder/Body/WaterBuilder.cs index c6cc0711..59bbc6ae 100644 --- a/NewHorizons/Builder/Body/WaterBuilder.cs +++ b/NewHorizons/Builder/Body/WaterBuilder.cs @@ -40,6 +40,8 @@ namespace NewHorizons.Builder.Body if (module.Tint != null) { tempArray[i].color = module.Tint.ToColor32(); + tempArray[i].color = module.Tint.ToColor(); + tempArray[i].SetColor("_FogColor", module.Tint.ToColor()); } } @@ -80,6 +82,13 @@ namespace NewHorizons.Builder.Body fogGO.name = "OceanFog"; fogGO.transform.localPosition = Vector3.zero; fogGO.transform.localScale = Vector3.one; + if (module.Tint != null) + { + var adjustedColour = module.Tint.ToColor() / 4f; + adjustedColour.a = 1f; + + fogGO.GetComponent().material.color = adjustedColour; + } if (module.Curve != null) { diff --git a/NewHorizons/Builder/Props/DialogueBuilder.cs b/NewHorizons/Builder/Props/DialogueBuilder.cs index 3b1a786a..3cc77e70 100644 --- a/NewHorizons/Builder/Props/DialogueBuilder.cs +++ b/NewHorizons/Builder/Props/DialogueBuilder.cs @@ -15,6 +15,8 @@ namespace NewHorizons.Builder.Props { public static void Make(GameObject go, Sector sector, PropModule.DialogueInfo info, IModHelper mod) { + if (info.blockAfterPersistentCondition != null && PlayerData._currentGameSave.GetPersistentCondition(info.blockAfterPersistentCondition)) return; + var dialogue = MakeConversationZone(go, sector, info, mod); if (info.remoteTriggerPosition != null) MakeRemoteDialogueTrigger(go, sector, info, dialogue); } diff --git a/NewHorizons/External/PropModule.cs b/NewHorizons/External/PropModule.cs index 02f66142..dfe7455c 100644 --- a/NewHorizons/External/PropModule.cs +++ b/NewHorizons/External/PropModule.cs @@ -66,7 +66,7 @@ namespace NewHorizons.External public float radius = 1f; public string xmlFile; public MVector3 remoteTriggerPosition; - public string persistentCondition; + public string blockAfterPersistentCondition; } } } diff --git a/NewHorizons/Builder/General/ShipLogBuilder.cs b/NewHorizons/Handlers/StarChartHandler.cs similarity index 92% rename from NewHorizons/Builder/General/ShipLogBuilder.cs rename to NewHorizons/Handlers/StarChartHandler.cs index 8d38d135..6fafab15 100644 --- a/NewHorizons/Builder/General/ShipLogBuilder.cs +++ b/NewHorizons/Handlers/StarChartHandler.cs @@ -5,29 +5,28 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; -using Logger = NewHorizons.Utility.Logger; -namespace NewHorizons.Builder.General +namespace NewHorizons.Handlers { - public static class ShipLogBuilder + public static class StarChartHandler { public static ShipLogStarChartMode ShipLogStarChartMode; public static void Init() { var shipLogRoot = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas"); - + var starChartLog = new GameObject("StarChartMode"); starChartLog.SetActive(false); starChartLog.transform.parent = shipLogRoot.transform; starChartLog.transform.localScale = Vector3.one * 1f; starChartLog.transform.localPosition = Vector3.zero; starChartLog.transform.localRotation = Quaternion.Euler(0, 0, 0); - + ShipLogStarChartMode = starChartLog.AddComponent(); - + var reticleImage = GameObject.Instantiate(GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/DetectiveMode/ReticleImage (1)/"), starChartLog.transform); - + var scaleRoot = new GameObject("ScaleRoot"); scaleRoot.transform.parent = starChartLog.transform; scaleRoot.transform.localScale = Vector3.one; @@ -38,7 +37,7 @@ namespace NewHorizons.Builder.General panRoot.transform.parent = scaleRoot.transform; panRoot.transform.localScale = Vector3.one; panRoot.transform.localPosition = Vector3.zero; - panRoot.transform.localRotation = Quaternion.Euler(0,0,0); + panRoot.transform.localRotation = Quaternion.Euler(0, 0, 0); var centerPromptList = shipLogRoot.transform.Find("ScreenPromptListScaleRoot/ScreenPromptList_Center")?.GetComponent(); var upperRightPromptList = shipLogRoot.transform.Find("ScreenPromptListScaleRoot/ScreenPromptList_UpperRight")?.GetComponent(); @@ -50,4 +49,4 @@ namespace NewHorizons.Builder.General oneShotSource); } } -} +} \ No newline at end of file diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 967b4466..4d81d809 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -7,6 +7,7 @@ using NewHorizons.Builder.Props; using NewHorizons.Components; using NewHorizons.External; using NewHorizons.External.VariableSize; +using NewHorizons.Handlers; using NewHorizons.OrbitalPhysics; using NewHorizons.Utility; using OWML.Common; @@ -113,12 +114,9 @@ namespace NewHorizons HasWarpDrive = true; _shipWarpController = GameObject.Find("Ship_Body").AddComponent(); - Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => ShipLogBuilder.Init()); + Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => StarChartHandler.Init()); - if (!PlayerData._currentGameSave.GetPersistentCondition("KnowsAboutWarpDrive")) - { - LoadBody(LoadConfig(this, "AssetBundle/WarpDriveConfig.json")); - } + LoadBody(LoadConfig(this, "AssetBundle/WarpDriveConfig.json")); } Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => AstroObjectLocator.GetAstroObject("MapSatellite").gameObject.AddComponent()); @@ -582,7 +580,7 @@ namespace NewHorizons } if (body.Config.Atmosphere.HasRain || body.Config.Atmosphere.HasSnow) - EffectsBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere.Size / 2f, body.Config.Atmosphere.HasRain, body.Config.Atmosphere.HasSnow); + EffectsBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere.Size, body.Config.Atmosphere.HasRain, body.Config.Atmosphere.HasSnow); if (body.Config.Atmosphere.FogSize != 0) FogBuilder.Make(go, sector, body.Config.Atmosphere); diff --git a/NewHorizons/Tools/Patches.cs b/NewHorizons/Tools/Patches.cs index cc02fc79..23df6941 100644 --- a/NewHorizons/Tools/Patches.cs +++ b/NewHorizons/Tools/Patches.cs @@ -52,6 +52,7 @@ namespace NewHorizons.Tools // Postfixes Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Awake", typeof(Patches), nameof(Patches.OnMapControllerAwake)); + Main.Instance.ModHelper.HarmonyHelper.AddPostfix("OnTargetReferenceFrame", typeof(Patches), nameof(Patches.OnMapControllerOnTargetReferenceFrame)); } public static bool GetHUDDisplayName(ReferenceFrame __instance, ref string __result) @@ -347,5 +348,10 @@ namespace NewHorizons.Tools } return false; } + + public static void OnMapControllerOnTargetReferenceFrame(MapController __instance, ReferenceFrame __0) + { + __instance._isLockedOntoMapSatellite = true; + } } } diff --git a/NewHorizons/Tools/WarpDrivePatches.cs b/NewHorizons/Tools/WarpDrivePatches.cs index e84d0d71..e06ce4c0 100644 --- a/NewHorizons/Tools/WarpDrivePatches.cs +++ b/NewHorizons/Tools/WarpDrivePatches.cs @@ -1,4 +1,5 @@ using NewHorizons.Builder.General; +using NewHorizons.Handlers; using System; using System.Collections.Generic; using System.Linq; @@ -35,7 +36,7 @@ namespace NewHorizons.Tools if (__instance._playerAtFlightConsole && OWInput.IsNewlyPressed(InputLibrary.autopilot, InputMode.ShipCockpit)) { - var targetSystem = ShipLogBuilder.ShipLogStarChartMode.GetTargetStarSystem(); + var targetSystem = StarChartHandler.ShipLogStarChartMode.GetTargetStarSystem(); if (targetSystem != null) { Main.Instance.ChangeCurrentStarSystem(targetSystem, true); @@ -52,7 +53,7 @@ namespace NewHorizons.Tools if (__instance._exiting || OWInput.GetInputMode() != InputMode.ShipComputer || __instance._currentMode.AllowCancelInput() && OWInput.IsNewlyPressed(InputLibrary.cancel, InputMode.All) - || ShipLogBuilder.ShipLogStarChartMode == null) + || StarChartHandler.ShipLogStarChartMode == null) return true; __instance._exitPrompt.SetVisibility(__instance._currentMode.AllowCancelInput()); @@ -66,8 +67,8 @@ namespace NewHorizons.Tools __instance._currentMode = (flag ? __instance._detectiveMode : __instance._mapMode); if (currentMode.Equals(__instance._mapMode)) - __instance._currentMode = ShipLogBuilder.ShipLogStarChartMode; - else if (currentMode.Equals(ShipLogBuilder.ShipLogStarChartMode)) + __instance._currentMode = StarChartHandler.ShipLogStarChartMode; + else if (currentMode.Equals(StarChartHandler.ShipLogStarChartMode)) __instance._currentMode = __instance._detectiveMode; else __instance._currentMode = __instance._mapMode; diff --git a/NewHorizons/Utility/DebugRaycaster.cs b/NewHorizons/Utility/DebugRaycaster.cs index 39537d07..6dd56a44 100644 --- a/NewHorizons/Utility/DebugRaycaster.cs +++ b/NewHorizons/Utility/DebugRaycaster.cs @@ -13,10 +13,6 @@ namespace NewHorizons.Utility public class DebugRaycaster : MonoBehaviour { private OWRigidbody _rb; - - private GameObject blackHole; - private GameObject whiteHole; - private void Awake() { _rb = this.GetRequiredComponent(); @@ -38,48 +34,6 @@ namespace NewHorizons.Utility } _rb.EnableCollisionDetection(); } - - /* - // Portal Gun: - if (Keyboard.current == null) return; - var fireBlackHole = Keyboard.current[Key.B].wasReleasedThisFrame; - var fireWhiteHole = Keyboard.current[Key.N].wasReleasedThisFrame; - if (fireBlackHole || fireWhiteHole) - { - // Raycast - _rb.DisableCollisionDetection(); - int layerMask = OWLayerMask.physicalMask; - var origin = Locator.GetActiveCamera().transform.position; - var direction = Locator.GetActiveCamera().transform.TransformDirection(Vector3.forward); - if (Physics.Raycast(origin, direction, out RaycastHit hitInfo, Mathf.Infinity, OWLayerMask.physicalMask)) - { - var pos = hitInfo.transform.InverseTransformPoint(hitInfo.point + hitInfo.normal); - var hitBody = hitInfo.transform.gameObject; - var sector = hitBody.GetComponent()?.GetRootSector(); - - if (hitBody == null || sector == null) return; - Logger.Log($"{hitBody}"); - if (fireBlackHole) - { - if (blackHole != null) GameObject.Destroy(blackHole); - blackHole = SingularityBuilder.MakeBlackHole(hitBody, sector, pos, 2, false, null, false); - Logger.Log("Make black hole"); - } - else - { - if (whiteHole != null) GameObject.Destroy(whiteHole); - whiteHole = SingularityBuilder.MakeWhiteHole(hitBody, sector, hitBody.GetAttachedOWRigidbody(), pos, 2, false); - Logger.Log("Make white hole"); - } - - if(blackHole && whiteHole) - { - SingularityBuilder.PairSingularities(blackHole, whiteHole); - } - } - _rb.EnableCollisionDetection(); - } - */ } } } From 90cff5bfc2a524a0e65e1a4830f79b8f1e96cb4a Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Tue, 8 Feb 2022 10:44:47 -0500 Subject: [PATCH 07/23] Fix issue where you autopilot to the sun when in DB --- NewHorizons/Tools/Patches.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NewHorizons/Tools/Patches.cs b/NewHorizons/Tools/Patches.cs index 23df6941..4e32af97 100644 --- a/NewHorizons/Tools/Patches.cs +++ b/NewHorizons/Tools/Patches.cs @@ -68,9 +68,12 @@ namespace NewHorizons.Tools public static bool CheckShipOutersideSolarSystem(PlayerState __instance, ref bool __result) { + if (PlayerState._inBrambleDimension) return false; + Transform sunTransform = Locator.GetSunTransform(); OWRigidbody shipBody = Locator.GetShipBody(); - __result = sunTransform != null && shipBody != null && (sunTransform.position - shipBody.transform.position).sqrMagnitude > Main.FurthestOrbit * Main.FurthestOrbit * 4f; + var maxDist2 = Mathf.Max(900000000f, Main.FurthestOrbit * Main.FurthestOrbit * 2f); + __result = sunTransform != null && shipBody != null && (sunTransform.position - shipBody.transform.position).sqrMagnitude > maxDist2; return false; } From f2b2ed0c1ebf4e8b27efd0890f08a54daa2a400b Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Tue, 8 Feb 2022 11:32:23 -0500 Subject: [PATCH 08/23] I always forget to update this --- NewHorizons/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/manifest.json b/NewHorizons/manifest.json index 2e7a1f51..1c5e0043 100644 --- a/NewHorizons/manifest.json +++ b/NewHorizons/manifest.json @@ -3,7 +3,7 @@ "author": "xen", "name": "New Horizons", "uniqueName": "xen.NewHorizons", - "version": "0.8.1", + "version": "0.8.2", "owmlVersion": "2.1.0", "dependencies": [ "PacificEngine.OW_CommonResources" ], "conflicts": [ "Raicuparta.QuantumSpaceBuddies", "Vesper.OuterWildsMMO", "Vesper.AutoResume" ] From c1b5402f8f752ff20aefba0b8722f46e47c48e5b Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Tue, 8 Feb 2022 11:32:31 -0500 Subject: [PATCH 09/23] Do alpha on water --- NewHorizons/Builder/Body/WaterBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Builder/Body/WaterBuilder.cs b/NewHorizons/Builder/Body/WaterBuilder.cs index 59bbc6ae..873b5f67 100644 --- a/NewHorizons/Builder/Body/WaterBuilder.cs +++ b/NewHorizons/Builder/Body/WaterBuilder.cs @@ -85,7 +85,7 @@ namespace NewHorizons.Builder.Body if (module.Tint != null) { var adjustedColour = module.Tint.ToColor() / 4f; - adjustedColour.a = 1f; + adjustedColour.a = adjustedColour.a * 4f; fogGO.GetComponent().material.color = adjustedColour; } From 3699c3a9b73172c9909e10dfe9271851f0cb15e1 Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Wed, 9 Feb 2022 13:38:06 -0500 Subject: [PATCH 10/23] Allow changing stock planet orbit (except for primary body) --- .../Builder/Orbital/InitialMotionBuilder.cs | 7 +- NewHorizons/External/OrbitModule.cs | 2 +- NewHorizons/External/PlanetConfig.cs | 2 +- NewHorizons/Main.cs | 80 ++++++++++++++++-- .../Utility/CommonResourcesUtilities.cs | 61 ++++++++++++++ NewHorizons/Utility/SearchUtilities.cs | 81 ++++++++++--------- 6 files changed, 185 insertions(+), 48 deletions(-) create mode 100644 NewHorizons/Utility/CommonResourcesUtilities.cs diff --git a/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs b/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs index aa71f286..1f84fcee 100644 --- a/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs +++ b/NewHorizons/Builder/Orbital/InitialMotionBuilder.cs @@ -21,10 +21,15 @@ namespace NewHorizons.Builder.Orbital return Update(initialMotion, body, primaryBody, OWRB, orbit); } + public static float SiderealPeriodToAngularSpeed(float siderealPeriod) + { + return siderealPeriod == 0 ? 0f : 2f * Mathf.PI / (siderealPeriod * 60f); + } + public static InitialMotion Update(InitialMotion initialMotion, GameObject body, AstroObject primaryBody, OWRigidbody OWRB, OrbitModule orbit) { // Rotation - initialMotion.SetValue("_initAngularSpeed", orbit.SiderealPeriod == 0 ? 0f : 2f * Mathf.PI / (orbit.SiderealPeriod * 60f)); + initialMotion.SetValue("_initAngularSpeed", SiderealPeriodToAngularSpeed(orbit.SiderealPeriod)); var rotationAxis = Quaternion.AngleAxis(orbit.AxialTilt + 90f, Vector3.right) * Vector3.up; body.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis); diff --git a/NewHorizons/External/OrbitModule.cs b/NewHorizons/External/OrbitModule.cs index 5e005f2a..d8ec66b4 100644 --- a/NewHorizons/External/OrbitModule.cs +++ b/NewHorizons/External/OrbitModule.cs @@ -9,7 +9,7 @@ namespace NewHorizons.External { public class OrbitModule : Module { - public int SemiMajorAxis { get; set; } = 5000; + public int SemiMajorAxis { get; set; } public float Inclination { get; set; } public string PrimaryBody { get; set; } public bool IsMoon { get; set; } diff --git a/NewHorizons/External/PlanetConfig.cs b/NewHorizons/External/PlanetConfig.cs index 4724d3a2..cf71a576 100644 --- a/NewHorizons/External/PlanetConfig.cs +++ b/NewHorizons/External/PlanetConfig.cs @@ -33,7 +33,7 @@ namespace NewHorizons.External public PlanetConfig(Dictionary dict) { - // Always have to have a base module and orbit module + // Always have to have a base module Base = new BaseModule(); Orbit = new OrbitModule(); diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 4d81d809..0e238d07 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -14,6 +14,8 @@ using OWML.Common; using OWML.ModHelper; using OWML.Utils; using PacificEngine.OW_CommonResources.Game.Player; +using PacificEngine.OW_CommonResources.Game.Resource; +using PacificEngine.OW_CommonResources.Game.State; using System; using System.Collections.Generic; using System.IO; @@ -421,7 +423,64 @@ namespace NewHorizons } // Do stuff that's shared between generating new planets and updating old ones - return SharedGenerateBody(body, go, sector, rb); + go = SharedGenerateBody(body, go, sector, rb); + + // Update a position using CommonResources + // Since orbits are always there just check if they set a semi major axis + if (body.Config.Orbit != null && body.Config.Orbit.SemiMajorAxis != 0f) + { + var mapping = Planet.defaultMapping; + var heavenlyBody = CommonResourcesUtilities.HeavenlyBodyFromAstroObject(AstroObjectLocator.GetAstroObject(body.Config.Name)); + + Logger.Log($"Updating position of {body.Config.Name} -> {heavenlyBody}"); + + if (heavenlyBody != PacificEngine.OW_CommonResources.Game.Resource.HeavenlyBody.None) + { + var original = mapping[heavenlyBody]; + + var targetScale = original.state.orbit.scale; + var coords = OrbitalHelper.KeplerCoordinatesFromOrbitModule(body.Config.Orbit); + var orientation = original.state.orbit.orientation; + + var parent = original.state.parent; + if (body.Config.Orbit.PrimaryBody != null) + { + var parentAO = AstroObjectLocator.GetAstroObject(body.Config.Orbit.PrimaryBody); + var newParent = CommonResourcesUtilities.HeavenlyBodyFromAstroObject(parentAO); + if (newParent != HeavenlyBody.None) + { + parent = newParent; + // Have to change the gravity stuff + go.GetComponentInChildren()._detectableFields = new ForceVolume[] { parentAO.GetGravityVolume() }; + go.GetComponent()._primaryBody = parentAO; + Logger.Log($"WHO???? {body.Config.Name}, {parentAO.name}"); + //Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => UpdatePosition(go, body, parentAO)); + } + else Logger.LogError($"Couldn't find new parent {body.Config.Orbit.PrimaryBody}"); + } + + Logger.Log($"{body.Config.Name} has parent {parent}"); + var planetoid = new Planet.Plantoid( + original.size, + original.gravity, + go.transform.rotation, + InitialMotionBuilder.SiderealPeriodToAngularSpeed(body.Config.Orbit.SiderealPeriod), + parent, + coords + ); + + mapping[heavenlyBody] = planetoid; + + Planet.defaultMapping = mapping; + Planet.mapping = mapping; + } + else + { + Logger.LogError($"Couldn't find heavenlyBody for {body.Config.Name}"); + } + } + + return go; } #endregion Load @@ -504,13 +563,7 @@ namespace NewHorizons body.Object = go; // Now that we're done move the planet into place - go.transform.parent = Locator.GetRootTransform(); - go.transform.position = OrbitalHelper.GetCartesian(new OrbitalHelper.Gravity(1, 100), body.Config.Orbit).Item1 + (primaryBody == null ? Vector3.zero : primaryBody.transform.position); - - if (go.transform.position.magnitude > FurthestOrbit) - { - FurthestOrbit = go.transform.position.magnitude + 30000f; - } + UpdatePosition(go, body, primaryBody); // Have to do this after setting position var initialMotion = InitialMotionBuilder.Make(go, primaryBody, owRigidBody, body.Config.Orbit); @@ -603,6 +656,17 @@ namespace NewHorizons return go; } + private void UpdatePosition(GameObject go, NewHorizonsBody body, AstroObject primaryBody) + { + go.transform.parent = Locator.GetRootTransform(); + go.transform.position = OrbitalHelper.GetCartesian(new OrbitalHelper.Gravity(1, 100), body.Config.Orbit).Item1 + (primaryBody == null ? Vector3.zero : primaryBody.transform.position); + + if (go.transform.position.magnitude > FurthestOrbit) + { + FurthestOrbit = go.transform.position.magnitude + 30000f; + } + } + #endregion Body generation #region Change star system diff --git a/NewHorizons/Utility/CommonResourcesUtilities.cs b/NewHorizons/Utility/CommonResourcesUtilities.cs new file mode 100644 index 00000000..b2da17f3 --- /dev/null +++ b/NewHorizons/Utility/CommonResourcesUtilities.cs @@ -0,0 +1,61 @@ +using PacificEngine.OW_CommonResources.Game.Resource; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.Utility +{ + public static class CommonResourcesUtilities + { + public static HeavenlyBody HeavenlyBodyFromAstroObject(AstroObject obj) + { + switch (obj.GetAstroObjectName()) + { + case AstroObject.Name.CustomString: + return HeavenlyBody.FromString(obj.GetCustomName()); + case AstroObject.Name.BrittleHollow: + return HeavenlyBodies.BrittleHollow; + case AstroObject.Name.CaveTwin: + return HeavenlyBodies.EmberTwin; + case AstroObject.Name.Comet: + return HeavenlyBodies.Interloper; + case AstroObject.Name.DarkBramble: + return HeavenlyBodies.DarkBramble; + case AstroObject.Name.DreamWorld: + return HeavenlyBodies.DreamWorld; + case AstroObject.Name.GiantsDeep: + return HeavenlyBodies.GiantsDeep; + case AstroObject.Name.HourglassTwins: + return HeavenlyBodies.HourglassTwins; + case AstroObject.Name.MapSatellite: + return HeavenlyBodies.SatiliteMapping; + case AstroObject.Name.ProbeCannon: + return HeavenlyBodies.ProbeCannon; + case AstroObject.Name.QuantumMoon: + return HeavenlyBodies.QuantumMoon; + case AstroObject.Name.RingWorld: + return HeavenlyBodies.Stranger; + case AstroObject.Name.Sun: + return HeavenlyBodies.Sun; + case AstroObject.Name.SunStation: + return HeavenlyBodies.SunStation; + case AstroObject.Name.TimberHearth: + return HeavenlyBodies.TimberHearth; + case AstroObject.Name.TimberMoon: + return HeavenlyBodies.Attlerock; + case AstroObject.Name.TowerTwin: + return HeavenlyBodies.AshTwin; + case AstroObject.Name.VolcanicMoon: + return HeavenlyBodies.HollowLantern; + case AstroObject.Name.WhiteHole: + return HeavenlyBodies.WhiteHole; + case AstroObject.Name.WhiteHoleTarget: + return HeavenlyBodies.WhiteHoleStation; + default: + return HeavenlyBodies.None; + } + } + } +} diff --git a/NewHorizons/Utility/SearchUtilities.cs b/NewHorizons/Utility/SearchUtilities.cs index 876ed4c1..f9422cb1 100644 --- a/NewHorizons/Utility/SearchUtilities.cs +++ b/NewHorizons/Utility/SearchUtilities.cs @@ -99,60 +99,67 @@ namespace NewHorizons.Utility public static GameObject Find(string path) { - var go = GameObject.Find(path); - - var names = path.Split(new char[] { '\\', '/' }); - if (go == null) + try { + var go = GameObject.Find(path); - // Get the root object and hope its the right one - var root = GameObject.Find(names[0]); - if (root == null) root = FindObjectOfTypeAndName(names[0]); - - var t = root?.transform; - if (t == null) + var names = path.Split(new char[] { '\\', '/' }); + if (go == null) { - Logger.LogWarning($"Couldn't find root object in path ({names[0]})"); - return null; - } - for (int i = 1; i < names.Length; i++) - { - var child = t.transform.Find(names[i]); + // Get the root object and hope its the right one + var root = GameObject.Find(names[0]); + if (root == null) root = FindObjectOfTypeAndName(names[0]); - if(child == null) + var t = root?.transform; + if (t == null) { - foreach(Transform c in t.GetComponentsInChildren(true)) + Logger.LogWarning($"Couldn't find root object in path ({names[0]})"); + return null; + } + + for (int i = 1; i < names.Length; i++) + { + var child = t.transform.Find(names[i]); + + if (child == null) { - if(t.name.Equals(names[i])) + foreach (Transform c in t.GetComponentsInChildren(true)) { - child = c; - break; + if (t.name.Equals(names[i])) + { + child = c; + break; + } } } + + if (child == null) + { + Logger.LogWarning($"Couldn't find object in path ({names[i]})"); + t = null; + break; + } + + t = child; } - if (child == null) - { - Logger.LogWarning($"Couldn't find object in path ({names[i]})"); - t = null; - break; - } - - t = child; + go = t?.gameObject; } - go = t?.gameObject; - } + if (go == null) + { + var name = names.Last(); + Logger.LogWarning($"Couldn't find object {path}, will look for potential matches for name {name}"); + go = FindObjectOfTypeAndName(name); + } - if(go == null) + return go; + } + catch(Exception) { - var name = names.Last(); - Logger.LogWarning($"Couldn't find object {path}, will look for potential matches for name {name}"); - go = FindObjectOfTypeAndName(name); + return null; } - - return go; } } } From aa73f2b92a0db362ef793341ec4b3eb4f72d8830 Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 9 Feb 2022 15:28:19 -0500 Subject: [PATCH 11/23] Add issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 38 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..dd84ea78 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..bbcbbe7d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From 1a0ac92de77da530398083a28631f8f5d33e834b Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Fri, 11 Feb 2022 00:38:08 -0500 Subject: [PATCH 12/23] Clean up OrbitUpdater --- NewHorizons/Builder/Updater/OrbitUpdater.cs | 69 +++++++++++++++++++++ NewHorizons/Main.cs | 51 +-------------- 2 files changed, 71 insertions(+), 49 deletions(-) create mode 100644 NewHorizons/Builder/Updater/OrbitUpdater.cs diff --git a/NewHorizons/Builder/Updater/OrbitUpdater.cs b/NewHorizons/Builder/Updater/OrbitUpdater.cs new file mode 100644 index 00000000..695d9c87 --- /dev/null +++ b/NewHorizons/Builder/Updater/OrbitUpdater.cs @@ -0,0 +1,69 @@ +using NewHorizons.Builder.Orbital; +using NewHorizons.OrbitalPhysics; +using NewHorizons.Utility; +using PacificEngine.OW_CommonResources.Game.Resource; +using PacificEngine.OW_CommonResources.Game.State; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Builder.Updater +{ + public static class OrbitUpdater + { + public static void Update(NewHorizonsBody body, GameObject go) + { + var mapping = Planet.defaultMapping; + var heavenlyBody = CommonResourcesUtilities.HeavenlyBodyFromAstroObject(AstroObjectLocator.GetAstroObject(body.Config.Name)); + + Logger.Log($"Updating position of {body.Config.Name}/{heavenlyBody}"); + + if (heavenlyBody != HeavenlyBody.None) + { + var original = mapping[heavenlyBody]; + + var coords = OrbitalHelper.KeplerCoordinatesFromOrbitModule(body.Config.Orbit); + + var parent = original.state.parent; + if (body.Config.Orbit.PrimaryBody != null) + { + var parentAO = AstroObjectLocator.GetAstroObject(body.Config.Orbit.PrimaryBody); + var newParent = CommonResourcesUtilities.HeavenlyBodyFromAstroObject(parentAO); + if (newParent != HeavenlyBody.None) + { + Logger.LogWarning($"Sorry, can't change primary body for planets yet. You tried making {body.Config.Name} orbit {newParent}"); + /* + parent = newParent; + // Have to change the gravity stuff + go.GetComponentInChildren()._detectableFields = new ForceVolume[] { parentAO.GetGravityVolume() }; + go.GetComponent()._primaryBody = parentAO; + */ + } + else Logger.LogError($"Couldn't find new parent {body.Config.Orbit.PrimaryBody}"); + } + + var planetoid = new Planet.Plantoid( + original.size, + original.gravity, + go.transform.rotation, + InitialMotionBuilder.SiderealPeriodToAngularSpeed(body.Config.Orbit.SiderealPeriod), + parent, + coords + ); + + mapping[heavenlyBody] = planetoid; + + Planet.defaultMapping = mapping; + Planet.mapping = mapping; + } + else + { + Logger.LogError($"Couldn't find heavenlyBody for {body.Config.Name}"); + } + } + } +} diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 0e238d07..74d73c23 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -4,6 +4,7 @@ using NewHorizons.Builder.Body; using NewHorizons.Builder.General; using NewHorizons.Builder.Orbital; using NewHorizons.Builder.Props; +using NewHorizons.Builder.Updater; using NewHorizons.Components; using NewHorizons.External; using NewHorizons.External.VariableSize; @@ -429,55 +430,7 @@ namespace NewHorizons // Since orbits are always there just check if they set a semi major axis if (body.Config.Orbit != null && body.Config.Orbit.SemiMajorAxis != 0f) { - var mapping = Planet.defaultMapping; - var heavenlyBody = CommonResourcesUtilities.HeavenlyBodyFromAstroObject(AstroObjectLocator.GetAstroObject(body.Config.Name)); - - Logger.Log($"Updating position of {body.Config.Name} -> {heavenlyBody}"); - - if (heavenlyBody != PacificEngine.OW_CommonResources.Game.Resource.HeavenlyBody.None) - { - var original = mapping[heavenlyBody]; - - var targetScale = original.state.orbit.scale; - var coords = OrbitalHelper.KeplerCoordinatesFromOrbitModule(body.Config.Orbit); - var orientation = original.state.orbit.orientation; - - var parent = original.state.parent; - if (body.Config.Orbit.PrimaryBody != null) - { - var parentAO = AstroObjectLocator.GetAstroObject(body.Config.Orbit.PrimaryBody); - var newParent = CommonResourcesUtilities.HeavenlyBodyFromAstroObject(parentAO); - if (newParent != HeavenlyBody.None) - { - parent = newParent; - // Have to change the gravity stuff - go.GetComponentInChildren()._detectableFields = new ForceVolume[] { parentAO.GetGravityVolume() }; - go.GetComponent()._primaryBody = parentAO; - Logger.Log($"WHO???? {body.Config.Name}, {parentAO.name}"); - //Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => UpdatePosition(go, body, parentAO)); - } - else Logger.LogError($"Couldn't find new parent {body.Config.Orbit.PrimaryBody}"); - } - - Logger.Log($"{body.Config.Name} has parent {parent}"); - var planetoid = new Planet.Plantoid( - original.size, - original.gravity, - go.transform.rotation, - InitialMotionBuilder.SiderealPeriodToAngularSpeed(body.Config.Orbit.SiderealPeriod), - parent, - coords - ); - - mapping[heavenlyBody] = planetoid; - - Planet.defaultMapping = mapping; - Planet.mapping = mapping; - } - else - { - Logger.LogError($"Couldn't find heavenlyBody for {body.Config.Name}"); - } + OrbitUpdater.Update(body, go); } return go; From 5afdbd94c37fc679e617e620cf1502c1ef5b1528 Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Fri, 11 Feb 2022 00:38:35 -0500 Subject: [PATCH 13/23] Fix SearchUtilities find method --- NewHorizons/Utility/SearchUtilities.cs | 37 +++++++++++++------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/NewHorizons/Utility/SearchUtilities.cs b/NewHorizons/Utility/SearchUtilities.cs index f9422cb1..953fe211 100644 --- a/NewHorizons/Utility/SearchUtilities.cs +++ b/NewHorizons/Utility/SearchUtilities.cs @@ -115,33 +115,34 @@ namespace NewHorizons.Utility if (t == null) { Logger.LogWarning($"Couldn't find root object in path ({names[0]})"); - return null; } - - for (int i = 1; i < names.Length; i++) + else { - var child = t.transform.Find(names[i]); - - if (child == null) + for (int i = 1; i < names.Length; i++) { - foreach (Transform c in t.GetComponentsInChildren(true)) + var child = t.transform.Find(names[i]); + + if (child == null) { - if (t.name.Equals(names[i])) + foreach (Transform c in t.GetComponentsInChildren(true)) { - child = c; - break; + if (t.name.Equals(names[i])) + { + child = c; + break; + } } } - } - if (child == null) - { - Logger.LogWarning($"Couldn't find object in path ({names[i]})"); - t = null; - break; - } + if (child == null) + { + Logger.LogWarning($"Couldn't find object in path ({names[i]})"); + t = null; + break; + } - t = child; + t = child; + } } go = t?.gameObject; From 7f1f06f73706305723911fc8e67507b9faeaf95c Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Fri, 11 Feb 2022 00:38:57 -0500 Subject: [PATCH 14/23] Remove detail generateColliders, add in removeChildren list --- NewHorizons/Builder/Props/DetailBuilder.cs | 40 +++++++++++---------- NewHorizons/Builder/Props/ScatterBuilder.cs | 2 +- NewHorizons/External/PropModule.cs | 3 +- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index 7970b7e0..cbfc88ea 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -16,10 +16,12 @@ namespace NewHorizons.Builder.Props { public static void Make(GameObject go, Sector sector, IPlanetConfig config, IModAssets assets, string uniqueModName, PropModule.DetailInfo detail) { + GameObject detailGO = null; + if (detail.assetBundle != null) { var prefab = PropBuildManager.LoadPrefab(detail.assetBundle, detail.path, uniqueModName, assets); - MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal, detail.generateColliders); + detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal); } else if (detail.objFilePath != null) { @@ -27,24 +29,33 @@ namespace NewHorizons.Builder.Props { var prefab = assets.Get3DObject(detail.objFilePath, detail.mtlFilePath); prefab.SetActive(false); - MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal, detail.generateColliders); + detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal); } catch (Exception e) { Logger.LogError($"Could not load 3d object {detail.objFilePath} with texture {detail.mtlFilePath} : {e.Message}"); } } - else MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal, detail.generateColliders); + else detailGO = MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal); + + if(detailGO != null && detail.removeChildren != null) + { + foreach(var childPath in detail.removeChildren) + { + var childObj = SearchUtilities.Find(SearchUtilities.GetPath(detailGO.transform) + "/" + childPath); + childObj.gameObject.SetActive(false); + } + } } - public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal, bool generateColliders) + public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) { var prefab = SearchUtilities.Find(propToClone); if (prefab == null) Logger.LogError($"Couldn't find detail {propToClone}"); - return MakeDetail(go, sector, prefab, position, rotation, scale, alignWithNormal, generateColliders); + return MakeDetail(go, sector, prefab, position, rotation, scale, alignWithNormal); } - public static GameObject MakeDetail(GameObject go, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal, bool generateColliders) + public static GameObject MakeDetail(GameObject go, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) { if (prefab == null) return null; @@ -77,7 +88,11 @@ namespace NewHorizons.Builder.Props if (component is GhostIK) (component as GhostIK).enabled = false; if (component is GhostEffects) (component as GhostEffects).enabled = false; - if (component is Animator) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => (component as Animator).enabled = true); + // If it's not a moving anglerfish make sure the anim controller is off + if(component is AnglerfishAnimController && component.GetComponentInParent() == null) + Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => (component as AnglerfishAnimController).enabled = false); + + if (component is Animator) Main.Instance.ModHelper.Events.Unity.FireInNUpdates(() => (component as Animator).enabled = true, 5); if (component is Collider) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => (component as Collider).enabled = true); if(component is Shape) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => (component as Shape).enabled = true); @@ -104,17 +119,6 @@ namespace NewHorizons.Builder.Props Logger.LogError($"Couldn't update AnglerFish chase speed: {e.Message}"); } } - - // Mesh colliders - if (generateColliders) - { - if (component is MeshFilter && component.gameObject.GetComponent() == null) - { - var mesh = (component as MeshFilter).mesh; - if (mesh.isReadable) component.gameObject.AddComponent(); - else Logger.LogError($"Couldn't change mesh for {component.gameObject.name} because it is not readable"); - } - } } prop.transform.position = position == null ? go.transform.position : go.transform.TransformPoint((Vector3)position); diff --git a/NewHorizons/Builder/Props/ScatterBuilder.cs b/NewHorizons/Builder/Props/ScatterBuilder.cs index 0538fee2..4990c867 100644 --- a/NewHorizons/Builder/Props/ScatterBuilder.cs +++ b/NewHorizons/Builder/Props/ScatterBuilder.cs @@ -71,7 +71,7 @@ namespace NewHorizons.Builder.Props height -= 0.2f; } - var prop = DetailBuilder.MakeDetail(go, sector, prefab, (MVector3)(point.normalized * height), null, propInfo.scale, true, propInfo.generateColliders); + var prop = DetailBuilder.MakeDetail(go, sector, prefab, (MVector3)(point.normalized * height), null, propInfo.scale, true); if (propInfo.offset != null) prop.transform.localPosition += prop.transform.TransformVector(propInfo.offset); if (propInfo.rotation != null) prop.transform.rotation *= Quaternion.Euler(propInfo.rotation); points.RemoveAt(randomInd); diff --git a/NewHorizons/External/PropModule.cs b/NewHorizons/External/PropModule.cs index dfe7455c..2d35bfe3 100644 --- a/NewHorizons/External/PropModule.cs +++ b/NewHorizons/External/PropModule.cs @@ -25,7 +25,6 @@ namespace NewHorizons.External public MVector3 offset; public MVector3 rotation; public float scale { get; set; } = 1f; - public bool generateColliders = false; } public class DetailInfo @@ -38,7 +37,7 @@ namespace NewHorizons.External public MVector3 rotation; public float scale { get; set; } = 1f; public bool alignToNormal; - public bool generateColliders = false; + public string[] removeChildren; } public class RaftInfo From 24b444c40a4e7cd5dbb132fccfdb9fa8e2423b36 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 11 Feb 2022 16:23:33 -0500 Subject: [PATCH 15/23] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8d0f6e64..4de9d623 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,8 @@ Check the ship's log for how to use your warp drive to travel between star syste ## How to create your own planets using configs +**Note that I'm more than happy to help you debug your planet config files, but please don't just use notepad to edit them. Use something like Visual Studio Code that will check your .json file for errors. It will save both of us time.** + There is a template [here](https://github.com/xen-42/ow-new-horizons-config-template) if you want to release your own planet mod using configs. You can learn how the configs work by picking apart the [Real Solar System](https://github.com/xen-42/outer-wilds-real-solar-system) mod or the [New Horizons Examples](https://github.com/xen-42/ow-new-horizons-examples) mod. Planets are created using a JSON file format structure, and placed in a folder called `planets` (or in any sub-directory of it) in the location where New Horizons is installed (by default this folder doesn't exist, you have to create it within the `xen.NewHorizons` directory). From 4a9642500177acd0029ded7c46c71842065bf522 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 11 Feb 2022 16:32:22 -0500 Subject: [PATCH 16/23] Update README.md --- README.md | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 4de9d623..e9bff777 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ To locate this directory, click the "..." symbol next to "New Horizons" in the O ![Create a planets folder in the mod directory](https://user-images.githubusercontent.com/22628069/149638007-26b872ab-f02e-455f-a7fd-99d0d2a96de8.png) Now that you have created your planets folder, this is where you will put your planet config files. A config file will look something like this: -``` +```json { "name" : "Wetrock", "$schema": "https://raw.githubusercontent.com/xen-42/outer-wilds-new-horizons/master/NewHorizons/schema.json", @@ -155,7 +155,7 @@ Each { must match up with a closing } to denote its section. If you don't know h Modules look like this: -``` +```json "Star" : { "size" : 3000, @@ -174,26 +174,26 @@ In this example the `Star` module has a `size` field and a `tint` field. Since t Most fields are either true/false, a decimal number, and integer number, or a string (word with quotation marks around it). There are also the following types of values: #### Colour: -``` +```json { - "r" : 200, - "g" : 255, - "b" : 255, - "a" : 255 + "r" : 200, + "g" : 255, + "b" : 255, + "a" : 255 } ``` #### Position: -``` +```json { - "x" : 182.4, - "y" : 227.4, - "z" : 62.7, + "x" : 182.4, + "y" : 227.4, + "z" : 62.7, } ``` #### Scale curve: -``` +```json [ {"time":0, "value":1}, {"time":5, "value":0}, @@ -271,7 +271,7 @@ Let's you put asteroids in orbit around a planet or star. Can probably negativel ### FocalPoint If you want to have binary planets or stars you have to do a few extra steps. First you make a focal point body. Here's an example (note the "..." means you'd be writing stuff there but it isn't important for the example. Don't literally put "..."): -``` +```json { "name" : "Alpha Centauri", "Base" : @@ -292,7 +292,7 @@ If you want to have binary planets or stars you have to do a few extra steps. Fi } ``` Then you would make config files for the two bodies in the binary pair. -``` +```json { "name" : "Alpha Centauri A", "Base" : @@ -312,7 +312,7 @@ Then you would make config files for the two bodies in the binary pair. } ``` and -``` +```json { "name" : "Alpha Centauri B", "Base" : @@ -346,7 +346,7 @@ The different things you can specify in the props section are: - "scatter" : (list) I'll just give an example. -``` +```json "scatter" : [ {"path" : "DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_1/Props_DreamZone_1/OtherComponentsGroup/Trees_Z1/DreamHouseIsland/Tree_DW_M_Var", "count" : 12} ] @@ -377,7 +377,7 @@ If for whatever reason you want to set up a Unity project manually instead of us 1. Start up a Unity 2017 project (I use Unity 2017.4.40f1 (64-bit), so if you use something else I can't guarantee it will work). The DLC updated Outer Wilds to 2019.4.27 so that probably works but I personally haven't tried it. 2. In the "Assets" folder in Unity, create a new folder called "Editor". In it create a file called "CreateAssetBundle.cs" with the following code in it: -``` +```cs using UnityEditor; using UnityEngine; using System.IO; @@ -414,7 +414,7 @@ An array of object, each one has the following properties: #### XML Here's an example dialogue XML: -``` +```xml EXAMPLE NPC @@ -536,7 +536,7 @@ Signal info objects can then have the following values set: - "insideCloak" : (true/false) You have to set this to true if the signal is inside a cloaking field Here's an example of what all this looks like, for more check my [Signals+](https://github.com/xen-42/outer-wilds-signals-plus) add-on: -``` +```json "Signal" : { "Signals" : @@ -577,7 +577,7 @@ This allows you to make black holes and white holes, and to pair them. ### How to destroy existing planets You do this (but with the appropriate name) as it's own config. -``` +```json { "name" : "Ember Twin", "destroy" : true, @@ -593,7 +593,7 @@ Similar to above, make a config where "Name" is the name of the planet. The name Only some of the above modules are supported (currently) for existing planets. Things you cannot modify for existing planets include: heightmaps, procedural generation, gravity, or their orbits. You also can't make them into stars or binary focal points (but why would you want to, just delete them and replace them entirely). However this still means there are many things you can do: completely change their atmospheres, give them rings, asteroid belts, comet tails, lava, water, prop details, or signals. You can also delete parts of an existing planet. Here's part of an example config which would delete the rising sand from Ember Twin: -``` +```json "name" : "Ember Twin", "childrenToDestroy" : ["SandSphere_Rising"], ``` @@ -604,7 +604,7 @@ In `childrenToDestroy` you list the relative paths for the children of the plane First create the following interface in your mod: -``` +```cs public interface INewHorizons { void Create(Dictionary config, IModBehaviour mod); @@ -616,7 +616,7 @@ public interface INewHorizons ``` In your main `ModBehaviour` class you can get the NewHorizons API like so: -``` +```cs INewHorizons NewHorizonsAPI = ModHelper.Interaction.GetModApi("xen.NewHorizons") ``` From 96b1584b6259663bfe9d8a73a6ea33b457f74556 Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Fri, 11 Feb 2022 17:06:17 -0500 Subject: [PATCH 17/23] Make spawn points more consistent --- NewHorizons/Builder/General/SpawnPointBuilder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Builder/General/SpawnPointBuilder.cs b/NewHorizons/Builder/General/SpawnPointBuilder.cs index 37b5a2d6..cd54f9a7 100644 --- a/NewHorizons/Builder/General/SpawnPointBuilder.cs +++ b/NewHorizons/Builder/General/SpawnPointBuilder.cs @@ -22,7 +22,7 @@ namespace NewHorizons.Builder.General playerSpawn = spawnGO.AddComponent(); spawnGO.transform.rotation = Quaternion.FromToRotation(Vector3.up, (playerSpawn.transform.position - body.transform.position).normalized); - spawnGO.transform.position = spawnGO.transform.position + spawnGO.transform.TransformDirection(Vector3.up) * 2f; + spawnGO.transform.position = spawnGO.transform.position + spawnGO.transform.TransformDirection(Vector3.up) * 4f; GameObject.FindObjectOfType().SetInitialSpawnPoint(playerSpawn); } @@ -41,7 +41,7 @@ namespace NewHorizons.Builder.General ship.transform.position = spawnPoint.transform.position; ship.transform.rotation = Quaternion.FromToRotation(Vector3.up, (spawnPoint.transform.position - body.transform.position).normalized); // Move it up a bit more - ship.transform.position = ship.transform.position + ship.transform.TransformDirection(Vector3.up) * 5f; + ship.transform.position = ship.transform.position + ship.transform.TransformDirection(Vector3.up) * 4f; ship.GetRequiredComponent().SetBodyToMatch(rb); From 5033173b66ec542d1afb110f37332d996c37fa32 Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Sun, 13 Feb 2022 21:11:43 -0500 Subject: [PATCH 18/23] Fix MColor cast to Color32 --- NewHorizons/Utility/MColor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Utility/MColor.cs b/NewHorizons/Utility/MColor.cs index 228ac25a..e18e6b66 100644 --- a/NewHorizons/Utility/MColor.cs +++ b/NewHorizons/Utility/MColor.cs @@ -17,7 +17,7 @@ namespace NewHorizons.Utility public int B { get; } public int A { get; } - public Color32 ToColor32() => new Color(R, G, B, A); + public Color32 ToColor32() => new Color32((byte)R, (byte)G, (byte)B, (byte)A); public Color ToColor() => new Color(R / 255f, G / 255f, B / 255f, A / 255f); } From ec3d2ed1b9e1fdc2691cede4c2cc869d9a5217f1 Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Sun, 13 Feb 2022 21:25:52 -0500 Subject: [PATCH 19/23] Make map-mode/altimeter not work when its a satellite --- .../Builder/Atmosphere/VolumesBuilder.cs | 15 +++++----- .../Builder/General/RFVolumeBuilder.cs | 30 +++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/NewHorizons/Builder/Atmosphere/VolumesBuilder.cs b/NewHorizons/Builder/Atmosphere/VolumesBuilder.cs index 569d8b14..f4128814 100644 --- a/NewHorizons/Builder/Atmosphere/VolumesBuilder.cs +++ b/NewHorizons/Builder/Atmosphere/VolumesBuilder.cs @@ -7,7 +7,7 @@ namespace NewHorizons.Atmosphere { static class VolumesBuilder { - public static void Make(GameObject body, float innerRadius, float outerRadius) + public static void Make(GameObject body, float innerRadius, float outerRadius, IPlanetConfig config) { GameObject volumesGO = new GameObject("Volumes"); volumesGO.SetActive(false); @@ -24,17 +24,18 @@ namespace NewHorizons.Atmosphere SS.pointChecksOnly = true; SS.radius = outerRadius; - /*OWTriggerVolume trigvol = */ rulesetGO.AddComponent(); PlanetoidRuleset PR = rulesetGO.AddComponent(); - PR.SetValue("_altitudeFloor", innerRadius); - PR.SetValue("_altitudeCeiling", outerRadius); + PR._altitudeFloor = innerRadius; + PR._altitudeCeiling = outerRadius; + PR._useMinimap = !config.Base.IsSatellite; + PR._useAltimeter = !config.Base.IsSatellite; EffectRuleset ER = rulesetGO.AddComponent(); - ER.SetValue("_type", EffectRuleset.BubbleType.Underwater); - ER.SetValue("_material", GameObject.Find("RulesetVolumes_GD").GetComponent().GetValue("_material")); - ER.SetValue("_cloudMaterial", GameObject.Find("RulesetVolumes_GD").GetComponent().GetValue("_cloudMaterial")); + ER._type = EffectRuleset.BubbleType.Underwater; + ER._material = GameObject.Find("RulesetVolumes_GD").GetComponent().GetValue("_material"); + ER._cloudMaterial = GameObject.Find("RulesetVolumes_GD").GetComponent().GetValue("_cloudMaterial"); volumesGO.transform.localPosition = Vector3.zero; rulesetGO.SetActive(true); diff --git a/NewHorizons/Builder/General/RFVolumeBuilder.cs b/NewHorizons/Builder/General/RFVolumeBuilder.cs index c93811f9..4e17d11d 100644 --- a/NewHorizons/Builder/General/RFVolumeBuilder.cs +++ b/NewHorizons/Builder/General/RFVolumeBuilder.cs @@ -22,22 +22,22 @@ namespace NewHorizons.Builder.General ReferenceFrameVolume RFV = rfGO.AddComponent(); ReferenceFrame RV = new ReferenceFrame(rigidbody); - RV.SetValue("_minSuitTargetDistance", sphereOfInfluence); - RV.SetValue("_maxTargetDistance", 0); - RV.SetValue("_autopilotArrivalDistance", sphereOfInfluence * 2f); - RV.SetValue("_autoAlignmentDistance", sphereOfInfluence * 1.5f); + RV._minSuitTargetDistance = sphereOfInfluence; + RV._maxTargetDistance = 0; + RV._autopilotArrivalDistance = 2.0f * sphereOfInfluence; + RV._autoAlignmentDistance = sphereOfInfluence * 1.5f; + + RV._hideLandingModePrompt = false; + RV._matchAngularVelocity = true; + RV._minMatchAngularVelocityDistance = 70; + RV._maxMatchAngularVelocityDistance = 400; + RV._bracketsRadius = sphereOfInfluence; - RV.SetValue("_hideLandingModePrompt", false); - RV.SetValue("_matchAngularVelocity", true); - RV.SetValue("_minMatchAngularVelocityDistance", 70); - RV.SetValue("_maxMatchAngularVelocityDistance", 400); - RV.SetValue("_bracketsRadius", sphereOfInfluence); - - RFV.SetValue("_referenceFrame", RV); - RFV.SetValue("_minColliderRadius", sphereOfInfluence); - RFV.SetValue("_maxColliderRadius", sphereOfInfluence * 2f); - RFV.SetValue("_isPrimaryVolume", true); - RFV.SetValue("_isCloseRangeVolume", false); + RFV._referenceFrame = RV; + RFV._minColliderRadius = sphereOfInfluence; + RFV._maxColliderRadius = sphereOfInfluence * 2f; + RFV._isPrimaryVolume = true; + RFV._isCloseRangeVolume = false; rfGO.SetActive(true); } From 0251e5f8168874cfe7afcea91458651f4ace5ab4 Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Sun, 13 Feb 2022 21:27:17 -0500 Subject: [PATCH 20/23] Update Main.cs --- NewHorizons/Main.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 74d73c23..29d4b03b 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -497,7 +497,7 @@ namespace NewHorizons var sector = MakeSector.Make(go, owRigidBody, sphereOfInfluence * 2f); ao.SetValue("_rootSector", sector); - VolumesBuilder.Make(go, body.Config.Base.SurfaceSize, sphereOfInfluence); + VolumesBuilder.Make(go, body.Config.Base.SurfaceSize, sphereOfInfluence, body.Config); if (body.Config.HeightMap != null) HeightMapBuilder.Make(go, body.Config.HeightMap, body.Mod.Assets); From 0ecf699de81c443d498051de27b783d24538ceed Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Sun, 13 Feb 2022 21:45:38 -0500 Subject: [PATCH 21/23] Update manifest.json --- NewHorizons/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/manifest.json b/NewHorizons/manifest.json index 1c5e0043..493970eb 100644 --- a/NewHorizons/manifest.json +++ b/NewHorizons/manifest.json @@ -3,7 +3,7 @@ "author": "xen", "name": "New Horizons", "uniqueName": "xen.NewHorizons", - "version": "0.8.2", + "version": "0.8.3", "owmlVersion": "2.1.0", "dependencies": [ "PacificEngine.OW_CommonResources" ], "conflicts": [ "Raicuparta.QuantumSpaceBuddies", "Vesper.OuterWildsMMO", "Vesper.AutoResume" ] From 6a6ce669875458ea861476cfecda74709c4aec7f Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 13 Feb 2022 21:48:18 -0500 Subject: [PATCH 22/23] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e9bff777..68c942fe 100644 --- a/README.md +++ b/README.md @@ -363,6 +363,7 @@ A detail info object can have the following parameters: - "rotation" : (x, y, z) the euler angle rotation from a 3d vector (in degrees) - "scale" : (decimal number) - "alignToNormal" : (true/false) If it should align with the normal vector of the surface its own (overwrites rotation) +- "removeChildren" : (list of strings) relative paths of children to get rid of You have three options: Load from the scene hierarchy by setting "path", load from an asset bundle by setting "path" and "assetBundle", or load an obj file by setting "objFilePath" and "mtlFilePath". Asset bundles give much better results than .obj's. From 0f94d5b351ad4c1804b5027fac08b3a1a9969bb8 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 15 Feb 2022 12:05:49 -0500 Subject: [PATCH 23/23] Update thumbnail --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 68c942fe..34592252 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![new horizons thumbnail](https://user-images.githubusercontent.com/22628069/146680547-bd815057-9f4e-42da-a6c4-84d3ff82ff2c.png) +![new horizons thumbnail 2](https://user-images.githubusercontent.com/22628069/154112130-b777f618-245f-44c9-9408-e11141fc5fde.png) ![Current version](https://img.shields.io/github/manifest-json/v/xen-42/outer-wilds-new-horizons?color=gree&filename=NewHorizons%2Fmanifest.json) ![Downloads](https://img.shields.io/github/downloads/xen-42/outer-wilds-new-horizons/total)