-
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Showing
25 changed files
with
1,060 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
NewHorizons/Builder/Props/EchoesOfTheEye/DreamArrivalPointBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} | ||
} |
74 changes: 74 additions & 0 deletions
74
NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} | ||
} |
Oops, something went wrong.