From a1d165e2b98030ee263e38f1e1da61885f5a4f40 Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sun, 13 Oct 2024 22:18:08 -0500 Subject: [PATCH] Portholes --- .../Props/EchoesOfTheEye/PortholeBuilder.cs | 90 +++++++++++++++++++ NewHorizons/Builder/Props/PropBuildManager.cs | 1 + NewHorizons/External/Modules/PropModule.cs | 5 ++ .../Props/EchoesOfTheEye/PortholeInfo.cs | 35 ++++++++ .../EchoesOfTheEyePatches/PeepholePatches.cs | 69 ++++++++++++++ 5 files changed, 200 insertions(+) create mode 100644 NewHorizons/Builder/Props/EchoesOfTheEye/PortholeBuilder.cs create mode 100644 NewHorizons/External/Modules/Props/EchoesOfTheEye/PortholeInfo.cs create mode 100644 NewHorizons/Patches/EchoesOfTheEyePatches/PeepholePatches.cs diff --git a/NewHorizons/Builder/Props/EchoesOfTheEye/PortholeBuilder.cs b/NewHorizons/Builder/Props/EchoesOfTheEye/PortholeBuilder.cs new file mode 100644 index 00000000..854dbd5f --- /dev/null +++ b/NewHorizons/Builder/Props/EchoesOfTheEye/PortholeBuilder.cs @@ -0,0 +1,90 @@ +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 PortholeBuilder + { + private static GameObject _mainPrefab; + private static GameObject _simPrefab; + + internal static void InitPrefabs() + { + if (_mainPrefab == null) + { + _mainPrefab = SearchUtilities.Find("DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_4/Interactibles_DreamZone_4_Upper/Props_IP_Peephole_Prison").InstantiateInactive().Rename("Prefab_Porthole").DontDestroyOnLoad(); + if (_mainPrefab == null) + { + NHLogger.LogWarning($"Tried to make a grapple totem but couldn't. Do you have the DLC installed?"); + return; + } + else + { + _mainPrefab.AddComponent()._destroyOnDLCNotOwned = true; + var peephole = _mainPrefab.GetComponentInChildren(); + peephole._factIDs = new string[0]; + peephole._viewingSector = null; + } + } + if (_simPrefab == null) + { + _simPrefab = SearchUtilities.Find("DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_4/Simulation_DreamZone_4/Geo_DreamZone_4_Upper/Effects_IP_SIM_Porthole").InstantiateInactive().Rename("Prefab_SIM_Porthole").DontDestroyOnLoad(); + if (_simPrefab == null) + { + NHLogger.LogWarning($"Tried to make a grapple totem but couldn't. Do you have the DLC installed?"); + return; + } + else + { + _simPrefab.AddComponent()._destroyOnDLCNotOwned = true; + } + } + } + + public static GameObject Make(GameObject planetGO, Sector sector, PortholeInfo info, IModBehaviour mod) + { + InitPrefabs(); + + if (_mainPrefab == null || _simPrefab == null || sector == null) return null; + + var portholeObj = DetailBuilder.Make(planetGO, sector, mod, _mainPrefab, new DetailInfo(info)); + + var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); + sphere.transform.SetParent(portholeObj.transform, false); + + var simObj = DetailBuilder.Make(planetGO, sector, mod, _simPrefab, new DetailInfo(info)); + simObj.transform.parent = portholeObj.transform; + + var peephole = portholeObj.GetComponentInChildren(); + if (info.revealFacts != null) + { + peephole._factIDs = info.revealFacts; + } + + peephole._peepholeCamera.farClipPlane = 4000f; + peephole._peepholeCamera.fieldOfView = info.fieldOfView; + + // Reposition the peephole camera later, after all planets are built, in case the target point is on a different astro body. + Delay.FireInNUpdates(() => + { + var cameraObj = GeneralPropBuilder.MakeFromExisting(peephole._peepholeCamera.gameObject, planetGO, sector, info.target); + cameraObj.transform.Rotate(Vector3.up, 180f, Space.Self); + cameraObj.transform.position += cameraObj.transform.up; + var viewingSector = cameraObj.GetComponentInParent(); + peephole._viewingSector = viewingSector; + }, 2); + + return portholeObj; + } + } +} diff --git a/NewHorizons/Builder/Props/PropBuildManager.cs b/NewHorizons/Builder/Props/PropBuildManager.cs index cb8be189..d171ae88 100644 --- a/NewHorizons/Builder/Props/PropBuildManager.cs +++ b/NewHorizons/Builder/Props/PropBuildManager.cs @@ -102,6 +102,7 @@ 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 nextPass = new List(); + if (Main.HasDLC) MakeGeneralProps(go, config.Props.portholes, (porthole) => PortholeBuilder.Make(go, sector, porthole, mod)); if (Main.HasDLC) MakeGeneralProps(go, config.Props.alarmTotems, (totem) => AlarmTotemBuilder.Make(go, sector, totem, mod)); if (Main.HasDLC) MakeGeneralProps(go, config.Props.grappleTotems, (totem) => GrappleTotemBuilder.Make(go, sector, totem, mod)); if (Main.HasDLC) MakeGeneralProps(go, config.Props.dreamCampfires, (campfire) => DreamCampfireBuilder.Make(go, sector, campfire, mod), (campfire) => campfire.id); diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index 539d0bed..046976d0 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -143,6 +143,11 @@ namespace NewHorizons.External.Modules /// public AlarmTotemInfo[] alarmTotems; + /// + /// Adds portholes (the windows you can peek through in the DLC) to this planet. + /// + public PortholeInfo[] portholes; + [Obsolete("reveal is deprecated. Use Volumes->revealVolumes instead.")] public RevealVolumeInfo[] reveal; [Obsolete("audioVolumes is deprecated. Use Volumes->audioVolumes instead.")] public AudioVolumeInfo[] audioVolumes; diff --git a/NewHorizons/External/Modules/Props/EchoesOfTheEye/PortholeInfo.cs b/NewHorizons/External/Modules/Props/EchoesOfTheEye/PortholeInfo.cs new file mode 100644 index 00000000..5f8659d3 --- /dev/null +++ b/NewHorizons/External/Modules/Props/EchoesOfTheEye/PortholeInfo.cs @@ -0,0 +1,35 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.External.Modules.Props.EchoesOfTheEye +{ + [JsonObject] + public class PortholeInfo : GeneralPropInfo + { + /// + /// Fact IDs to reveal when peeking through the porthole. + /// + public string[] revealFacts; + + /// + /// The field of view of the porthole camera. + /// + [DefaultValue(90f)] public float fieldOfView = 90f; + + /// + /// The location of the camera when the player peeks through the porthole. Can be placed on a different planet. + /// + public PortholeTargetInfo target; + } + + [JsonObject] + public class PortholeTargetInfo : GeneralSolarSystemPropInfo + { + + } +} diff --git a/NewHorizons/Patches/EchoesOfTheEyePatches/PeepholePatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/PeepholePatches.cs new file mode 100644 index 00000000..f0b6df44 --- /dev/null +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/PeepholePatches.cs @@ -0,0 +1,69 @@ +using HarmonyLib; +using NewHorizons.Components.EOTE; +using System.Collections.Generic; +using System.Reflection.Emit; +using UnityEngine; + +namespace NewHorizons.Patches.EchoesOfTheEyePatches +{ + [HarmonyPatch(typeof(Peephole))] + public static class PeepholePatches + { + static List _previousSectors = new List(); + + [HarmonyPrefix] + [HarmonyPatch(nameof(Peephole.SwitchToPeepholeCamera))] + public static void Peephole_SwitchToPeepholeCamera_Prefix() + { + _previousSectors.Clear(); + _previousSectors.AddRange(Locator.GetPlayerSectorDetector()._sectorList); + } + + + [HarmonyPostfix] + [HarmonyPatch(nameof(Peephole.SwitchToPeepholeCamera))] + public static void Peephole_SwitchToPeepholeCamera(Peephole __instance) + { + if (__instance._viewingSector) + { + var sector = __instance._viewingSector; + while (sector._parentSector != null) + { + sector = sector._parentSector; + + if (!_previousSectors.Contains(sector)) + { + sector.AddOccupant(Locator.GetPlayerSectorDetector()); + } + } + } + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(Peephole.SwitchToPlayerCamera))] + public static void Peephole_SwitchToPlayerCamera(Peephole __instance) + { + if (__instance._viewingSector) + { + var sector = __instance._viewingSector; + + if (_previousSectors.Contains(sector)) + { + sector.AddOccupant(Locator.GetPlayerSectorDetector()); + } + + while (sector._parentSector != null) + { + sector = sector._parentSector; + + if (!_previousSectors.Contains(sector)) + { + sector.RemoveOccupant(Locator.GetPlayerSectorDetector()); + } + } + } + + _previousSectors.Clear(); + } + } +}