mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
1.23.0 (#956)
Thank you Hawkbar for implementing custom Dreamworlds in this update! ## Major features - Added `Dream.inDreamWorld` to planet configs to treat a planet as if it were part of the dream world dimension. The planet's contents will be deactivated unless you enter via a dream arrival point or another dream world dimension. Closes #916 - Added `dreamCampfires` and `dreamArrivalPoints` as new linked prop types, which allow you to create new entry points into Echoes of the Eye's dream world or create similar experiences using custom planets. ## Improvements - General support for dream world simulations even if the vanilla dream world is disabled in custom solar systems. - Preserve held items when warping (closes #192). Note that if you leave an item in another system and warp out, that item will be gone forever from all systems until you start a new loop. Some items (i.e., slide reels) do not work between systems. ## Bug fixes - Time loop will be disabled in other systems if you removed the AWC and warped while holding it or using the Vessel. Closes #952 - Fixed configs getting loaded more than once if parent body is updated again #921
This commit is contained in:
commit
bb978af67b
107
NewHorizons/Builder/Body/DreamDimensionBuilder.cs
Normal file
107
NewHorizons/Builder/Body/DreamDimensionBuilder.cs
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
using NewHorizons.Components.EOTE;
|
||||||
|
using NewHorizons.Components.Props;
|
||||||
|
using NewHorizons.External;
|
||||||
|
using NewHorizons.External.Configs;
|
||||||
|
using NewHorizons.Utility;
|
||||||
|
using NewHorizons.Utility.OuterWilds;
|
||||||
|
using NewHorizons.Utility.OWML;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Builder.Body
|
||||||
|
{
|
||||||
|
public static class DreamDimensionBuilder
|
||||||
|
{
|
||||||
|
private static Material gridMaterial;
|
||||||
|
private static Material waterMaterial;
|
||||||
|
|
||||||
|
private readonly static string[] EXCLUDED_OBJECT_NAMES =
|
||||||
|
{
|
||||||
|
"Prefab_IP_SIM_",
|
||||||
|
"Props_IP_SIM_",
|
||||||
|
"Effects_IP_SIM_",
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly static string[] EXCLUDED_SHADER_NAMES =
|
||||||
|
{
|
||||||
|
"Fog",
|
||||||
|
"Simulation Bubble",
|
||||||
|
"Foliage",
|
||||||
|
"Flame",
|
||||||
|
};
|
||||||
|
|
||||||
|
public static void Make(GameObject planetGO, Sector sector, NewHorizonsBody body)
|
||||||
|
{
|
||||||
|
var bodyWantsSimMeshes = body.Config.Dream?.generateSimulationMeshes ?? false;
|
||||||
|
var propsWantSimMeshes = body.Config.Props?.dreamArrivalPoints?.Any(p => p.generateSimulationMeshes) ?? false;
|
||||||
|
if (bodyWantsSimMeshes || propsWantSimMeshes)
|
||||||
|
{
|
||||||
|
MakeDreamSimulationMeshes(sector ? sector.gameObject : planetGO);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body.Config?.Dream?.inDreamWorld ?? false)
|
||||||
|
{
|
||||||
|
var dreamDimension = planetGO.AddComponent<DreamDimension>();
|
||||||
|
Delay.FireInNUpdates(() =>
|
||||||
|
{
|
||||||
|
dreamDimension.Initialize();
|
||||||
|
}, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void MakeDreamSimulationMeshes(GameObject go)
|
||||||
|
{
|
||||||
|
if (gridMaterial == null) gridMaterial = SearchUtilities.FindResourceOfTypeAndName<Material>("Terrain_IP_DreamGrid_mat");
|
||||||
|
if (waterMaterial == null) waterMaterial = SearchUtilities.FindResourceOfTypeAndName<Material>("Terrain_IP_DreamGrid_mat");
|
||||||
|
|
||||||
|
foreach (var mr in go.GetComponentsInChildren<MeshRenderer>(true))
|
||||||
|
{
|
||||||
|
if (mr.GetType() != typeof(MeshRenderer)) continue;
|
||||||
|
var mf = mr.GetComponent<MeshFilter>();
|
||||||
|
if (mf == null) continue;
|
||||||
|
if (!CheckMeshCreationHeuristic(mr.gameObject, mr.sharedMaterials)) continue;
|
||||||
|
var simMesh = new GameObject("SimulationMesh").AddComponent<DreamSimulationMesh>();
|
||||||
|
simMesh.Init(mr.transform, GetMeshMaterial(go, mr.sharedMaterials));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Material GetMeshMaterial(GameObject go, Material[] materials)
|
||||||
|
{
|
||||||
|
if (materials.Any(m => m.name.Contains("Ocean_Stencil_mat"))) return waterMaterial;
|
||||||
|
return gridMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CheckMeshCreationHeuristic(GameObject go, Material[] materials)
|
||||||
|
{
|
||||||
|
if (go.layer == Layer.DreamSimulation) return false;
|
||||||
|
var mr = go.GetComponent<MeshRenderer>();
|
||||||
|
if (EXCLUDED_SHADER_NAMES.Any(name => materials.Any(mat => mat.shader.name.Contains(name)))) return false;
|
||||||
|
if (go.transform.parent)
|
||||||
|
{
|
||||||
|
foreach (Transform c in go.transform.parent)
|
||||||
|
{
|
||||||
|
if (c && c.gameObject.layer == Layer.DreamSimulation) return false;
|
||||||
|
}
|
||||||
|
if (go.transform.parent.parent)
|
||||||
|
{
|
||||||
|
foreach (Transform c in go.transform.parent.parent)
|
||||||
|
{
|
||||||
|
if (c && c.gameObject.layer == Layer.DreamSimulation) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var t = go.transform;
|
||||||
|
while (t != null)
|
||||||
|
{
|
||||||
|
if (EXCLUDED_OBJECT_NAMES.Any(t.name.Contains)) return false;
|
||||||
|
t = t.parent;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ using UnityEngine;
|
|||||||
using NewHorizons.Utility;
|
using NewHorizons.Utility;
|
||||||
using NewHorizons.External.Modules;
|
using NewHorizons.External.Modules;
|
||||||
using NewHorizons.Utility.Files;
|
using NewHorizons.Utility.Files;
|
||||||
|
using NewHorizons.Components;
|
||||||
|
|
||||||
namespace NewHorizons.Builder.General
|
namespace NewHorizons.Builder.General
|
||||||
{
|
{
|
||||||
|
|||||||
@ -10,16 +10,25 @@ namespace NewHorizons.Builder.Orbital
|
|||||||
private static Material _dottedLineMaterial;
|
private static Material _dottedLineMaterial;
|
||||||
private static Material _lineMaterial;
|
private static Material _lineMaterial;
|
||||||
|
|
||||||
public static OrbitLine Make(GameObject planetGO, NHAstroObject astroObject, bool isMoon, PlanetConfig config)
|
public static GameObject Make(GameObject planetGO, bool isMoon, PlanetConfig config)
|
||||||
|
{
|
||||||
|
var orbitGO = new GameObject("Orbit");
|
||||||
|
orbitGO.transform.parent = planetGO.transform;
|
||||||
|
orbitGO.transform.localPosition = Vector3.zero;
|
||||||
|
|
||||||
|
Delay.FireOnNextUpdate(() => PostMake(orbitGO, planetGO, isMoon, config));
|
||||||
|
return orbitGO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PostMake(GameObject orbitGO, GameObject planetGO, bool isMoon, PlanetConfig config)
|
||||||
{
|
{
|
||||||
if (_dottedLineMaterial == null) _dottedLineMaterial = SearchUtilities.FindResourceOfTypeAndName<Material>("Effects_SPA_OrbitLine_Dotted_mat");
|
if (_dottedLineMaterial == null) _dottedLineMaterial = SearchUtilities.FindResourceOfTypeAndName<Material>("Effects_SPA_OrbitLine_Dotted_mat");
|
||||||
if (_lineMaterial == null) _lineMaterial = SearchUtilities.FindResourceOfTypeAndName<Material>("Effects_SPA_OrbitLine_mat");
|
if (_lineMaterial == null) _lineMaterial = SearchUtilities.FindResourceOfTypeAndName<Material>("Effects_SPA_OrbitLine_mat");
|
||||||
|
|
||||||
if (_dottedLineMaterial == null || _lineMaterial == null) return null;
|
// Might've been otherwise destroyed when updating
|
||||||
|
if (orbitGO == null) return;
|
||||||
|
|
||||||
var orbitGO = new GameObject("Orbit");
|
var astroObject = planetGO.GetComponent<NHAstroObject>();
|
||||||
orbitGO.transform.parent = planetGO.transform;
|
|
||||||
orbitGO.transform.localPosition = Vector3.zero;
|
|
||||||
|
|
||||||
var lineRenderer = orbitGO.AddComponent<LineRenderer>();
|
var lineRenderer = orbitGO.AddComponent<LineRenderer>();
|
||||||
|
|
||||||
@ -47,7 +56,6 @@ namespace NewHorizons.Builder.Orbital
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
orbitLine = orbitGO.AddComponent<NHOrbitLine>();
|
orbitLine = orbitGO.AddComponent<NHOrbitLine>();
|
||||||
|
|
||||||
(orbitLine as NHOrbitLine).SetFromParameters(astroObject);
|
(orbitLine as NHOrbitLine).SetFromParameters(astroObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,8 +102,6 @@ namespace NewHorizons.Builder.Orbital
|
|||||||
orbitGO.SetActive(false);
|
orbitGO.SetActive(false);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return orbitLine;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,63 @@
|
|||||||
|
using NewHorizons.Components.Props;
|
||||||
|
using NewHorizons.External.Modules.Props;
|
||||||
|
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
|
||||||
|
using NewHorizons.Handlers;
|
||||||
|
using NewHorizons.Utility;
|
||||||
|
using NewHorizons.Utility.OWML;
|
||||||
|
using OWML.Common;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Builder.Props.EchoesOfTheEye
|
||||||
|
{
|
||||||
|
public static class DreamArrivalPointBuilder
|
||||||
|
{
|
||||||
|
private static GameObject _prefab;
|
||||||
|
|
||||||
|
internal static void InitPrefab()
|
||||||
|
{
|
||||||
|
if (_prefab == null)
|
||||||
|
{
|
||||||
|
_prefab = SearchUtilities.Find("DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_1/DreamFireHouse_1/Interactibles_DreamFireHouse_1/Prefab_IP_DreamArrivalPoint_Zone1").InstantiateInactive().Rename("Prefab_DreamArrivalPoint").DontDestroyOnLoad();
|
||||||
|
if (_prefab == null)
|
||||||
|
{
|
||||||
|
NHLogger.LogWarning($"Tried to make a dream arrival point but couldn't. Do you have the DLC installed?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_prefab.AddComponent<DestroyOnDLC>()._destroyOnDLCNotOwned = true;
|
||||||
|
var dreamArrivalPoint = _prefab.GetComponent<DreamArrivalPoint>();
|
||||||
|
dreamArrivalPoint._location = DreamArrivalPoint.Location.Undefined;
|
||||||
|
dreamArrivalPoint._sector = null;
|
||||||
|
dreamArrivalPoint._entrywayVolumes = new OWTriggerVolume[0];
|
||||||
|
dreamArrivalPoint._raftSpawn = null;
|
||||||
|
dreamArrivalPoint._connectedDreamCampfire = null;
|
||||||
|
dreamArrivalPoint._campfire._sector = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameObject Make(GameObject planetGO, Sector sector, DreamArrivalPointInfo info, IModBehaviour mod)
|
||||||
|
{
|
||||||
|
InitPrefab();
|
||||||
|
|
||||||
|
if (_prefab == null || sector == null) return null;
|
||||||
|
|
||||||
|
var arrivalPointObj = DetailBuilder.Make(planetGO, sector, mod, _prefab, new DetailInfo(info));
|
||||||
|
|
||||||
|
StreamingHandler.SetUpStreaming(arrivalPointObj, sector);
|
||||||
|
|
||||||
|
DreamArrivalPoint arrivalPoint = arrivalPointObj.GetComponent<DreamArrivalPoint>();
|
||||||
|
arrivalPoint._sector = arrivalPoint.GetComponentInParent<Sector>();
|
||||||
|
arrivalPoint._location = DreamHandler.GetDreamArrivalLocation(info.id);
|
||||||
|
Locator.RegisterDreamArrivalPoint(arrivalPoint, arrivalPoint._location);
|
||||||
|
|
||||||
|
return arrivalPointObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
using NewHorizons.External.Modules.Props;
|
||||||
|
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
|
||||||
|
using NewHorizons.Handlers;
|
||||||
|
using NewHorizons.Utility;
|
||||||
|
using NewHorizons.Utility.OWML;
|
||||||
|
using OWML.Common;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Builder.Props.EchoesOfTheEye
|
||||||
|
{
|
||||||
|
public static class DreamCampfireBuilder
|
||||||
|
{
|
||||||
|
private static GameObject _prefab;
|
||||||
|
|
||||||
|
internal static void InitPrefab()
|
||||||
|
{
|
||||||
|
if (_prefab == null)
|
||||||
|
{
|
||||||
|
_prefab = SearchUtilities.Find("RingWorld_Body/Sector_RingInterior/Sector_Zone4/Sector_PrisonDocks/Sector_PrisonInterior/Interactibles_PrisonInterior/Prefab_IP_DreamCampfire").InstantiateInactive().Rename("Prefab_DreamCampfire").DontDestroyOnLoad();
|
||||||
|
if (_prefab == null)
|
||||||
|
{
|
||||||
|
NHLogger.LogWarning($"Tried to make a dream campfire but couldn't. Do you have the DLC installed?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_prefab.AddComponent<DestroyOnDLC>()._destroyOnDLCNotOwned = true;
|
||||||
|
var campfire = _prefab.GetComponentInChildren<DreamCampfire>();
|
||||||
|
campfire._dreamArrivalLocation = DreamArrivalPoint.Location.Undefined;
|
||||||
|
campfire._sector = null;
|
||||||
|
campfire._entrywayVolumes = new OWTriggerVolume[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameObject Make(GameObject planetGO, Sector sector, DreamCampfireInfo info, IModBehaviour mod)
|
||||||
|
{
|
||||||
|
InitPrefab();
|
||||||
|
|
||||||
|
if (_prefab == null || sector == null) return null;
|
||||||
|
|
||||||
|
var campfireObj = DetailBuilder.Make(planetGO, sector, mod, _prefab, new DetailInfo(info));
|
||||||
|
|
||||||
|
var campfire = campfireObj.GetComponentInChildren<DreamCampfire>();
|
||||||
|
campfire._dreamArrivalLocation = DreamHandler.GetDreamArrivalLocation(info.id);
|
||||||
|
|
||||||
|
// The streaming groups on DreamCampfires get set on Start() so we wait until after to change it again
|
||||||
|
Delay.FireInNUpdates(() => {
|
||||||
|
var streaming = campfireObj.GetComponentInChildren<DreamCampfireStreaming>();
|
||||||
|
if (streaming != null)
|
||||||
|
{
|
||||||
|
var targetArrivalPoint = Locator.GetDreamArrivalPoint(campfire._dreamArrivalLocation);
|
||||||
|
if (targetArrivalPoint != null)
|
||||||
|
{
|
||||||
|
var streamingGroup = targetArrivalPoint.transform.root.GetComponentInChildren<StreamingGroup>();
|
||||||
|
if (streamingGroup)
|
||||||
|
{
|
||||||
|
streaming._streamingGroup = streamingGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 2);
|
||||||
|
|
||||||
|
Locator.RegisterDreamCampfire(campfire, campfire._dreamArrivalLocation);
|
||||||
|
|
||||||
|
return campfireObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using NewHorizons.Builder.Body;
|
using NewHorizons.Builder.Body;
|
||||||
using NewHorizons.Builder.Props.Audio;
|
using NewHorizons.Builder.Props.Audio;
|
||||||
|
using NewHorizons.Builder.Props.EchoesOfTheEye;
|
||||||
using NewHorizons.Builder.Props.TranslatorText;
|
using NewHorizons.Builder.Props.TranslatorText;
|
||||||
using NewHorizons.Builder.ShipLog;
|
using NewHorizons.Builder.ShipLog;
|
||||||
using NewHorizons.External;
|
using NewHorizons.External;
|
||||||
@ -101,6 +102,8 @@ namespace NewHorizons.Builder.Props
|
|||||||
// If a prop has set its parentPath and the parent cannot be found, add it to the next pass and try again later
|
// If a prop has set its parentPath and the parent cannot be found, add it to the next pass and try again later
|
||||||
nextPass = new List<Action>();
|
nextPass = new List<Action>();
|
||||||
|
|
||||||
|
if (Main.HasDLC) MakeGeneralProps(go, config.Props.dreamCampfires, (campfire) => DreamCampfireBuilder.Make(go, sector, campfire, mod), (campfire) => campfire.id);
|
||||||
|
if (Main.HasDLC) MakeGeneralProps(go, config.Props.dreamArrivalPoints, (point) => DreamArrivalPointBuilder.Make(go, sector, point, mod), (point) => point.id);
|
||||||
MakeGeneralProps(go, config.Props.gravityCannons, (cannon) => GravityCannonBuilder.Make(go, sector, cannon, mod), (cannon) => cannon.shuttleID);
|
MakeGeneralProps(go, config.Props.gravityCannons, (cannon) => GravityCannonBuilder.Make(go, sector, cannon, mod), (cannon) => cannon.shuttleID);
|
||||||
MakeGeneralProps(go, config.Props.shuttles, (shuttle) => ShuttleBuilder.Make(go, sector, mod, shuttle), (shuttle) => shuttle.id);
|
MakeGeneralProps(go, config.Props.shuttles, (shuttle) => ShuttleBuilder.Make(go, sector, mod, shuttle), (shuttle) => shuttle.id);
|
||||||
MakeGeneralProps(go, config.Props.details, (detail) => DetailBuilder.Make(go, sector, mod, detail), (detail) => detail.path);
|
MakeGeneralProps(go, config.Props.details, (detail) => DetailBuilder.Make(go, sector, mod, detail), (detail) => detail.path);
|
||||||
|
|||||||
66
NewHorizons/Components/EOTE/DreamDimension.cs
Normal file
66
NewHorizons/Components/EOTE/DreamDimension.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Components.EOTE
|
||||||
|
{
|
||||||
|
public class DreamDimension : MonoBehaviour
|
||||||
|
{
|
||||||
|
private bool initialized;
|
||||||
|
private bool active;
|
||||||
|
private List<GameObject> toggledObjects = new();
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
if (initialized) return;
|
||||||
|
|
||||||
|
foreach (Transform child in transform)
|
||||||
|
{
|
||||||
|
if (child.gameObject.name == "FieldDetector") continue;
|
||||||
|
toggledObjects.Add(child.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
UpdateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetActive(bool active)
|
||||||
|
{
|
||||||
|
if (this.active != active)
|
||||||
|
{
|
||||||
|
this.active = active;
|
||||||
|
UpdateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Awake()
|
||||||
|
{
|
||||||
|
GlobalMessenger.AddListener("EnterDreamWorld", OnEnterDreamWorld);
|
||||||
|
GlobalMessenger.AddListener("ExitDreamWorld", OnExitDreamWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
GlobalMessenger.RemoveListener("EnterDreamWorld", OnEnterDreamWorld);
|
||||||
|
GlobalMessenger.RemoveListener("ExitDreamWorld", OnExitDreamWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateState()
|
||||||
|
{
|
||||||
|
foreach (var obj in toggledObjects) obj.SetActive(active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEnterDreamWorld()
|
||||||
|
{
|
||||||
|
SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnExitDreamWorld()
|
||||||
|
{
|
||||||
|
SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
NewHorizons/Components/EOTE/LanternExtinguisher.cs
Normal file
23
NewHorizons/Components/EOTE/LanternExtinguisher.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Components.EOTE;
|
||||||
|
|
||||||
|
public class LanternExtinguisher : MonoBehaviour
|
||||||
|
{
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (PlayerState.InDreamWorld() && PlayerState.IsCameraUnderwater())
|
||||||
|
{
|
||||||
|
var heldItem = Locator.GetToolModeSwapper().GetItemCarryTool().GetHeldItem();
|
||||||
|
if (heldItem is DreamLanternItem lantern && lantern._lanternController._lit)
|
||||||
|
{
|
||||||
|
Locator.GetDreamWorldController().ExitDreamWorld(DreamWakeType.LanternSubmerged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
76
NewHorizons/Components/Props/DreamSimulationMesh.cs
Normal file
76
NewHorizons/Components/Props/DreamSimulationMesh.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
using NewHorizons.Utility.OuterWilds;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Remoting;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Components.Props
|
||||||
|
{
|
||||||
|
public class DreamSimulationMesh : MonoBehaviour
|
||||||
|
{
|
||||||
|
Transform target;
|
||||||
|
Material mat;
|
||||||
|
MeshFilter sourceMeshFilter;
|
||||||
|
MeshRenderer sourceMeshRenderer;
|
||||||
|
MeshFilter targetMeshFilter;
|
||||||
|
MeshRenderer targetMeshRenderer;
|
||||||
|
StreamingRenderMeshHandle streamingHandle;
|
||||||
|
|
||||||
|
bool initialized;
|
||||||
|
|
||||||
|
public void Init(Transform target, Material mat)
|
||||||
|
{
|
||||||
|
this.target = target;
|
||||||
|
this.mat = mat;
|
||||||
|
|
||||||
|
gameObject.layer = Layer.DreamSimulation;
|
||||||
|
|
||||||
|
sourceMeshFilter = target.GetComponent<MeshFilter>();
|
||||||
|
sourceMeshRenderer = target.GetComponent<MeshRenderer>();
|
||||||
|
targetMeshFilter = gameObject.AddComponent<MeshFilter>();
|
||||||
|
targetMeshRenderer = gameObject.AddComponent<MeshRenderer>();
|
||||||
|
|
||||||
|
transform.SetParent(target.transform, false);
|
||||||
|
|
||||||
|
streamingHandle = target.GetComponent<StreamingRenderMeshHandle>();
|
||||||
|
if (streamingHandle != null)
|
||||||
|
{
|
||||||
|
streamingHandle.OnMeshLoaded += OnMeshLoaded;
|
||||||
|
streamingHandle.OnMeshUnloaded += OnMeshUnloaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
Sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Sync()
|
||||||
|
{
|
||||||
|
if (!initialized) return;
|
||||||
|
targetMeshFilter.sharedMesh = sourceMeshFilter.sharedMesh;
|
||||||
|
targetMeshRenderer.sharedMaterials = sourceMeshRenderer.sharedMaterials.Select(_ => mat).ToArray();
|
||||||
|
targetMeshRenderer.enabled = sourceMeshRenderer.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
if (streamingHandle != null)
|
||||||
|
{
|
||||||
|
streamingHandle.OnMeshLoaded -= OnMeshLoaded;
|
||||||
|
streamingHandle.OnMeshUnloaded -= OnMeshUnloaded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnMeshLoaded()
|
||||||
|
{
|
||||||
|
Sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnMeshUnloaded()
|
||||||
|
{
|
||||||
|
Sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
NewHorizons/External/Configs/PlanetConfig.cs
vendored
8
NewHorizons/External/Configs/PlanetConfig.cs
vendored
@ -90,6 +90,11 @@ namespace NewHorizons.External.Configs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public CloakModule Cloak;
|
public CloakModule Cloak;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Make this planet part of the dream world
|
||||||
|
/// </summary>
|
||||||
|
public DreamModule Dream;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Make this body into a focal point (barycenter)
|
/// Make this body into a focal point (barycenter)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -279,6 +284,9 @@ namespace NewHorizons.External.Configs
|
|||||||
|
|
||||||
// Stars and focal points shouldnt be destroyed by stars
|
// Stars and focal points shouldnt be destroyed by stars
|
||||||
if (Star != null || FocalPoint != null) Base.hasFluidDetector = false;
|
if (Star != null || FocalPoint != null) Base.hasFluidDetector = false;
|
||||||
|
|
||||||
|
// Disable map marker for dream dimensions
|
||||||
|
if (Dream != null && Dream.inDreamWorld) MapMarker.enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Migrate()
|
public void Migrate()
|
||||||
|
|||||||
17
NewHorizons/External/Modules/DreamModule.cs
vendored
Normal file
17
NewHorizons/External/Modules/DreamModule.cs
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace NewHorizons.External.Modules
|
||||||
|
{
|
||||||
|
[JsonObject]
|
||||||
|
public class DreamModule
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Setting this value will make this body a dream world style dimension where its contents are only activated while entering it from a dream campfire. Disables the body's map marker.
|
||||||
|
/// </summary>
|
||||||
|
public bool inDreamWorld;
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to generate simulation meshes (the models used in the "tronworld" or "matrix" view) for most objects on this planet by cloning the existing meshes and applying the simulation materials. Leave this off if you are building your own simulation meshes or using existing objects which have them.
|
||||||
|
/// </summary>
|
||||||
|
public bool generateSimulationMeshes;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
NewHorizons/External/Modules/PropModule.cs
vendored
10
NewHorizons/External/Modules/PropModule.cs
vendored
@ -123,6 +123,16 @@ namespace NewHorizons.External.Modules
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ShuttleInfo[] shuttles;
|
public ShuttleInfo[] shuttles;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add campfires that allow you to enter the dream world/simulation. Must be paired with a dream arrival point, which can be placed on this planet or elsewhere.
|
||||||
|
/// </summary>
|
||||||
|
public DreamCampfireInfo[] dreamCampfires;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the points you will arrive at when entering the dream world/simulation from a paired dream campfire, which can be placed on this planet or elsewhere. The planet with the arrival point should be statically positioned to avoid issues with the simulation view materials.
|
||||||
|
/// </summary>
|
||||||
|
public DreamArrivalPointInfo[] dreamArrivalPoints;
|
||||||
|
|
||||||
[Obsolete("reveal is deprecated. Use Volumes->revealVolumes instead.")] public RevealVolumeInfo[] reveal;
|
[Obsolete("reveal is deprecated. Use Volumes->revealVolumes instead.")] public RevealVolumeInfo[] reveal;
|
||||||
|
|
||||||
[Obsolete("audioVolumes is deprecated. Use Volumes->audioVolumes instead.")] public AudioVolumeInfo[] audioVolumes;
|
[Obsolete("audioVolumes is deprecated. Use Volumes->audioVolumes instead.")] public AudioVolumeInfo[] audioVolumes;
|
||||||
|
|||||||
22
NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamArrivalPointInfo.cs
vendored
Normal file
22
NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamArrivalPointInfo.cs
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NewHorizons.External.Modules.Props.EchoesOfTheEye
|
||||||
|
{
|
||||||
|
[JsonObject]
|
||||||
|
public class DreamArrivalPointInfo : GeneralPropInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unique ID for this dream-world arrival point
|
||||||
|
/// </summary>
|
||||||
|
public string id;
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to generate simulation meshes (the models used in the "tronworld" or "matrix" view) for most objects on the current planet by cloning the existing meshes and applying the simulation materials. Leave this off if you are building your own simulation meshes or using existing objects which have them.
|
||||||
|
/// </summary>
|
||||||
|
public bool generateSimulationMeshes;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamCampfireInfo.cs
vendored
Normal file
18
NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamCampfireInfo.cs
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NewHorizons.External.Modules.Props.EchoesOfTheEye
|
||||||
|
{
|
||||||
|
[JsonObject]
|
||||||
|
public class DreamCampfireInfo : GeneralPropInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unique ID for this dream-world campfire
|
||||||
|
/// </summary>
|
||||||
|
public string id;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
NewHorizons/External/NewHorizonBody.cs
vendored
3
NewHorizons/External/NewHorizonBody.cs
vendored
@ -39,8 +39,11 @@ namespace NewHorizons.External
|
|||||||
{
|
{
|
||||||
var detailPaths = Config?.Props?.details?.Select(x => x.path) ?? Array.Empty<string>();
|
var detailPaths = Config?.Props?.details?.Select(x => x.path) ?? Array.Empty<string>();
|
||||||
return Config?.Cloak != null
|
return Config?.Cloak != null
|
||||||
|
|| Config?.Dream != null
|
||||||
|| Config?.Props?.rafts != null
|
|| Config?.Props?.rafts != null
|
||||||
|| Config?.Props?.slideShows != null
|
|| Config?.Props?.slideShows != null
|
||||||
|
|| Config?.Props?.dreamArrivalPoints != null
|
||||||
|
|| Config?.Props?.dreamCampfires != null
|
||||||
|| detailPaths.Any(x => x.StartsWith("RingWorld_Body") || x.StartsWith("DreamWorld_Body"));
|
|| detailPaths.Any(x => x.StartsWith("RingWorld_Body") || x.StartsWith("DreamWorld_Body"));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
|||||||
88
NewHorizons/Handlers/DreamHandler.cs
Normal file
88
NewHorizons/Handlers/DreamHandler.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using NewHorizons.Utility;
|
||||||
|
using NewHorizons.Utility.OWML;
|
||||||
|
using OWML.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Handlers
|
||||||
|
{
|
||||||
|
public static class DreamHandler
|
||||||
|
{
|
||||||
|
public static DreamArrivalPoint.Location GetDreamArrivalLocation(string id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (EnumUtils.TryParse(id, out DreamArrivalPoint.Location location))
|
||||||
|
{
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NHLogger.LogVerbose($"Registering new dream arrival location [{id}]");
|
||||||
|
return EnumUtilities.Create<DreamArrivalPoint.Location>(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
NHLogger.LogError($"Couldn't load dream arrival location [{id}]:\n{e}");
|
||||||
|
return DreamArrivalPoint.Location.Undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void MigrateDreamWorldController()
|
||||||
|
{
|
||||||
|
// Create new DreamWorldController instance since the existing one is disabled
|
||||||
|
var managerObj = new GameObject("DreamWorldManager");
|
||||||
|
managerObj.SetActive(false);
|
||||||
|
var oldDWC = Locator.GetDreamWorldController();
|
||||||
|
var dwc = managerObj.AddComponent<DreamWorldController>();
|
||||||
|
|
||||||
|
var simRootObj = MigrateCopy(oldDWC._primarySimulationRoot.gameObject, managerObj);
|
||||||
|
|
||||||
|
dwc._primarySimulationRoot = simRootObj.transform;
|
||||||
|
dwc._simulationRoots = new Transform[] { simRootObj.transform };
|
||||||
|
dwc._simulationCamera = simRootObj.FindChild("Camera_Simulation").GetComponent<SimulationCamera>();
|
||||||
|
dwc._simulationSphere = simRootObj.FindChild("SimulationSphere").GetComponent<OWRenderer>();
|
||||||
|
|
||||||
|
dwc._tempSkyboxColor = oldDWC._tempSkyboxColor;
|
||||||
|
dwc._sarcophagusController = oldDWC._sarcophagusController;
|
||||||
|
dwc._prisonerDirector = oldDWC._prisonerDirector;
|
||||||
|
|
||||||
|
// These should correspond to the arrival point's attached body
|
||||||
|
dwc._dreamBody = null;
|
||||||
|
dwc._dreamWorldSector = null;
|
||||||
|
dwc._dreamWorldVolume = null;
|
||||||
|
|
||||||
|
// These should correspond to the campfire's attached body
|
||||||
|
dwc._planetBody = null;
|
||||||
|
dwc._ringWorldController = null;
|
||||||
|
|
||||||
|
managerObj.SetActive(true);
|
||||||
|
|
||||||
|
// Run after Start() completes
|
||||||
|
Delay.FireOnNextUpdate(() =>
|
||||||
|
{
|
||||||
|
dwc._dreamBody = null;
|
||||||
|
dwc._dreamWorldSector = null;
|
||||||
|
dwc._dreamWorldVolume = null;
|
||||||
|
dwc._planetBody = null;
|
||||||
|
dwc._ringWorldController = null;
|
||||||
|
|
||||||
|
// Dreamworld has a giant plane for simulation water, we don't want that in our custom world
|
||||||
|
dwc._primarySimulationRoot.Find("water_simulation").gameObject.SetActive(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GameObject MigrateCopy(GameObject go, GameObject newParent)
|
||||||
|
{
|
||||||
|
var clone = GameObject.Instantiate(go);
|
||||||
|
clone.transform.SetParent(newParent.transform, false);
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
229
NewHorizons/Handlers/HeldItemHandler.cs
Normal file
229
NewHorizons/Handlers/HeldItemHandler.cs
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using NewHorizons.Builder.Props;
|
||||||
|
using NewHorizons.External.Modules.Props;
|
||||||
|
using NewHorizons.Utility;
|
||||||
|
using NewHorizons.Utility.OWML;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Handlers;
|
||||||
|
|
||||||
|
[HarmonyPatch]
|
||||||
|
public static class HeldItemHandler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Dictionary of system name to item path
|
||||||
|
/// If we travel to multiple systems within a single loop, this will hold the items we move between systems
|
||||||
|
/// </summary>
|
||||||
|
private static Dictionary<string, HashSet<string>> _pathOfItemTakenFromSystem = new();
|
||||||
|
|
||||||
|
public static bool WasAWCTakenFromATP => _pathOfItemTakenFromSystem.TryGetValue("SolarSystem", out var list) && list.Contains(ADVANCED_WARP_CORE);
|
||||||
|
|
||||||
|
private static GameObject _currentlyHeldItem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Track the path of any item we ever pick up, in case we take it out of the system
|
||||||
|
/// </summary>
|
||||||
|
private static Dictionary<GameObject, string> _trackedPaths = new();
|
||||||
|
|
||||||
|
private static bool _isInitialized = false;
|
||||||
|
private static bool _isSystemReady = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// We keep our own reference to this because when Unload gets called it might have already been updated
|
||||||
|
/// </summary>
|
||||||
|
private static string _currentStarSystem;
|
||||||
|
|
||||||
|
private const string ADVANCED_WARP_CORE = "TowerTwin_Body/Sector_TowerTwin/Sector_TimeLoopInterior/Interactables_TimeLoopInterior/WarpCoreSocket/Prefab_NOM_WarpCoreVessel";
|
||||||
|
|
||||||
|
[HarmonyPrefix, HarmonyPatch(typeof(ItemTool), nameof(ItemTool.Awake))]
|
||||||
|
private static void Init()
|
||||||
|
{
|
||||||
|
_trackedPaths.Clear();
|
||||||
|
|
||||||
|
_currentStarSystem = Main.Instance.CurrentStarSystem;
|
||||||
|
|
||||||
|
if (!_isInitialized)
|
||||||
|
{
|
||||||
|
_isInitialized = true;
|
||||||
|
Main.Instance.OnChangeStarSystem.AddListener(OnStarSystemChanging);
|
||||||
|
Main.Instance.OnStarSystemLoaded.AddListener(OnSystemReady);
|
||||||
|
GlobalMessenger<DeathType>.AddListener("PlayerDeath", OnPlayerDeath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnPlayerDeath(DeathType _)
|
||||||
|
{
|
||||||
|
NHLogger.Log("Player died, resetting held items");
|
||||||
|
|
||||||
|
// Destroy everything
|
||||||
|
_pathOfItemTakenFromSystem.Clear();
|
||||||
|
GameObject.Destroy(_currentlyHeldItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GameObject MakePerfectCopy(GameObject go)
|
||||||
|
{
|
||||||
|
var owItem = go.GetComponent<OWItem>();
|
||||||
|
|
||||||
|
var tempParent = new GameObject();
|
||||||
|
tempParent.transform.position = new Vector3(100000, 0, 0);
|
||||||
|
var newObject = DetailBuilder.Make(tempParent, tempParent.AddComponent<Sector>(), null, go, new DetailInfo() { keepLoaded = true });
|
||||||
|
newObject.SetActive(false);
|
||||||
|
newObject.transform.parent = null;
|
||||||
|
newObject.name = go.name;
|
||||||
|
|
||||||
|
var newOWItem = newObject.GetComponent<OWItem>();
|
||||||
|
|
||||||
|
NHLogger.Log($"Cloned {go.name}, original item has component: [{owItem != null}] new item has component: [{newOWItem != null}]");
|
||||||
|
|
||||||
|
return newObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TrackPath(string path)
|
||||||
|
{
|
||||||
|
if (!_pathOfItemTakenFromSystem.ContainsKey(Main.Instance.CurrentStarSystem))
|
||||||
|
{
|
||||||
|
_pathOfItemTakenFromSystem[Main.Instance.CurrentStarSystem] = new();
|
||||||
|
}
|
||||||
|
_pathOfItemTakenFromSystem[Main.Instance.CurrentStarSystem].Add(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnStarSystemChanging(string _)
|
||||||
|
{
|
||||||
|
if (_currentlyHeldItem != null)
|
||||||
|
{
|
||||||
|
// Track it so that when we return to this system we can delete the original
|
||||||
|
if (_trackedPaths.TryGetValue(_currentlyHeldItem, out var path))
|
||||||
|
{
|
||||||
|
TrackPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
NHLogger.Log($"Scene unloaded, preserved inactive held item {_currentlyHeldItem.name}");
|
||||||
|
// For some reason, the original will get destroyed no matter what we do. To avoid, we make a copy
|
||||||
|
_currentlyHeldItem = MakePerfectCopy(_currentlyHeldItem).DontDestroyOnLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If warping with a vessel, make sure to also track the path to the advanced warp core (assuming the player actually removed it)
|
||||||
|
if (Main.Instance.CurrentStarSystem == "SolarSystem" && Main.Instance.IsWarpingFromVessel)
|
||||||
|
{
|
||||||
|
// Making sure its actually gone
|
||||||
|
var warpCoreSocket = GameObject.FindObjectOfType<TimeLoopCoreController>()._warpCoreSocket;
|
||||||
|
if (!warpCoreSocket.IsSocketOccupied() || warpCoreSocket.GetWarpCoreType() != WarpCoreType.Vessel)
|
||||||
|
{
|
||||||
|
TrackPath(ADVANCED_WARP_CORE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_trackedPaths.Clear();
|
||||||
|
_isSystemReady = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnSystemReady(string _)
|
||||||
|
{
|
||||||
|
// If something was taken from this system during this life, remove it
|
||||||
|
if (_pathOfItemTakenFromSystem.TryGetValue(Main.Instance.CurrentStarSystem, out var paths))
|
||||||
|
{
|
||||||
|
foreach (var path in paths)
|
||||||
|
{
|
||||||
|
// Have to wait two frames for the sockets to Awake and Start
|
||||||
|
Delay.FireInNUpdates(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
NHLogger.Log($"Removing item that was taken from this system at {path}");
|
||||||
|
var item = SearchUtilities.Find(path)?.GetComponent<OWItem>();
|
||||||
|
// Make sure to update the socket it might be in so that it works
|
||||||
|
if (item.GetComponentInParent<OWItemSocket>() is OWItemSocket socket)
|
||||||
|
{
|
||||||
|
socket.RemoveFromSocket();
|
||||||
|
// Time loop core controller doesn't have time to hook up its events yet so we call this manually
|
||||||
|
if (path == ADVANCED_WARP_CORE)
|
||||||
|
{
|
||||||
|
var controller = GameObject.FindObjectOfType<TimeLoopCoreController>();
|
||||||
|
controller.OpenCore();
|
||||||
|
controller.OnSocketableRemoved(item);
|
||||||
|
}
|
||||||
|
NHLogger.Log($"Unsocketed {item.name}");
|
||||||
|
}
|
||||||
|
item.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
NHLogger.LogError($"Failed to remove item at {path}: {e}");
|
||||||
|
}
|
||||||
|
}, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give whatever item we were previously holding
|
||||||
|
if (_currentlyHeldItem != null)
|
||||||
|
{
|
||||||
|
NHLogger.Log($"Giving player held item {_currentlyHeldItem.name}");
|
||||||
|
// Else its spawning the item inside the player and for that one frame it kills you
|
||||||
|
var newObject = MakePerfectCopy(_currentlyHeldItem);
|
||||||
|
|
||||||
|
// We wait a bit because at some point after not something resets your held item to nothing
|
||||||
|
Delay.FireInNUpdates(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Locator.GetToolModeSwapper().GetItemCarryTool().PickUpItemInstantly(newObject.GetComponent<OWItem>());
|
||||||
|
// For some reason picking something up messes up the input mode
|
||||||
|
if (PlayerState.AtFlightConsole())
|
||||||
|
{
|
||||||
|
Locator.GetToolModeSwapper().UnequipTool();
|
||||||
|
Locator.GetToolModeSwapper().OnEnterFlightConsole(Locator.GetShipBody());
|
||||||
|
}
|
||||||
|
newObject.SetActive(true);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
NHLogger.LogError($"Failed to take item {newObject.name} to a new system: {e}");
|
||||||
|
GameObject.Destroy(_currentlyHeldItem);
|
||||||
|
_currentlyHeldItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isSystemReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix, HarmonyPatch(typeof(ItemTool), nameof(ItemTool.MoveItemToCarrySocket))]
|
||||||
|
private static void HeldItemChanged(ItemTool __instance, OWItem item)
|
||||||
|
{
|
||||||
|
if (!_isSystemReady)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
var path = item.transform.GetPath();
|
||||||
|
if (!_trackedPaths.ContainsKey(item.gameObject))
|
||||||
|
{
|
||||||
|
_trackedPaths[item.gameObject] = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NHLogger.Log($"Player is now holding {item?.name ?? "nothing"}");
|
||||||
|
_currentlyHeldItem = item?.gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix, HarmonyPatch(typeof(ItemTool))]
|
||||||
|
[HarmonyPatch(nameof(ItemTool.SocketItem))]
|
||||||
|
[HarmonyPatch(nameof(ItemTool.DropItem))]
|
||||||
|
[HarmonyPatch(nameof(ItemTool.StartUnsocketItem))]
|
||||||
|
private static void HeldItemChanged2(ItemTool __instance)
|
||||||
|
{
|
||||||
|
if (!_isSystemReady)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NHLogger.Log($"Player is now holding nothing");
|
||||||
|
_currentlyHeldItem = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
using Epic.OnlineServices;
|
||||||
using NewHorizons.Builder.Atmosphere;
|
using NewHorizons.Builder.Atmosphere;
|
||||||
using NewHorizons.Builder.Body;
|
using NewHorizons.Builder.Body;
|
||||||
using NewHorizons.Builder.General;
|
using NewHorizons.Builder.General;
|
||||||
@ -87,6 +88,7 @@ namespace NewHorizons.Handlers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load all planets
|
// Load all planets
|
||||||
|
_loadedBodies.Clear();
|
||||||
var toLoad = bodies.ToList();
|
var toLoad = bodies.ToList();
|
||||||
var newPlanetGraph = new PlanetGraphHandler(toLoad);
|
var newPlanetGraph = new PlanetGraphHandler(toLoad);
|
||||||
|
|
||||||
@ -151,8 +153,18 @@ namespace NewHorizons.Handlers
|
|||||||
SingularityBuilder.PairAllSingularities();
|
SingularityBuilder.PairAllSingularities();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<NewHorizonsBody> _loadedBodies = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns false if it failed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="body"></param>
|
||||||
|
/// <param name="defaultPrimaryToSun"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static bool LoadBody(NewHorizonsBody body, bool defaultPrimaryToSun = false)
|
public static bool LoadBody(NewHorizonsBody body, bool defaultPrimaryToSun = false)
|
||||||
{
|
{
|
||||||
|
if (_loadedBodies.Contains(body)) return true;
|
||||||
|
|
||||||
body.LoadCache();
|
body.LoadCache();
|
||||||
|
|
||||||
// I don't remember doing this why is it exceptions what am I doing
|
// I don't remember doing this why is it exceptions what am I doing
|
||||||
@ -306,6 +318,7 @@ namespace NewHorizons.Handlers
|
|||||||
}
|
}
|
||||||
|
|
||||||
body.UnloadCache(true);
|
body.UnloadCache(true);
|
||||||
|
_loadedBodies.Add(body);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,7 +519,7 @@ namespace NewHorizons.Handlers
|
|||||||
|
|
||||||
if (body.Config.Orbit.showOrbitLine && !body.Config.Orbit.isStatic)
|
if (body.Config.Orbit.showOrbitLine && !body.Config.Orbit.isStatic)
|
||||||
{
|
{
|
||||||
Delay.FireOnNextUpdate(() => OrbitlineBuilder.Make(body.Object, ao, body.Config.Orbit.isMoon, body.Config));
|
OrbitlineBuilder.Make(body.Object, body.Config.Orbit.isMoon, body.Config);
|
||||||
}
|
}
|
||||||
|
|
||||||
DetectorBuilder.Make(go, owRigidBody, primaryBody, ao, body.Config);
|
DetectorBuilder.Make(go, owRigidBody, primaryBody, ao, body.Config);
|
||||||
@ -717,6 +730,11 @@ namespace NewHorizons.Handlers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Main.HasDLC)
|
||||||
|
{
|
||||||
|
DreamDimensionBuilder.Make(go, sector, body);
|
||||||
|
}
|
||||||
|
|
||||||
// Has to go last probably
|
// Has to go last probably
|
||||||
if (willHaveCloak)
|
if (willHaveCloak)
|
||||||
{
|
{
|
||||||
@ -813,11 +831,18 @@ namespace NewHorizons.Handlers
|
|||||||
if (referenceFrame != null) referenceFrame._attachedAstroObject = newAO;
|
if (referenceFrame != null) referenceFrame._attachedAstroObject = newAO;
|
||||||
|
|
||||||
// QM and stuff don't have orbit lines
|
// QM and stuff don't have orbit lines
|
||||||
var orbitLine = go.GetComponentInChildren<OrbitLine>()?.gameObject;
|
// Using the name as well since NH only creates the OrbitLine components next frame
|
||||||
if (orbitLine != null) UnityEngine.Object.Destroy(orbitLine);
|
var orbitLine = go.GetComponentInChildren<OrbitLine>()?.gameObject ?? go.transform.Find("Orbit")?.gameObject;
|
||||||
|
if (orbitLine != null)
|
||||||
|
{
|
||||||
|
UnityEngine.Object.Destroy(orbitLine);
|
||||||
|
}
|
||||||
|
|
||||||
var isMoon = newAO.GetAstroObjectType() is AstroObject.Type.Moon or AstroObject.Type.Satellite or AstroObject.Type.SpaceStation;
|
var isMoon = newAO.GetAstroObjectType() is AstroObject.Type.Moon or AstroObject.Type.Satellite or AstroObject.Type.SpaceStation;
|
||||||
if (body.Config.Orbit.showOrbitLine) OrbitlineBuilder.Make(go, newAO, isMoon, body.Config);
|
if (body.Config.Orbit.showOrbitLine)
|
||||||
|
{
|
||||||
|
OrbitlineBuilder.Make(go, isMoon, body.Config);
|
||||||
|
}
|
||||||
|
|
||||||
DetectorBuilder.SetDetector(primary, newAO, go.GetComponentInChildren<ConstantForceDetector>());
|
DetectorBuilder.SetDetector(primary, newAO, go.GetComponentInChildren<ConstantForceDetector>());
|
||||||
|
|
||||||
|
|||||||
@ -70,6 +70,7 @@ namespace NewHorizons.Handlers
|
|||||||
if (Main.HasDLC)
|
if (Main.HasDLC)
|
||||||
{
|
{
|
||||||
StrangerRemoved();
|
StrangerRemoved();
|
||||||
|
DreamWorldRemoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put it back at the center of the universe after banishing it else there are weird graphical bugs
|
// Put it back at the center of the universe after banishing it else there are weird graphical bugs
|
||||||
@ -90,6 +91,11 @@ namespace NewHorizons.Handlers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void DreamWorldRemoved()
|
||||||
|
{
|
||||||
|
DreamHandler.MigrateDreamWorldController();
|
||||||
|
}
|
||||||
|
|
||||||
private static void SunRemoved()
|
private static void SunRemoved()
|
||||||
{
|
{
|
||||||
var sun = SearchUtilities.Find("Sun_Body").GetComponent<AstroObject>();
|
var sun = SearchUtilities.Find("Sun_Body").GetComponent<AstroObject>();
|
||||||
@ -207,6 +213,9 @@ namespace NewHorizons.Handlers
|
|||||||
case AstroObject.Name.RingWorld:
|
case AstroObject.Name.RingWorld:
|
||||||
StrangerRemoved();
|
StrangerRemoved();
|
||||||
break;
|
break;
|
||||||
|
case AstroObject.Name.DreamWorld:
|
||||||
|
DreamWorldRemoved();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always delete the children
|
// Always delete the children
|
||||||
|
|||||||
@ -51,12 +51,22 @@ namespace NewHorizons.Handlers
|
|||||||
Delay.StartCoroutine(SpawnCoroutine(30));
|
Delay.StartCoroutine(SpawnCoroutine(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
var cloak = GetDefaultSpawn()?.GetAttachedOWRigidbody()?.GetComponentInChildren<CloakFieldController>();
|
|
||||||
|
// It was NREing in here when it was all ?. so explicit null checks
|
||||||
|
var spawn = GetDefaultSpawn();
|
||||||
|
if (spawn != null)
|
||||||
|
{
|
||||||
|
var attachedOWRigidBody = spawn.GetAttachedOWRigidbody();
|
||||||
|
if (attachedOWRigidBody != null)
|
||||||
|
{
|
||||||
|
var cloak = attachedOWRigidBody.GetComponentInChildren<CloakFieldController>();
|
||||||
if (cloak != null)
|
if (cloak != null)
|
||||||
{
|
{
|
||||||
// Ensures it has invoked everything and actually placed the player in the cloaking field #671
|
// Ensures it has invoked everything and actually placed the player in the cloaking field #671
|
||||||
cloak._firstUpdate = true;
|
cloak._firstUpdate = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Spawn ship
|
// Spawn ship
|
||||||
Delay.FireInNUpdates(SpawnShip, 30);
|
Delay.FireInNUpdates(SpawnShip, 30);
|
||||||
|
|||||||
@ -4,7 +4,9 @@ using NewHorizons.Builder.Body;
|
|||||||
using NewHorizons.Builder.General;
|
using NewHorizons.Builder.General;
|
||||||
using NewHorizons.Builder.Props;
|
using NewHorizons.Builder.Props;
|
||||||
using NewHorizons.Builder.Props.Audio;
|
using NewHorizons.Builder.Props.Audio;
|
||||||
|
using NewHorizons.Builder.Props.EchoesOfTheEye;
|
||||||
using NewHorizons.Builder.Props.TranslatorText;
|
using NewHorizons.Builder.Props.TranslatorText;
|
||||||
|
using NewHorizons.Components.EOTE;
|
||||||
using NewHorizons.Components.Fixers;
|
using NewHorizons.Components.Fixers;
|
||||||
using NewHorizons.Components.Ship;
|
using NewHorizons.Components.Ship;
|
||||||
using NewHorizons.Components.SizeControllers;
|
using NewHorizons.Components.SizeControllers;
|
||||||
@ -381,6 +383,8 @@ namespace NewHorizons
|
|||||||
ProjectionBuilder.InitPrefabs();
|
ProjectionBuilder.InitPrefabs();
|
||||||
CloakBuilder.InitPrefab();
|
CloakBuilder.InitPrefab();
|
||||||
RaftBuilder.InitPrefab();
|
RaftBuilder.InitPrefab();
|
||||||
|
DreamCampfireBuilder.InitPrefab();
|
||||||
|
DreamArrivalPointBuilder.InitPrefab();
|
||||||
}
|
}
|
||||||
|
|
||||||
WarpPadBuilder.InitPrefabs();
|
WarpPadBuilder.InitPrefabs();
|
||||||
@ -619,6 +623,7 @@ namespace NewHorizons
|
|||||||
Locator.GetPlayerBody().gameObject.AddComponent<DebugPropPlacer>();
|
Locator.GetPlayerBody().gameObject.AddComponent<DebugPropPlacer>();
|
||||||
Locator.GetPlayerBody().gameObject.AddComponent<DebugMenu>();
|
Locator.GetPlayerBody().gameObject.AddComponent<DebugMenu>();
|
||||||
Locator.GetPlayerBody().gameObject.AddComponent<PlayerShipAtmosphereDetectorFix>();
|
Locator.GetPlayerBody().gameObject.AddComponent<PlayerShipAtmosphereDetectorFix>();
|
||||||
|
if (HasDLC) Locator.GetPlayerBody().gameObject.AddComponent<LanternExtinguisher>();
|
||||||
|
|
||||||
PlayerSpawnHandler.OnSystemReady(shouldWarpInFromShip, shouldWarpInFromVessel);
|
PlayerSpawnHandler.OnSystemReady(shouldWarpInFromShip, shouldWarpInFromVessel);
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
using NewHorizons.Components.EOTE;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@ -26,5 +27,60 @@ namespace NewHorizons.Patches.EchoesOfTheEyePatches
|
|||||||
.Repeat(matcher => matcher.RemoveInstructions(5))
|
.Repeat(matcher => matcher.RemoveInstructions(5))
|
||||||
.InstructionEnumeration();
|
.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(nameof(DreamWorldController.EnterDreamWorld))]
|
||||||
|
public static bool DreamWorldController_EnterDreamWorld(DreamWorldController __instance, DreamCampfire dreamCampfire, DreamArrivalPoint arrivalPoint)
|
||||||
|
{
|
||||||
|
// If we are arriving in a custom dream dimension, activate it immediately
|
||||||
|
var dimension = arrivalPoint.GetAttachedOWRigidbody().GetComponent<DreamDimension>();
|
||||||
|
if (dimension != null)
|
||||||
|
{
|
||||||
|
dimension.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the body/sector/volume where the player 'wakes up' in the dream match the body where the arrival point is located if it isn't the vanilla DreamWorld, or reset it if it is
|
||||||
|
var dreamWorldAO = Locator.GetAstroObject(AstroObject.Name.DreamWorld);
|
||||||
|
if (arrivalPoint.GetAttachedOWRigidbody() == dreamWorldAO.GetOWRigidbody())
|
||||||
|
{
|
||||||
|
__instance._dreamBody = dreamWorldAO.GetAttachedOWRigidbody();
|
||||||
|
__instance._dreamWorldSector = dreamWorldAO.GetRootSector();
|
||||||
|
__instance._dreamWorldVolume = __instance._dreamWorldSector.transform.Find("Volumes_DreamWorld").Find("DreamWorldVolume").GetComponent<OWTriggerVolume>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var arrivalAO = arrivalPoint.GetComponentInParent<AstroObject>();
|
||||||
|
__instance._dreamBody = arrivalAO.GetAttachedOWRigidbody();
|
||||||
|
__instance._dreamWorldSector = arrivalAO.GetRootSector();
|
||||||
|
__instance._dreamWorldVolume = arrivalAO._gravityVolume.GetOWTriggerVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the 'bubble' around the artifact load correctly when the destination body isn't the vanilla DreamWorld
|
||||||
|
__instance._primarySimulationRoot.GetComponent<SectorCullGroup>().SetSector(__instance._dreamWorldSector);
|
||||||
|
|
||||||
|
// if the player's already in the dream world, we want to wake up at the first campfire we slept at, so don't override those values
|
||||||
|
if (PlayerState.InDreamWorld())
|
||||||
|
{
|
||||||
|
__instance._dreamArrivalPoint = arrivalPoint;
|
||||||
|
__instance._enteringDream = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the body where the player 'wakes up' out of the dream match the body where the campfire is located if it isn't the Stranger ("RingWorld"), or reset it if it is
|
||||||
|
var ringWorldAO = Locator.GetAstroObject(AstroObject.Name.RingWorld);
|
||||||
|
if (dreamCampfire.GetAttachedOWRigidbody() == ringWorldAO.GetOWRigidbody())
|
||||||
|
{
|
||||||
|
__instance._planetBody = ringWorldAO.GetAttachedOWRigidbody();
|
||||||
|
__instance._ringWorldController = ringWorldAO.GetComponent<RingWorldController>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var departureAO = dreamCampfire.GetComponentInParent<AstroObject>();
|
||||||
|
__instance._planetBody = departureAO.GetAttachedOWRigidbody();
|
||||||
|
__instance._ringWorldController = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
using NewHorizons.Handlers;
|
||||||
|
|
||||||
namespace NewHorizons.Patches
|
namespace NewHorizons.Patches
|
||||||
{
|
{
|
||||||
@ -14,5 +15,16 @@ namespace NewHorizons.Patches
|
|||||||
[HarmonyPatch(typeof(GlobalMusicController), nameof(GlobalMusicController.UpdateEndTimesMusic))]
|
[HarmonyPatch(typeof(GlobalMusicController), nameof(GlobalMusicController.UpdateEndTimesMusic))]
|
||||||
[HarmonyPatch(typeof(TimeLoop), nameof(TimeLoop.Update))]
|
[HarmonyPatch(typeof(TimeLoop), nameof(TimeLoop.Update))]
|
||||||
public static bool DisableWithoutTimeLoop() => Main.Instance.TimeLoopEnabled;
|
public static bool DisableWithoutTimeLoop() => Main.Instance.TimeLoopEnabled;
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(TimeLoop), nameof(TimeLoop.Start))]
|
||||||
|
public static void TimeLoop_Start(TimeLoop __instance)
|
||||||
|
{
|
||||||
|
// If we took the AWC out of the main system make sure to disable time loop
|
||||||
|
if (Main.Instance.CurrentStarSystem != "SolarSystem" && HeldItemHandler.WasAWCTakenFromATP)
|
||||||
|
{
|
||||||
|
TimeLoop.SetTimeLoopEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,6 +65,10 @@
|
|||||||
"description": "Add a cloaking field to this planet",
|
"description": "Add a cloaking field to this planet",
|
||||||
"$ref": "#/definitions/CloakModule"
|
"$ref": "#/definitions/CloakModule"
|
||||||
},
|
},
|
||||||
|
"Dream": {
|
||||||
|
"description": "Make this planet part of the dream world",
|
||||||
|
"$ref": "#/definitions/DreamModule"
|
||||||
|
},
|
||||||
"FocalPoint": {
|
"FocalPoint": {
|
||||||
"description": "Make this body into a focal point (barycenter)",
|
"description": "Make this body into a focal point (barycenter)",
|
||||||
"$ref": "#/definitions/FocalPointModule"
|
"$ref": "#/definitions/FocalPointModule"
|
||||||
@ -799,6 +803,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"DreamModule": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"inDreamWorld": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Setting this value will make this body a dream world style dimension where its contents are only activated while entering it from a dream campfire. Disables the body's map marker."
|
||||||
|
},
|
||||||
|
"generateSimulationMeshes": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to generate simulation meshes (the models used in the \"tronworld\" or \"matrix\" view) for most objects on this planet by cloning the existing meshes and applying the simulation materials. Leave this off if you are building your own simulation meshes or using existing objects which have them."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"FocalPointModule": {
|
"FocalPointModule": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
@ -1294,6 +1312,20 @@
|
|||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/ShuttleInfo"
|
"$ref": "#/definitions/ShuttleInfo"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"dreamCampfires": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Add campfires that allow you to enter the dream world/simulation. Must be paired with a dream arrival point, which can be placed on this planet or elsewhere.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/DreamCampfireInfo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dreamArrivalPoints": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Add the points you will arrive at when entering the dream world/simulation from a paired dream campfire, which can be placed on this planet or elsewhere. The planet with the arrival point should be statically positioned to avoid issues with the simulation view materials.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/DreamArrivalPointInfo"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3371,6 +3403,84 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"DreamCampfireInfo": {
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"isRelativeToParent": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object."
|
||||||
|
},
|
||||||
|
"parentPath": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)."
|
||||||
|
},
|
||||||
|
"rename": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "An optional rename of this object"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Unique ID for this dream-world campfire"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DreamArrivalPointInfo": {
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"isRelativeToParent": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object."
|
||||||
|
},
|
||||||
|
"parentPath": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)."
|
||||||
|
},
|
||||||
|
"rename": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "An optional rename of this object"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Unique ID for this dream-world arrival point"
|
||||||
|
},
|
||||||
|
"generateSimulationMeshes": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to generate simulation meshes (the models used in the \"tronworld\" or \"matrix\" view) for most objects on the current planet by cloning the existing meshes and applying the simulation materials. Leave this off if you are building your own simulation meshes or using existing objects which have them."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ReferenceFrameModule": {
|
"ReferenceFrameModule": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
"author": "xen, Bwc9876, JohnCorby, MegaPiggy, Trifid, and friends",
|
"author": "xen, Bwc9876, JohnCorby, MegaPiggy, Trifid, and friends",
|
||||||
"name": "New Horizons",
|
"name": "New Horizons",
|
||||||
"uniqueName": "xen.NewHorizons",
|
"uniqueName": "xen.NewHorizons",
|
||||||
"version": "1.22.8",
|
"version": "1.23.0",
|
||||||
"owmlVersion": "2.12.1",
|
"owmlVersion": "2.12.1",
|
||||||
"dependencies": [ "JohnCorby.VanillaFix", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
|
"dependencies": [ "JohnCorby.VanillaFix", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
|
||||||
"conflicts": [ "PacificEngine.OW_CommonResources" ],
|
"conflicts": [ "PacificEngine.OW_CommonResources" ],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user