From 22a386e50a60ecfcb73ff01d6630cd14acdd3555 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Mon, 23 May 2022 10:06:42 -0400 Subject: [PATCH 01/22] feat: added patch to make vision torches droppable, patch to allow vision torches to scan other targets besides the prisoner, added untested code to handle creating new vision torch targets --- .../Builder/Props/ProjectionBuilder.cs | 50 +++++++++++++- NewHorizons/Handlers/TitleSceneHandler.cs | 10 +-- NewHorizons/Patches/VisionTorchPatches.cs | 68 +++++++++++++++++++ 3 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 NewHorizons/Patches/VisionTorchPatches.cs diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 4e0983f1..86dc61b8 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -1,10 +1,11 @@ -using NewHorizons.External.Modules; +using NewHorizons.External.Modules; using NewHorizons.Handlers; using NewHorizons.Utility; using OWML.Common; using System; using System.Collections.Generic; using UnityEngine; +using static NewHorizons.External.Modules.PropModule; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Builder.Props { @@ -153,6 +154,47 @@ namespace NewHorizons.Builder.Props projectorObj.SetActive(true); } + + // Makes a target for a vision torch to scan + public static GameObject MakeMindSlidesTarget(GameObject planetGO, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod) + { + // spawn a trigger for the vision torch + var path = "DreamWorld_Body/Sector_DreamWorld/Sector_Underground/Sector_PrisonCell/Ghosts_PrisonCell/GhostNodeMap_PrisonCell_Lower/Prefab_IP_GhostBird_Prisoner/Ghostbird_IP_ANIM/Ghostbird_Skin_01:Ghostbird_Rig_V01:Base/Ghostbird_Skin_01:Ghostbird_Rig_V01:Root/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine03/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine04/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Head/PrisonerHeadDetector"; + var position = info.position; + GameObject g = DetailBuilder.MakeDetail(planetGO, sector, path, position, Vector3.zero, 1, false); + g.name = "VisionStaffDetector"; + + // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item + SlideInfo[] slides = info.slides; + var slidesCount = slides.Length; + var slideCollection = new SlideCollection(slidesCount); + + + for (int i = 0; i < slidesCount; i++) + { + var slide = new Slide(); + var slideInfo = slides[i]; + + var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); + slide.textureOverride = ImageUtilities.Invert(texture); + + AddModules(slideInfo, ref slide); + + slideCollection.slides[i] = slide; + } + + // attatch a component to store all the data for the slides that play when a vision torch scans this target + VisionTorchTarget target = g.AddComponent(); + SlideCollectionContainer slideCollectionContainer = g.AddComponent(); + slideCollectionContainer.slideCollection = slideCollection; + target.slideCollection = new MindSlideCollection(); + target.slideCollection._slideCollectionContainer = slideCollectionContainer; + + // Idk why but it wants reveals to be comma delimited not a list + if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); + + return g; + } private static void AddModules(PropModule.SlideInfo slideInfo, ref Slide slide) { @@ -201,5 +243,11 @@ namespace NewHorizons.Builder.Props Slide.WriteModules(modules, ref slide._modulesList, ref slide._modulesData, ref slide.lengths); } + } + + public class VisionTorchTarget : MonoBehaviour + { + public MindSlideCollection slideCollection; + public SlideCollectionContainer slideCollectionContainer; } } diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 9a28229b..f3566315 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -1,4 +1,4 @@ -using NewHorizons.Builder.Body; +using NewHorizons.Builder.Body; using NewHorizons.External.Modules; using NewHorizons.Utility; using System.Collections.Generic; @@ -15,10 +15,10 @@ namespace NewHorizons.Handlers { GameObject subtitleContainer = GameObject.Find("TitleMenu/TitleCanvas/TitleLayoutGroup/Logo_EchoesOfTheEye"); - if (subtitleContainer == null) - { - Logger.LogError("No subtitle container found! Failed to load subtitles."); - return; + if (subtitleContainer == null) + { + Logger.LogError("No subtitle container found! Failed to load subtitles."); + return; } subtitleContainer.SetActive(true); diff --git a/NewHorizons/Patches/VisionTorchPatches.cs b/NewHorizons/Patches/VisionTorchPatches.cs new file mode 100644 index 00000000..b2f97763 --- /dev/null +++ b/NewHorizons/Patches/VisionTorchPatches.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using HarmonyLib; +using NewHorizons.Builder.Props; +using UnityEngine; + +namespace NewHorizons.Patches +{ + + [HarmonyPatch] + public static class MindProjectorTriggerPatches + { + [HarmonyPrefix] + [HarmonyPatch(typeof(MindProjectorTrigger), nameof(MindProjectorTrigger.OnTriggerVolumeEntry))] + public static bool MindProjectorTrigger_OnTriggerVolumeEntry(MindProjectorTrigger __instance, GameObject hitObj) + { + Logger.Log("MIND PROJECTOR TRIGGER"); + + VisionTorchTarget t = hitObj.GetComponent(); + if (t != null) //(hitObj.CompareTag("PrisonerDetector")) + { + // _slideCollectionItem is actually a reference to a SlideCollectionContainer. Not a slide reel item + __instance._mindProjector._slideCollectionItem = t.slideCollectionContainer; + __instance._mindProjector._mindSlideCollection = t.slideCollection; + + Logger.Log("MIND PROJECTOR CUSTOM TRIGGER"); + __instance.OnBeamStartHitPrisoner.Invoke(); + __instance._mindProjector.Play(reset: true); + __instance._mindProjector.OnProjectionStart += new OWEvent.OWCallback(__instance.OnProjectionStart); + __instance._mindProjector.OnProjectionComplete += new OWEvent.OWCallback(__instance.OnProjectionComplete); + Locator.GetPlayerTransform().GetComponent().LockOn(hitObj.transform, Vector3.zero); + __instance._playerLockedOn = true; + return false; + } + + return true; + } + + // TOOD: OnTriggerVolumeExit + } + + [HarmonyPatch] + public static class VisionTorchItemPatches + { + // This is some dark magic + // this creates a method called base_DropItem that basically just calls OWItem.PickUpItem whenever it (VisionTorchItemPatches.base_PickUpItem) is called + [HarmonyReversePatch] + [HarmonyPatch(typeof(OWItem), nameof(OWItem.DropItem))] + private static void base_DropItem(OWItem instance, Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) { } + + + // Make the vision torch droppable. In the base game you can only drop it if you're in the dream world. + [HarmonyPrefix] + [HarmonyPatch(typeof(VisionTorchItem), nameof(VisionTorchItem.DropItem))] + public static bool VisionTorchItem_DropItem(VisionTorchItem __instance, Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) + { + if (!Locator.GetDreamWorldController().IsInDream()) + { + base_DropItem(__instance, position, normal, parent, sector, customDropTarget); + } + + return true; + } + } +} From 72a87c5c2edd93188afef3cb05c34df8d7015a32 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Mon, 23 May 2022 12:57:37 -0400 Subject: [PATCH 02/22] fix: fixed some missing references and a MonoBehavior that was incorrectly initialized as a regular class. also added some stuff from VisionTorchItem.Start that won't get called for custom slides since some references aren't set up at that point --- NewHorizons/Builder/Props/ProjectionBuilder.cs | 10 +++++++++- NewHorizons/Patches/VisionTorchPatches.cs | 9 ++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 86dc61b8..a6e11cc4 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -162,6 +162,13 @@ namespace NewHorizons.Builder.Props var path = "DreamWorld_Body/Sector_DreamWorld/Sector_Underground/Sector_PrisonCell/Ghosts_PrisonCell/GhostNodeMap_PrisonCell_Lower/Prefab_IP_GhostBird_Prisoner/Ghostbird_IP_ANIM/Ghostbird_Skin_01:Ghostbird_Rig_V01:Base/Ghostbird_Skin_01:Ghostbird_Rig_V01:Root/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine03/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine04/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Head/PrisonerHeadDetector"; var position = info.position; GameObject g = DetailBuilder.MakeDetail(planetGO, sector, path, position, Vector3.zero, 1, false); + + if (g == null) + { + Logger.LogWarning($"Tried to make a vision torch target but couldn't. Do you have the DLC installed?"); + return null; + } + g.name = "VisionStaffDetector"; // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item @@ -187,8 +194,9 @@ namespace NewHorizons.Builder.Props VisionTorchTarget target = g.AddComponent(); SlideCollectionContainer slideCollectionContainer = g.AddComponent(); slideCollectionContainer.slideCollection = slideCollection; - target.slideCollection = new MindSlideCollection(); + target.slideCollection = g.AddComponent(); target.slideCollection._slideCollectionContainer = slideCollectionContainer; + target.slideCollectionContainer = slideCollectionContainer; // Idk why but it wants reveals to be comma delimited not a list if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); diff --git a/NewHorizons/Patches/VisionTorchPatches.cs b/NewHorizons/Patches/VisionTorchPatches.cs index b2f97763..acb8f61c 100644 --- a/NewHorizons/Patches/VisionTorchPatches.cs +++ b/NewHorizons/Patches/VisionTorchPatches.cs @@ -17,8 +17,6 @@ namespace NewHorizons.Patches [HarmonyPatch(typeof(MindProjectorTrigger), nameof(MindProjectorTrigger.OnTriggerVolumeEntry))] public static bool MindProjectorTrigger_OnTriggerVolumeEntry(MindProjectorTrigger __instance, GameObject hitObj) { - Logger.Log("MIND PROJECTOR TRIGGER"); - VisionTorchTarget t = hitObj.GetComponent(); if (t != null) //(hitObj.CompareTag("PrisonerDetector")) { @@ -26,11 +24,16 @@ namespace NewHorizons.Patches __instance._mindProjector._slideCollectionItem = t.slideCollectionContainer; __instance._mindProjector._mindSlideCollection = t.slideCollection; - Logger.Log("MIND PROJECTOR CUSTOM TRIGGER"); + Main.Instance.ModHelper.Console.WriteLine("MIND PROJECTOR CUSTOM TRIGGER"); __instance.OnBeamStartHitPrisoner.Invoke(); __instance._mindProjector.Play(reset: true); __instance._mindProjector.OnProjectionStart += new OWEvent.OWCallback(__instance.OnProjectionStart); __instance._mindProjector.OnProjectionComplete += new OWEvent.OWCallback(__instance.OnProjectionComplete); + + __instance._mindProjector._slideCollectionItem.onSlideTextureUpdated += new OWEvent.OWCallback(__instance._mindProjector.OnSlideTextureUpdated); + __instance._mindProjector._slideCollectionItem.onPlayBeatAudio += new OWEvent.OWCallback(__instance._mindProjector.OnPlayBeatAudio); + __instance._mindProjector._slideCollectionItem.Initialize(); + Locator.GetPlayerTransform().GetComponent().LockOn(hitObj.transform, Vector3.zero); __instance._playerLockedOn = true; return false; From f1ed8be741646db5c69840b4338571ac7fc5bfcd Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Tue, 24 May 2022 07:28:57 -0400 Subject: [PATCH 03/22] vision torches now work, as long as you're not wearing your suit --- NewHorizons/Builder/Props/ProjectionBuilder.cs | 1 + NewHorizons/Patches/VisionTorchPatches.cs | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index a6e11cc4..fe01b388 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -182,6 +182,7 @@ namespace NewHorizons.Builder.Props var slide = new Slide(); var slideInfo = slides[i]; + // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); slide.textureOverride = ImageUtilities.Invert(texture); diff --git a/NewHorizons/Patches/VisionTorchPatches.cs b/NewHorizons/Patches/VisionTorchPatches.cs index acb8f61c..82d8fbf2 100644 --- a/NewHorizons/Patches/VisionTorchPatches.cs +++ b/NewHorizons/Patches/VisionTorchPatches.cs @@ -23,6 +23,7 @@ namespace NewHorizons.Patches // _slideCollectionItem is actually a reference to a SlideCollectionContainer. Not a slide reel item __instance._mindProjector._slideCollectionItem = t.slideCollectionContainer; __instance._mindProjector._mindSlideCollection = t.slideCollection; + __instance._mindProjector.SetMindSlideCollection(t.slideCollection); Main.Instance.ModHelper.Console.WriteLine("MIND PROJECTOR CUSTOM TRIGGER"); __instance.OnBeamStartHitPrisoner.Invoke(); @@ -30,10 +31,10 @@ namespace NewHorizons.Patches __instance._mindProjector.OnProjectionStart += new OWEvent.OWCallback(__instance.OnProjectionStart); __instance._mindProjector.OnProjectionComplete += new OWEvent.OWCallback(__instance.OnProjectionComplete); - __instance._mindProjector._slideCollectionItem.onSlideTextureUpdated += new OWEvent.OWCallback(__instance._mindProjector.OnSlideTextureUpdated); - __instance._mindProjector._slideCollectionItem.onPlayBeatAudio += new OWEvent.OWCallback(__instance._mindProjector.OnPlayBeatAudio); - __instance._mindProjector._slideCollectionItem.Initialize(); - + // __instance._mindProjector._slideCollectionItem.onSlideTextureUpdated += new OWEvent.OWCallback(__instance._mindProjector.OnSlideTextureUpdated); + //__instance._mindProjector._slideCollectionItem.onPlayBeatAudio += new OWEvent.OWCallback(__instance._mindProjector.OnPlayBeatAudio); + //__instance._mindProjector._slideCollectionItem.Initialize(); + Locator.GetPlayerTransform().GetComponent().LockOn(hitObj.transform, Vector3.zero); __instance._playerLockedOn = true; return false; From 2af257a35fea2f01fce4b83c705f13ef9253bebb Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Tue, 24 May 2022 11:34:17 -0400 Subject: [PATCH 04/22] added patches required to block item swapping while holding a vision torch. this is the last change required to get vision torches baseline functional --- .../Builder/Props/ProjectionBuilder.cs | 2 +- NewHorizons/Patches/ToolModeSwapperPatches.cs | 36 +++++++++++++++++++ NewHorizons/Patches/VisionTorchPatches.cs | 3 ++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 NewHorizons/Patches/ToolModeSwapperPatches.cs diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index fe01b388..d0f7f67d 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -184,7 +184,7 @@ namespace NewHorizons.Builder.Props // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); - slide.textureOverride = ImageUtilities.Invert(texture); + slide.textureOverride = texture; //ImageUtilities.Invert(texture); AddModules(slideInfo, ref slide); diff --git a/NewHorizons/Patches/ToolModeSwapperPatches.cs b/NewHorizons/Patches/ToolModeSwapperPatches.cs new file mode 100644 index 00000000..dc102864 --- /dev/null +++ b/NewHorizons/Patches/ToolModeSwapperPatches.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using HarmonyLib; + +namespace NewHorizons.Patches +{ + [HarmonyPatch] + public static class ToolModeSwapperPatches + { + + // Patches ToolModeSwapper.EquipToolMode(ToolMode mode) to deny swaps if you're holding a vision torch. + // This is critical for preventing swapping to the scout launcher (causes memory slides to fail) but it + // just doesn't look right when you switch to other stuff (eg the signalscope), so I'm disabling swapping tools entirely + + // the correct way to do this is to patch ToolModeSwapper.Update to be exactly the same as it is now, but change the below line + // to include a check for "is holding vision torch", but I'm not copy/pasting an entire function, no sir + // if (((_currentToolMode == ToolMode.None || _currentToolMode == ToolMode.Item) && Locator.GetPlayerSuit().IsWearingSuit(includeTrainingSuit: false)) || ((_currentToolMode == ToolMode.None || _currentToolMode == ToolMode.SignalScope) && OWInput.IsInputMode(InputMode.ShipCockpit))) + [HarmonyPrefix] + [HarmonyPatch(typeof(ToolModeSwapper), nameof(ToolModeSwapper.EquipToolMode))] + public static bool ToolModeSwapper_EquipToolMode(ToolModeSwapper __instance, ToolMode mode) + { + bool isHoldingVisionTorch = __instance.GetItemCarryTool()?.GetHeldItemType() == ItemType.VisionTorch; + bool swappingToRestrictedTool = + mode == ToolMode.Probe || + mode == ToolMode.SignalScope || + mode == ToolMode.Translator; + + if (isHoldingVisionTorch && swappingToRestrictedTool) return false; + + return true; + } + } +} diff --git a/NewHorizons/Patches/VisionTorchPatches.cs b/NewHorizons/Patches/VisionTorchPatches.cs index 82d8fbf2..c51e6afe 100644 --- a/NewHorizons/Patches/VisionTorchPatches.cs +++ b/NewHorizons/Patches/VisionTorchPatches.cs @@ -68,5 +68,8 @@ namespace NewHorizons.Patches return true; } + + // ProbeLauncher.Disable()? + // public override void PickUpItem(Transform holdTranform) } } From 667e68f7ace40ee4a31ac288537c008f6e0136c4 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Tue, 24 May 2022 12:25:34 -0400 Subject: [PATCH 05/22] added standing vision torches (the kind that just sit in the environment and you walk into their projection beam) --- NewHorizons/Builder/Props/DetailBuilder.cs | 26 +++++++++- .../Builder/Props/ProjectionBuilder.cs | 52 +++++++++++++++++-- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index 68247a08..b505aba2 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -1,4 +1,4 @@ -using NewHorizons.External.Configs; +using NewHorizons.External.Configs; using NewHorizons.External.Modules; using NewHorizons.Handlers; using NewHorizons.Utility; @@ -12,6 +12,7 @@ namespace NewHorizons.Builder.Props { public static class DetailBuilder { + private static readonly string VISION_TORCH_PATH = "DreamWorld_Body/Sector_DreamWorld/Sector_Underground/Sector_PrisonCell/Interactibles_PrisonCell/PrisonerSequence/VisionTorchWallSocket/Prefab_IP_VisionTorchItem"; private static Dictionary detailInfoToCorrespondingSpawnedGameObject = new Dictionary(); public static GameObject GetSpawnedGameObjectByDetailInfo(PropModule.DetailInfo detail) @@ -81,6 +82,8 @@ namespace NewHorizons.Builder.Props public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) { + if (propToClone == VISION_TORCH_PATH) return MakeVisionTorch(go, sector, position, rotation, scale, 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); @@ -219,5 +222,26 @@ namespace NewHorizons.Builder.Props return prop; } + + public static GameObject MakeVisionTorch(GameObject planetGO, Sector sector, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) + { + if (!Main.HasDLC) + { + Logger.LogError("Could not instantiate Prefab_IP_VisionTorchItem, user does not own the DLC."); + return null; + } + + var prefab = SearchUtilities.Find(VISION_TORCH_PATH); + if (prefab == null) Logger.LogError($"Couldn't find detail Prefab_IP_VisionTorchItem"); + + GameObject Prefab_IP_VisionTorchItem = MakeDetail(planetGO, sector, prefab, position, rotation, scale, alignWithNormal); + + Prefab_IP_VisionTorchItem.GetComponent().enabled = true; + Prefab_IP_VisionTorchItem.GetComponent().mindProjectorTrigger.enabled = true; + + Prefab_IP_VisionTorchItem.GetComponent().mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); + + return Prefab_IP_VisionTorchItem; + } } } diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index d0f7f67d..07a7f531 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -18,7 +18,9 @@ namespace NewHorizons.Builder.Props public static void Make(GameObject go, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod) { if (info.type == "autoProjector") MakeAutoProjector(go, sector, info, mod); - else if (info.type == "slideReel") MakeSlideReel(go, sector, info, mod); + else if (info.type == "slideReel") MakeSlideReel(go, sector, info, mod); + else if (info.type == "playerVisionTorchTarget") MakeMindSlidesTarget(go, sector, info, mod); + else if (info.type == "standingVisionTorch") MakeStandingVisionTorch(go, sector, info, mod); else Logger.LogError($"Invalid projection type {info.type}"); } @@ -160,8 +162,7 @@ namespace NewHorizons.Builder.Props { // spawn a trigger for the vision torch var path = "DreamWorld_Body/Sector_DreamWorld/Sector_Underground/Sector_PrisonCell/Ghosts_PrisonCell/GhostNodeMap_PrisonCell_Lower/Prefab_IP_GhostBird_Prisoner/Ghostbird_IP_ANIM/Ghostbird_Skin_01:Ghostbird_Rig_V01:Base/Ghostbird_Skin_01:Ghostbird_Rig_V01:Root/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine03/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine04/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Head/PrisonerHeadDetector"; - var position = info.position; - GameObject g = DetailBuilder.MakeDetail(planetGO, sector, path, position, Vector3.zero, 1, false); + GameObject g = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, Vector3.zero, 1, false); if (g == null) { @@ -204,6 +205,51 @@ namespace NewHorizons.Builder.Props return g; } + + public static GameObject MakeStandingVisionTorch(GameObject planetGO, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod) + { + // spawn the torch itself + var path = "RingWorld_Body/Sector_RingWorld/Sector_SecretEntrance/Interactibles_SecretEntrance/Experiment_1/VisionTorchApparatus/VisionTorchRoot/Prefab_IP_VisionTorchProjector"; + GameObject standingTorch = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, info.rotation, 1, false); + + if (standingTorch == null) + { + Logger.LogWarning($"Tried to make a vision torch target but couldn't. Do you have the DLC installed?"); + return null; + } + + // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item + SlideInfo[] slides = info.slides; + var slidesCount = slides.Length; + var slideCollection = new SlideCollection(slidesCount); + + + for (int i = 0; i < slidesCount; i++) + { + var slide = new Slide(); + var slideInfo = slides[i]; + + // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days + var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); + slide.textureOverride = texture; //ImageUtilities.Invert(texture); + + AddModules(slideInfo, ref slide); + + slideCollection.slides[i] = slide; + } + + // attatch a component to store all the data for the slides that play when a vision torch scans this target + SlideCollectionContainer slideCollectionContainer = standingTorch.AddComponent(); + slideCollectionContainer.slideCollection = slideCollection; + MindSlideCollection mindlideCollection = standingTorch.AddComponent(); + mindlideCollection._slideCollectionContainer = slideCollectionContainer; + slideCollectionContainer = slideCollectionContainer; + + // Idk why but it wants reveals to be comma delimited not a list + if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); + + return standingTorch; + } private static void AddModules(PropModule.SlideInfo slideInfo, ref Slide slide) { From 8118b1756198f7b4dda3d9986de2235755bb273f Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Tue, 24 May 2022 12:28:53 -0400 Subject: [PATCH 06/22] added comments to the props module --- NewHorizons/External/Modules/PropModule.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index a70f4634..ad5098ae 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -1,4 +1,4 @@ -using NewHorizons.Utility; +using NewHorizons.Utility; using System.ComponentModel; namespace NewHorizons.External.Modules @@ -142,7 +142,10 @@ namespace NewHorizons.External.Modules public MVector3 position; public MVector3 rotation; public string[] reveals; - public SlideInfo[] slides; + public SlideInfo[] slides; + + // enum values for this property: "autoProjector", "slideReel", "playerVisionTorchTarget", "standingVisionTorch" + // I don't know why the default value is capital 'S' SlideReel. it should be lower case as far as I can tell. public string type = "SlideReel"; } From b1688c0a6d63e1ef2be632c353ac6dbee2de3a47 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Tue, 24 May 2022 18:16:12 -0400 Subject: [PATCH 07/22] added more necessary stuff to standing vision torches, made vision staff targets bigger so they're easier to hit --- .../Builder/Props/ProjectionBuilder.cs | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 07a7f531..cbfa8ba5 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -162,7 +162,7 @@ namespace NewHorizons.Builder.Props { // spawn a trigger for the vision torch var path = "DreamWorld_Body/Sector_DreamWorld/Sector_Underground/Sector_PrisonCell/Ghosts_PrisonCell/GhostNodeMap_PrisonCell_Lower/Prefab_IP_GhostBird_Prisoner/Ghostbird_IP_ANIM/Ghostbird_Skin_01:Ghostbird_Rig_V01:Base/Ghostbird_Skin_01:Ghostbird_Rig_V01:Root/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine03/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine04/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Head/PrisonerHeadDetector"; - GameObject g = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, Vector3.zero, 1, false); + GameObject g = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, Vector3.zero, 2, false); if (g == null) { @@ -208,7 +208,10 @@ namespace NewHorizons.Builder.Props public static GameObject MakeStandingVisionTorch(GameObject planetGO, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod) { + // // spawn the torch itself + // + var path = "RingWorld_Body/Sector_RingWorld/Sector_SecretEntrance/Interactibles_SecretEntrance/Experiment_1/VisionTorchApparatus/VisionTorchRoot/Prefab_IP_VisionTorchProjector"; GameObject standingTorch = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, info.rotation, 1, false); @@ -218,12 +221,22 @@ namespace NewHorizons.Builder.Props return null; } + // + // set some required properties on the torch + // + + MindSlideProjector mindSlideProjector = standingTorch.GetComponent(); + mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); + + // + // set up slides + // + // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item SlideInfo[] slides = info.slides; var slidesCount = slides.Length; var slideCollection = new SlideCollection(slidesCount); - for (int i = 0; i < slidesCount; i++) { var slide = new Slide(); @@ -238,12 +251,19 @@ namespace NewHorizons.Builder.Props slideCollection.slides[i] = slide; } - // attatch a component to store all the data for the slides that play when a vision torch scans this target + // set up the containers for the slides SlideCollectionContainer slideCollectionContainer = standingTorch.AddComponent(); slideCollectionContainer.slideCollection = slideCollection; - MindSlideCollection mindlideCollection = standingTorch.AddComponent(); - mindlideCollection._slideCollectionContainer = slideCollectionContainer; - slideCollectionContainer = slideCollectionContainer; + MindSlideCollection mindSlideCollection = standingTorch.AddComponent(); + mindSlideCollection._slideCollectionContainer = slideCollectionContainer; + + // make sure that these slides play when the player wanders into the beam + // _slideCollectionItem is actually a reference to a SlideCollectionContainer. Not a slide reel item + standingTorch.GetComponent()._mindSlideCollection = mindSlideCollection; + mindSlideProjector._slideCollectionItem = slideCollectionContainer; + mindSlideProjector._mindSlideCollection = mindSlideCollection; + mindSlideProjector.SetMindSlideCollection(mindSlideCollection); + // Idk why but it wants reveals to be comma delimited not a list if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); From 41c8e17f49dd652bd6e5407c730b28595aac7fa2 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 07:26:50 -0400 Subject: [PATCH 08/22] removed separate CreateVisionTorch function and folded it into the regular Make function --- NewHorizons/Builder/Props/DetailBuilder.cs | 478 ++++++++++----------- 1 file changed, 231 insertions(+), 247 deletions(-) diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index b505aba2..7b687fe0 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -1,247 +1,231 @@ -using NewHorizons.External.Configs; -using NewHorizons.External.Modules; -using NewHorizons.Handlers; -using NewHorizons.Utility; -using OWML.Common; -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using Logger = NewHorizons.Utility.Logger; -namespace NewHorizons.Builder.Props -{ - public static class DetailBuilder - { - private static readonly string VISION_TORCH_PATH = "DreamWorld_Body/Sector_DreamWorld/Sector_Underground/Sector_PrisonCell/Interactibles_PrisonCell/PrisonerSequence/VisionTorchWallSocket/Prefab_IP_VisionTorchItem"; - private static Dictionary detailInfoToCorrespondingSpawnedGameObject = new Dictionary(); - - public static GameObject GetSpawnedGameObjectByDetailInfo(PropModule.DetailInfo detail) - { - if (!detailInfoToCorrespondingSpawnedGameObject.ContainsKey(detail)) return null; - return detailInfoToCorrespondingSpawnedGameObject[detail]; - } - - public static void Make(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, string uniqueModName, PropModule.DetailInfo detail) - { - GameObject detailGO = null; - - if (detail.assetBundle != null) - { - var prefab = AssetBundleUtilities.LoadPrefab(detail.assetBundle, detail.path, mod); - - detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal); - } - else if (detail.objFilePath != null) - { - try - { - var prefab = mod.ModHelper.Assets.Get3DObject(detail.objFilePath, detail.mtlFilePath); - AssetBundleUtilities.ReplaceShaders(prefab); - prefab.SetActive(false); - 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 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 = detailGO.transform.Find(childPath); - if (childObj != null) childObj.gameObject.SetActive(false); - else Logger.LogWarning($"Couldn't find {childPath}"); - } - } - - if (detailGO != null && detail.removeComponents) - { - // Just swap all the children to a new game object - var newDetailGO = new GameObject(detailGO.name); - newDetailGO.transform.position = detailGO.transform.position; - newDetailGO.transform.parent = detailGO.transform.parent; - // Can't modify parents while looping through children bc idk - var children = new List(); - foreach (Transform child in detailGO.transform) - { - children.Add(child); - } - foreach (var child in children) - { - child.parent = newDetailGO.transform; - } - GameObject.Destroy(detailGO); - detailGO = newDetailGO; - } - - detailInfoToCorrespondingSpawnedGameObject[detail] = detailGO; - } - - public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) - { - if (propToClone == VISION_TORCH_PATH) return MakeVisionTorch(go, sector, position, rotation, scale, 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); - } - - public static GameObject MakeDetail(GameObject planetGO, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) - { - if (prefab == null) return null; - - GameObject prop = prefab.InstantiateInactive(); - prop.transform.parent = sector?.transform ?? planetGO.transform; - prop.SetActive(false); - - if (sector != null) sector.OnOccupantEnterSector += (SectorDetector sd) => OWAssetHandler.OnOccupantEnterSector(prop, sd, sector); - OWAssetHandler.LoadObject(prop); - - foreach (var component in prop.GetComponents().Concat(prop.GetComponentsInChildren())) - { - // Enable all children or something - var enabledField = component?.GetType()?.GetField("enabled"); - if (enabledField != null && enabledField.FieldType == typeof(bool)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => enabledField.SetValue(component, true)); - - // Fix a bunch of sector stuff - if (sector != null) - { - if (component is Sector) - { - (component as Sector)._parentSector = sector; - } - - // TODO: Make this work or smthng - if (component is GhostIK) (component as GhostIK).enabled = false; - if (component is GhostEffects) (component as GhostEffects).enabled = false; - - if (component is DarkMatterVolume) - { - var probeVisuals = component.gameObject.transform.Find("ProbeVisuals"); - if (probeVisuals != null) probeVisuals.gameObject.SetActive(true); - } - - if (component is SectoredMonoBehaviour) - { - (component as SectoredMonoBehaviour).SetSector(sector); - } - else - { - var sectorField = component?.GetType()?.GetField("_sector"); - if (sectorField != null && sectorField.FieldType == typeof(Sector)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => sectorField.SetValue(component, sector)); - } - - if (component is AnglerfishController) - { - try - { - (component as AnglerfishController)._chaseSpeed += OWPhysics.CalculateOrbitVelocity(planetGO.GetAttachedOWRigidbody(), planetGO.GetComponent().GetPrimaryBody().GetAttachedOWRigidbody()).magnitude; - } - catch (Exception e) - { - Logger.LogError($"Couldn't update AnglerFish chase speed: {e.Message}"); - } - } - - // Fix slide reel - if (component is SlideCollectionContainer) - { - sector.OnOccupantEnterSector.AddListener((_) => (component as SlideCollectionContainer).LoadStreamingTextures()); - } - - if (component is OWItemSocket) - { - (component as OWItemSocket)._sector = sector; - } - } - else - { - // Remove things that require sectors. Will just keep extending this as things pop up - - if (component is FogLight || component is SectoredMonoBehaviour) - { - GameObject.DestroyImmediate(component); - continue; - } - } - - // Fix a bunch of stuff when done loading - Main.Instance.ModHelper.Events.Unity.RunWhen(() => Main.IsSystemReady, () => - { - try - { - if (component is Animator) (component as Animator).enabled = true; - else if (component is Collider) (component as Collider).enabled = true; - else if (component is Renderer) (component as Renderer).enabled = true; - else if (component is Shape) (component as Shape).enabled = true; - // If it's not a moving anglerfish make sure the anim controller is regular - else if (component is AnglerfishAnimController && component.GetComponentInParent() == null) - { - Logger.Log("Enabling anglerfish animation"); - var angler = (component as AnglerfishAnimController); - // Remove any reference to its angler - if (angler._anglerfishController) - { - angler._anglerfishController.OnChangeAnglerState -= angler.OnChangeAnglerState; - angler._anglerfishController.OnAnglerTurn -= angler.OnAnglerTurn; - angler._anglerfishController.OnAnglerSuspended -= angler.OnAnglerSuspended; - angler._anglerfishController.OnAnglerUnsuspended -= angler.OnAnglerUnsuspended; - } - angler.enabled = true; - angler.OnChangeAnglerState(AnglerfishController.AnglerState.Lurking); - } - } - catch (Exception e) - { - Logger.LogWarning($"Exception when modifying component [{component.GetType().Name}] on [{planetGO.name}] : {e.Message}, {e.StackTrace}"); - } - }); - } - - prop.transform.position = position == null ? planetGO.transform.position : planetGO.transform.TransformPoint((Vector3)position); - - Quaternion rot = rotation == null ? Quaternion.identity : Quaternion.Euler((Vector3)rotation); - if (alignWithNormal) - { - // Apply the rotation after aligning it with normal - var up = planetGO.transform.InverseTransformPoint(prop.transform.position).normalized; - prop.transform.rotation = Quaternion.FromToRotation(Vector3.up, up); - prop.transform.rotation *= rot; - } - else - { - prop.transform.rotation = planetGO.transform.TransformRotation(rot); - } - - prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale; - - prop.SetActive(true); - - return prop; - } - - public static GameObject MakeVisionTorch(GameObject planetGO, Sector sector, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) - { - if (!Main.HasDLC) - { - Logger.LogError("Could not instantiate Prefab_IP_VisionTorchItem, user does not own the DLC."); - return null; - } - - var prefab = SearchUtilities.Find(VISION_TORCH_PATH); - if (prefab == null) Logger.LogError($"Couldn't find detail Prefab_IP_VisionTorchItem"); - - GameObject Prefab_IP_VisionTorchItem = MakeDetail(planetGO, sector, prefab, position, rotation, scale, alignWithNormal); - - Prefab_IP_VisionTorchItem.GetComponent().enabled = true; - Prefab_IP_VisionTorchItem.GetComponent().mindProjectorTrigger.enabled = true; - - Prefab_IP_VisionTorchItem.GetComponent().mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); - - return Prefab_IP_VisionTorchItem; - } - } -} +using NewHorizons.External.Configs; +using NewHorizons.External.Modules; +using NewHorizons.Handlers; +using NewHorizons.Utility; +using OWML.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; +namespace NewHorizons.Builder.Props +{ + public static class DetailBuilder + { + private static Dictionary detailInfoToCorrespondingSpawnedGameObject = new Dictionary(); + + public static GameObject GetSpawnedGameObjectByDetailInfo(PropModule.DetailInfo detail) + { + if (!detailInfoToCorrespondingSpawnedGameObject.ContainsKey(detail)) return null; + return detailInfoToCorrespondingSpawnedGameObject[detail]; + } + + public static void Make(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, string uniqueModName, PropModule.DetailInfo detail) + { + GameObject detailGO = null; + + if (detail.assetBundle != null) + { + var prefab = AssetBundleUtilities.LoadPrefab(detail.assetBundle, detail.path, mod); + + detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal); + } + else if (detail.objFilePath != null) + { + try + { + var prefab = mod.ModHelper.Assets.Get3DObject(detail.objFilePath, detail.mtlFilePath); + AssetBundleUtilities.ReplaceShaders(prefab); + prefab.SetActive(false); + 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 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 = detailGO.transform.Find(childPath); + if (childObj != null) childObj.gameObject.SetActive(false); + else Logger.LogWarning($"Couldn't find {childPath}"); + } + } + + if (detailGO != null && detail.removeComponents) + { + // Just swap all the children to a new game object + var newDetailGO = new GameObject(detailGO.name); + newDetailGO.transform.position = detailGO.transform.position; + newDetailGO.transform.parent = detailGO.transform.parent; + // Can't modify parents while looping through children bc idk + var children = new List(); + foreach (Transform child in detailGO.transform) + { + children.Add(child); + } + foreach (var child in children) + { + child.parent = newDetailGO.transform; + } + GameObject.Destroy(detailGO); + detailGO = newDetailGO; + } + + detailInfoToCorrespondingSpawnedGameObject[detail] = detailGO; + } + + 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); + } + + public static GameObject MakeDetail(GameObject planetGO, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) + { + if (prefab == null) return null; + + GameObject prop = prefab.InstantiateInactive(); + prop.transform.parent = sector?.transform ?? planetGO.transform; + prop.SetActive(false); + + if (sector != null) sector.OnOccupantEnterSector += (SectorDetector sd) => OWAssetHandler.OnOccupantEnterSector(prop, sd, sector); + OWAssetHandler.LoadObject(prop); + + foreach (var component in prop.GetComponents().Concat(prop.GetComponentsInChildren())) + { + // Enable all children or something + var enabledField = component?.GetType()?.GetField("enabled"); + if (enabledField != null && enabledField.FieldType == typeof(bool)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => enabledField.SetValue(component, true)); + + // Fix a bunch of sector stuff + if (sector != null) + { + if (component is Sector) + { + (component as Sector)._parentSector = sector; + } + + // TODO: Make this work or smthng + if (component is GhostIK) (component as GhostIK).enabled = false; + if (component is GhostEffects) (component as GhostEffects).enabled = false; + + if (component is DarkMatterVolume) + { + var probeVisuals = component.gameObject.transform.Find("ProbeVisuals"); + if (probeVisuals != null) probeVisuals.gameObject.SetActive(true); + } + + if (component is SectoredMonoBehaviour) + { + (component as SectoredMonoBehaviour).SetSector(sector); + } + else + { + var sectorField = component?.GetType()?.GetField("_sector"); + if (sectorField != null && sectorField.FieldType == typeof(Sector)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => sectorField.SetValue(component, sector)); + } + + if (component is AnglerfishController) + { + try + { + (component as AnglerfishController)._chaseSpeed += OWPhysics.CalculateOrbitVelocity(planetGO.GetAttachedOWRigidbody(), planetGO.GetComponent().GetPrimaryBody().GetAttachedOWRigidbody()).magnitude; + } + catch (Exception e) + { + Logger.LogError($"Couldn't update AnglerFish chase speed: {e.Message}"); + } + } + + // Fix slide reel + if (component is SlideCollectionContainer) + { + sector.OnOccupantEnterSector.AddListener((_) => (component as SlideCollectionContainer).LoadStreamingTextures()); + } + + if (component is OWItemSocket) + { + (component as OWItemSocket)._sector = sector; + } + + // Fix vision torch + if (component is VisionTorchItem) + { + (component as VisionTorchItem).enabled = true; + (component as VisionTorchItem).mindProjectorTrigger.enabled = true; + (component as VisionTorchItem).mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); + } + } + else + { + // Remove things that require sectors. Will just keep extending this as things pop up + + if (component is FogLight || component is SectoredMonoBehaviour) + { + GameObject.DestroyImmediate(component); + continue; + } + } + + // Fix a bunch of stuff when done loading + Main.Instance.ModHelper.Events.Unity.RunWhen(() => Main.IsSystemReady, () => + { + try + { + if (component is Animator) (component as Animator).enabled = true; + else if (component is Collider) (component as Collider).enabled = true; + else if (component is Renderer) (component as Renderer).enabled = true; + else if (component is Shape) (component as Shape).enabled = true; + // If it's not a moving anglerfish make sure the anim controller is regular + else if (component is AnglerfishAnimController && component.GetComponentInParent() == null) + { + Logger.Log("Enabling anglerfish animation"); + var angler = (component as AnglerfishAnimController); + // Remove any reference to its angler + if (angler._anglerfishController) + { + angler._anglerfishController.OnChangeAnglerState -= angler.OnChangeAnglerState; + angler._anglerfishController.OnAnglerTurn -= angler.OnAnglerTurn; + angler._anglerfishController.OnAnglerSuspended -= angler.OnAnglerSuspended; + angler._anglerfishController.OnAnglerUnsuspended -= angler.OnAnglerUnsuspended; + } + angler.enabled = true; + angler.OnChangeAnglerState(AnglerfishController.AnglerState.Lurking); + } + } + catch (Exception e) + { + Logger.LogWarning($"Exception when modifying component [{component.GetType().Name}] on [{planetGO.name}] : {e.Message}, {e.StackTrace}"); + } + }); + } + + prop.transform.position = position == null ? planetGO.transform.position : planetGO.transform.TransformPoint((Vector3)position); + + Quaternion rot = rotation == null ? Quaternion.identity : Quaternion.Euler((Vector3)rotation); + if (alignWithNormal) + { + // Apply the rotation after aligning it with normal + var up = planetGO.transform.InverseTransformPoint(prop.transform.position).normalized; + prop.transform.rotation = Quaternion.FromToRotation(Vector3.up, up); + prop.transform.rotation *= rot; + } + else + { + prop.transform.rotation = planetGO.transform.TransformRotation(rot); + } + + prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale; + + prop.SetActive(true); + + return prop; + } + } +} From c1b2a2fc8cdd09b2e71f93931336ee83ab78980c Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 07:27:07 -0400 Subject: [PATCH 09/22] fixed line endings, stupid visual studio --- .../Builder/Props/ProjectionBuilder.cs | 230 +++++++++--------- NewHorizons/Patches/ToolModeSwapperPatches.cs | 72 +++--- NewHorizons/Patches/VisionTorchPatches.cs | 150 ++++++------ 3 files changed, 226 insertions(+), 226 deletions(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index cbfa8ba5..259835bf 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -5,7 +5,7 @@ using OWML.Common; using System; using System.Collections.Generic; using UnityEngine; -using static NewHorizons.External.Modules.PropModule; +using static NewHorizons.External.Modules.PropModule; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Builder.Props { @@ -18,8 +18,8 @@ namespace NewHorizons.Builder.Props public static void Make(GameObject go, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod) { if (info.type == "autoProjector") MakeAutoProjector(go, sector, info, mod); - else if (info.type == "slideReel") MakeSlideReel(go, sector, info, mod); - else if (info.type == "playerVisionTorchTarget") MakeMindSlidesTarget(go, sector, info, mod); + else if (info.type == "slideReel") MakeSlideReel(go, sector, info, mod); + else if (info.type == "playerVisionTorchTarget") MakeMindSlidesTarget(go, sector, info, mod); else if (info.type == "standingVisionTorch") MakeStandingVisionTorch(go, sector, info, mod); else Logger.LogError($"Invalid projection type {info.type}"); } @@ -156,120 +156,120 @@ namespace NewHorizons.Builder.Props projectorObj.SetActive(true); } - - // Makes a target for a vision torch to scan - public static GameObject MakeMindSlidesTarget(GameObject planetGO, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod) - { - // spawn a trigger for the vision torch - var path = "DreamWorld_Body/Sector_DreamWorld/Sector_Underground/Sector_PrisonCell/Ghosts_PrisonCell/GhostNodeMap_PrisonCell_Lower/Prefab_IP_GhostBird_Prisoner/Ghostbird_IP_ANIM/Ghostbird_Skin_01:Ghostbird_Rig_V01:Base/Ghostbird_Skin_01:Ghostbird_Rig_V01:Root/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine03/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine04/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Head/PrisonerHeadDetector"; - GameObject g = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, Vector3.zero, 2, false); - + + // Makes a target for a vision torch to scan + public static GameObject MakeMindSlidesTarget(GameObject planetGO, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod) + { + // spawn a trigger for the vision torch + var path = "DreamWorld_Body/Sector_DreamWorld/Sector_Underground/Sector_PrisonCell/Ghosts_PrisonCell/GhostNodeMap_PrisonCell_Lower/Prefab_IP_GhostBird_Prisoner/Ghostbird_IP_ANIM/Ghostbird_Skin_01:Ghostbird_Rig_V01:Base/Ghostbird_Skin_01:Ghostbird_Rig_V01:Root/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine03/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine04/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Head/PrisonerHeadDetector"; + GameObject g = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, Vector3.zero, 2, false); + if (g == null) { Logger.LogWarning($"Tried to make a vision torch target but couldn't. Do you have the DLC installed?"); return null; - } - - g.name = "VisionStaffDetector"; - - // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item - SlideInfo[] slides = info.slides; - var slidesCount = slides.Length; - var slideCollection = new SlideCollection(slidesCount); - - - for (int i = 0; i < slidesCount; i++) - { - var slide = new Slide(); - var slideInfo = slides[i]; - - // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days - var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); - slide.textureOverride = texture; //ImageUtilities.Invert(texture); - - AddModules(slideInfo, ref slide); - - slideCollection.slides[i] = slide; - } - - // attatch a component to store all the data for the slides that play when a vision torch scans this target - VisionTorchTarget target = g.AddComponent(); - SlideCollectionContainer slideCollectionContainer = g.AddComponent(); - slideCollectionContainer.slideCollection = slideCollection; - target.slideCollection = g.AddComponent(); - target.slideCollection._slideCollectionContainer = slideCollectionContainer; - target.slideCollectionContainer = slideCollectionContainer; - - // Idk why but it wants reveals to be comma delimited not a list - if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); - - return g; - } - - public static GameObject MakeStandingVisionTorch(GameObject planetGO, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod) - { - // - // spawn the torch itself - // - - var path = "RingWorld_Body/Sector_RingWorld/Sector_SecretEntrance/Interactibles_SecretEntrance/Experiment_1/VisionTorchApparatus/VisionTorchRoot/Prefab_IP_VisionTorchProjector"; - GameObject standingTorch = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, info.rotation, 1, false); - + } + + g.name = "VisionStaffDetector"; + + // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item + SlideInfo[] slides = info.slides; + var slidesCount = slides.Length; + var slideCollection = new SlideCollection(slidesCount); + + + for (int i = 0; i < slidesCount; i++) + { + var slide = new Slide(); + var slideInfo = slides[i]; + + // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days + var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); + slide.textureOverride = texture; //ImageUtilities.Invert(texture); + + AddModules(slideInfo, ref slide); + + slideCollection.slides[i] = slide; + } + + // attatch a component to store all the data for the slides that play when a vision torch scans this target + VisionTorchTarget target = g.AddComponent(); + SlideCollectionContainer slideCollectionContainer = g.AddComponent(); + slideCollectionContainer.slideCollection = slideCollection; + target.slideCollection = g.AddComponent(); + target.slideCollection._slideCollectionContainer = slideCollectionContainer; + target.slideCollectionContainer = slideCollectionContainer; + + // Idk why but it wants reveals to be comma delimited not a list + if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); + + return g; + } + + public static GameObject MakeStandingVisionTorch(GameObject planetGO, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod) + { + // + // spawn the torch itself + // + + var path = "RingWorld_Body/Sector_RingWorld/Sector_SecretEntrance/Interactibles_SecretEntrance/Experiment_1/VisionTorchApparatus/VisionTorchRoot/Prefab_IP_VisionTorchProjector"; + GameObject standingTorch = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, info.rotation, 1, false); + if (standingTorch == null) { Logger.LogWarning($"Tried to make a vision torch target but couldn't. Do you have the DLC installed?"); return null; - } - - // - // set some required properties on the torch - // - - MindSlideProjector mindSlideProjector = standingTorch.GetComponent(); - mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); - - // - // set up slides - // - - // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item - SlideInfo[] slides = info.slides; - var slidesCount = slides.Length; - var slideCollection = new SlideCollection(slidesCount); - - for (int i = 0; i < slidesCount; i++) - { - var slide = new Slide(); - var slideInfo = slides[i]; - - // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days - var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); - slide.textureOverride = texture; //ImageUtilities.Invert(texture); - - AddModules(slideInfo, ref slide); - - slideCollection.slides[i] = slide; - } - - // set up the containers for the slides - SlideCollectionContainer slideCollectionContainer = standingTorch.AddComponent(); - slideCollectionContainer.slideCollection = slideCollection; - MindSlideCollection mindSlideCollection = standingTorch.AddComponent(); - mindSlideCollection._slideCollectionContainer = slideCollectionContainer; - - // make sure that these slides play when the player wanders into the beam - // _slideCollectionItem is actually a reference to a SlideCollectionContainer. Not a slide reel item - standingTorch.GetComponent()._mindSlideCollection = mindSlideCollection; - mindSlideProjector._slideCollectionItem = slideCollectionContainer; - mindSlideProjector._mindSlideCollection = mindSlideCollection; - mindSlideProjector.SetMindSlideCollection(mindSlideCollection); - - - // Idk why but it wants reveals to be comma delimited not a list - if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); - - return standingTorch; - } + } + + // + // set some required properties on the torch + // + + MindSlideProjector mindSlideProjector = standingTorch.GetComponent(); + mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); + + // + // set up slides + // + + // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item + SlideInfo[] slides = info.slides; + var slidesCount = slides.Length; + var slideCollection = new SlideCollection(slidesCount); + + for (int i = 0; i < slidesCount; i++) + { + var slide = new Slide(); + var slideInfo = slides[i]; + + // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days + var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); + slide.textureOverride = texture; //ImageUtilities.Invert(texture); + + AddModules(slideInfo, ref slide); + + slideCollection.slides[i] = slide; + } + + // set up the containers for the slides + SlideCollectionContainer slideCollectionContainer = standingTorch.AddComponent(); + slideCollectionContainer.slideCollection = slideCollection; + MindSlideCollection mindSlideCollection = standingTorch.AddComponent(); + mindSlideCollection._slideCollectionContainer = slideCollectionContainer; + + // make sure that these slides play when the player wanders into the beam + // _slideCollectionItem is actually a reference to a SlideCollectionContainer. Not a slide reel item + standingTorch.GetComponent()._mindSlideCollection = mindSlideCollection; + mindSlideProjector._slideCollectionItem = slideCollectionContainer; + mindSlideProjector._mindSlideCollection = mindSlideCollection; + mindSlideProjector.SetMindSlideCollection(mindSlideCollection); + + + // Idk why but it wants reveals to be comma delimited not a list + if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); + + return standingTorch; + } private static void AddModules(PropModule.SlideInfo slideInfo, ref Slide slide) { @@ -318,11 +318,11 @@ namespace NewHorizons.Builder.Props Slide.WriteModules(modules, ref slide._modulesList, ref slide._modulesData, ref slide.lengths); } - } - - public class VisionTorchTarget : MonoBehaviour - { - public MindSlideCollection slideCollection; - public SlideCollectionContainer slideCollectionContainer; + } + + public class VisionTorchTarget : MonoBehaviour + { + public MindSlideCollection slideCollection; + public SlideCollectionContainer slideCollectionContainer; } } diff --git a/NewHorizons/Patches/ToolModeSwapperPatches.cs b/NewHorizons/Patches/ToolModeSwapperPatches.cs index dc102864..90639421 100644 --- a/NewHorizons/Patches/ToolModeSwapperPatches.cs +++ b/NewHorizons/Patches/ToolModeSwapperPatches.cs @@ -1,36 +1,36 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using HarmonyLib; - -namespace NewHorizons.Patches -{ - [HarmonyPatch] - public static class ToolModeSwapperPatches - { - - // Patches ToolModeSwapper.EquipToolMode(ToolMode mode) to deny swaps if you're holding a vision torch. - // This is critical for preventing swapping to the scout launcher (causes memory slides to fail) but it - // just doesn't look right when you switch to other stuff (eg the signalscope), so I'm disabling swapping tools entirely - - // the correct way to do this is to patch ToolModeSwapper.Update to be exactly the same as it is now, but change the below line - // to include a check for "is holding vision torch", but I'm not copy/pasting an entire function, no sir - // if (((_currentToolMode == ToolMode.None || _currentToolMode == ToolMode.Item) && Locator.GetPlayerSuit().IsWearingSuit(includeTrainingSuit: false)) || ((_currentToolMode == ToolMode.None || _currentToolMode == ToolMode.SignalScope) && OWInput.IsInputMode(InputMode.ShipCockpit))) - [HarmonyPrefix] - [HarmonyPatch(typeof(ToolModeSwapper), nameof(ToolModeSwapper.EquipToolMode))] - public static bool ToolModeSwapper_EquipToolMode(ToolModeSwapper __instance, ToolMode mode) - { - bool isHoldingVisionTorch = __instance.GetItemCarryTool()?.GetHeldItemType() == ItemType.VisionTorch; - bool swappingToRestrictedTool = - mode == ToolMode.Probe || - mode == ToolMode.SignalScope || - mode == ToolMode.Translator; - - if (isHoldingVisionTorch && swappingToRestrictedTool) return false; - - return true; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using HarmonyLib; + +namespace NewHorizons.Patches +{ + [HarmonyPatch] + public static class ToolModeSwapperPatches + { + + // Patches ToolModeSwapper.EquipToolMode(ToolMode mode) to deny swaps if you're holding a vision torch. + // This is critical for preventing swapping to the scout launcher (causes memory slides to fail) but it + // just doesn't look right when you switch to other stuff (eg the signalscope), so I'm disabling swapping tools entirely + + // the correct way to do this is to patch ToolModeSwapper.Update to be exactly the same as it is now, but change the below line + // to include a check for "is holding vision torch", but I'm not copy/pasting an entire function, no sir + // if (((_currentToolMode == ToolMode.None || _currentToolMode == ToolMode.Item) && Locator.GetPlayerSuit().IsWearingSuit(includeTrainingSuit: false)) || ((_currentToolMode == ToolMode.None || _currentToolMode == ToolMode.SignalScope) && OWInput.IsInputMode(InputMode.ShipCockpit))) + [HarmonyPrefix] + [HarmonyPatch(typeof(ToolModeSwapper), nameof(ToolModeSwapper.EquipToolMode))] + public static bool ToolModeSwapper_EquipToolMode(ToolModeSwapper __instance, ToolMode mode) + { + bool isHoldingVisionTorch = __instance.GetItemCarryTool()?.GetHeldItemType() == ItemType.VisionTorch; + bool swappingToRestrictedTool = + mode == ToolMode.Probe || + mode == ToolMode.SignalScope || + mode == ToolMode.Translator; + + if (isHoldingVisionTorch && swappingToRestrictedTool) return false; + + return true; + } + } +} diff --git a/NewHorizons/Patches/VisionTorchPatches.cs b/NewHorizons/Patches/VisionTorchPatches.cs index c51e6afe..c715c44f 100644 --- a/NewHorizons/Patches/VisionTorchPatches.cs +++ b/NewHorizons/Patches/VisionTorchPatches.cs @@ -1,75 +1,75 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using HarmonyLib; -using NewHorizons.Builder.Props; -using UnityEngine; - -namespace NewHorizons.Patches -{ - - [HarmonyPatch] - public static class MindProjectorTriggerPatches - { - [HarmonyPrefix] - [HarmonyPatch(typeof(MindProjectorTrigger), nameof(MindProjectorTrigger.OnTriggerVolumeEntry))] - public static bool MindProjectorTrigger_OnTriggerVolumeEntry(MindProjectorTrigger __instance, GameObject hitObj) - { - VisionTorchTarget t = hitObj.GetComponent(); - if (t != null) //(hitObj.CompareTag("PrisonerDetector")) - { - // _slideCollectionItem is actually a reference to a SlideCollectionContainer. Not a slide reel item - __instance._mindProjector._slideCollectionItem = t.slideCollectionContainer; - __instance._mindProjector._mindSlideCollection = t.slideCollection; - __instance._mindProjector.SetMindSlideCollection(t.slideCollection); - - Main.Instance.ModHelper.Console.WriteLine("MIND PROJECTOR CUSTOM TRIGGER"); - __instance.OnBeamStartHitPrisoner.Invoke(); - __instance._mindProjector.Play(reset: true); - __instance._mindProjector.OnProjectionStart += new OWEvent.OWCallback(__instance.OnProjectionStart); - __instance._mindProjector.OnProjectionComplete += new OWEvent.OWCallback(__instance.OnProjectionComplete); - - // __instance._mindProjector._slideCollectionItem.onSlideTextureUpdated += new OWEvent.OWCallback(__instance._mindProjector.OnSlideTextureUpdated); - //__instance._mindProjector._slideCollectionItem.onPlayBeatAudio += new OWEvent.OWCallback(__instance._mindProjector.OnPlayBeatAudio); - //__instance._mindProjector._slideCollectionItem.Initialize(); - - Locator.GetPlayerTransform().GetComponent().LockOn(hitObj.transform, Vector3.zero); - __instance._playerLockedOn = true; - return false; - } - - return true; - } - - // TOOD: OnTriggerVolumeExit - } - - [HarmonyPatch] - public static class VisionTorchItemPatches - { - // This is some dark magic - // this creates a method called base_DropItem that basically just calls OWItem.PickUpItem whenever it (VisionTorchItemPatches.base_PickUpItem) is called - [HarmonyReversePatch] - [HarmonyPatch(typeof(OWItem), nameof(OWItem.DropItem))] - private static void base_DropItem(OWItem instance, Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) { } - - - // Make the vision torch droppable. In the base game you can only drop it if you're in the dream world. - [HarmonyPrefix] - [HarmonyPatch(typeof(VisionTorchItem), nameof(VisionTorchItem.DropItem))] - public static bool VisionTorchItem_DropItem(VisionTorchItem __instance, Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) - { - if (!Locator.GetDreamWorldController().IsInDream()) - { - base_DropItem(__instance, position, normal, parent, sector, customDropTarget); - } - - return true; - } - - // ProbeLauncher.Disable()? - // public override void PickUpItem(Transform holdTranform) - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using HarmonyLib; +using NewHorizons.Builder.Props; +using UnityEngine; + +namespace NewHorizons.Patches +{ + + [HarmonyPatch] + public static class MindProjectorTriggerPatches + { + [HarmonyPrefix] + [HarmonyPatch(typeof(MindProjectorTrigger), nameof(MindProjectorTrigger.OnTriggerVolumeEntry))] + public static bool MindProjectorTrigger_OnTriggerVolumeEntry(MindProjectorTrigger __instance, GameObject hitObj) + { + VisionTorchTarget t = hitObj.GetComponent(); + if (t != null) //(hitObj.CompareTag("PrisonerDetector")) + { + // _slideCollectionItem is actually a reference to a SlideCollectionContainer. Not a slide reel item + __instance._mindProjector._slideCollectionItem = t.slideCollectionContainer; + __instance._mindProjector._mindSlideCollection = t.slideCollection; + __instance._mindProjector.SetMindSlideCollection(t.slideCollection); + + Main.Instance.ModHelper.Console.WriteLine("MIND PROJECTOR CUSTOM TRIGGER"); + __instance.OnBeamStartHitPrisoner.Invoke(); + __instance._mindProjector.Play(reset: true); + __instance._mindProjector.OnProjectionStart += new OWEvent.OWCallback(__instance.OnProjectionStart); + __instance._mindProjector.OnProjectionComplete += new OWEvent.OWCallback(__instance.OnProjectionComplete); + + // __instance._mindProjector._slideCollectionItem.onSlideTextureUpdated += new OWEvent.OWCallback(__instance._mindProjector.OnSlideTextureUpdated); + //__instance._mindProjector._slideCollectionItem.onPlayBeatAudio += new OWEvent.OWCallback(__instance._mindProjector.OnPlayBeatAudio); + //__instance._mindProjector._slideCollectionItem.Initialize(); + + Locator.GetPlayerTransform().GetComponent().LockOn(hitObj.transform, Vector3.zero); + __instance._playerLockedOn = true; + return false; + } + + return true; + } + + // TOOD: OnTriggerVolumeExit + } + + [HarmonyPatch] + public static class VisionTorchItemPatches + { + // This is some dark magic + // this creates a method called base_DropItem that basically just calls OWItem.PickUpItem whenever it (VisionTorchItemPatches.base_PickUpItem) is called + [HarmonyReversePatch] + [HarmonyPatch(typeof(OWItem), nameof(OWItem.DropItem))] + private static void base_DropItem(OWItem instance, Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) { } + + + // Make the vision torch droppable. In the base game you can only drop it if you're in the dream world. + [HarmonyPrefix] + [HarmonyPatch(typeof(VisionTorchItem), nameof(VisionTorchItem.DropItem))] + public static bool VisionTorchItem_DropItem(VisionTorchItem __instance, Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) + { + if (!Locator.GetDreamWorldController().IsInDream()) + { + base_DropItem(__instance, position, normal, parent, sector, customDropTarget); + } + + return true; + } + + // ProbeLauncher.Disable()? + // public override void PickUpItem(Transform holdTranform) + } +} From d0a66a97572814db6c08e2566983098c082e691e Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 07:29:14 -0400 Subject: [PATCH 10/22] removed unneeded comments --- NewHorizons/Patches/VisionTorchPatches.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/NewHorizons/Patches/VisionTorchPatches.cs b/NewHorizons/Patches/VisionTorchPatches.cs index c715c44f..cc34f615 100644 --- a/NewHorizons/Patches/VisionTorchPatches.cs +++ b/NewHorizons/Patches/VisionTorchPatches.cs @@ -25,15 +25,10 @@ namespace NewHorizons.Patches __instance._mindProjector._mindSlideCollection = t.slideCollection; __instance._mindProjector.SetMindSlideCollection(t.slideCollection); - Main.Instance.ModHelper.Console.WriteLine("MIND PROJECTOR CUSTOM TRIGGER"); __instance.OnBeamStartHitPrisoner.Invoke(); __instance._mindProjector.Play(reset: true); __instance._mindProjector.OnProjectionStart += new OWEvent.OWCallback(__instance.OnProjectionStart); __instance._mindProjector.OnProjectionComplete += new OWEvent.OWCallback(__instance.OnProjectionComplete); - - // __instance._mindProjector._slideCollectionItem.onSlideTextureUpdated += new OWEvent.OWCallback(__instance._mindProjector.OnSlideTextureUpdated); - //__instance._mindProjector._slideCollectionItem.onPlayBeatAudio += new OWEvent.OWCallback(__instance._mindProjector.OnPlayBeatAudio); - //__instance._mindProjector._slideCollectionItem.Initialize(); Locator.GetPlayerTransform().GetComponent().LockOn(hitObj.transform, Vector3.zero); __instance._playerLockedOn = true; @@ -42,8 +37,6 @@ namespace NewHorizons.Patches return true; } - - // TOOD: OnTriggerVolumeExit } [HarmonyPatch] @@ -68,8 +61,5 @@ namespace NewHorizons.Patches return true; } - - // ProbeLauncher.Disable()? - // public override void PickUpItem(Transform holdTranform) } } From e34a5170958b6bcefd1fbfca344dd5d41123b13a Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 07:32:48 -0400 Subject: [PATCH 11/22] switched to using var for all declarations --- NewHorizons/Patches/ToolModeSwapperPatches.cs | 4 ++-- NewHorizons/Patches/VisionTorchPatches.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NewHorizons/Patches/ToolModeSwapperPatches.cs b/NewHorizons/Patches/ToolModeSwapperPatches.cs index 90639421..987ae1dc 100644 --- a/NewHorizons/Patches/ToolModeSwapperPatches.cs +++ b/NewHorizons/Patches/ToolModeSwapperPatches.cs @@ -22,8 +22,8 @@ namespace NewHorizons.Patches [HarmonyPatch(typeof(ToolModeSwapper), nameof(ToolModeSwapper.EquipToolMode))] public static bool ToolModeSwapper_EquipToolMode(ToolModeSwapper __instance, ToolMode mode) { - bool isHoldingVisionTorch = __instance.GetItemCarryTool()?.GetHeldItemType() == ItemType.VisionTorch; - bool swappingToRestrictedTool = + var isHoldingVisionTorch = __instance.GetItemCarryTool()?.GetHeldItemType() == ItemType.VisionTorch; + var swappingToRestrictedTool = mode == ToolMode.Probe || mode == ToolMode.SignalScope || mode == ToolMode.Translator; diff --git a/NewHorizons/Patches/VisionTorchPatches.cs b/NewHorizons/Patches/VisionTorchPatches.cs index cc34f615..e6df091c 100644 --- a/NewHorizons/Patches/VisionTorchPatches.cs +++ b/NewHorizons/Patches/VisionTorchPatches.cs @@ -17,7 +17,7 @@ namespace NewHorizons.Patches [HarmonyPatch(typeof(MindProjectorTrigger), nameof(MindProjectorTrigger.OnTriggerVolumeEntry))] public static bool MindProjectorTrigger_OnTriggerVolumeEntry(MindProjectorTrigger __instance, GameObject hitObj) { - VisionTorchTarget t = hitObj.GetComponent(); + var t = hitObj.GetComponent(); if (t != null) //(hitObj.CompareTag("PrisonerDetector")) { // _slideCollectionItem is actually a reference to a SlideCollectionContainer. Not a slide reel item From 714deaea0556b300f56422c4e6e42fef1aa392bc Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 07:34:20 -0400 Subject: [PATCH 12/22] switched to using var for all declarations --- NewHorizons/Builder/Props/ProjectionBuilder.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 259835bf..7745ee0e 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -162,7 +162,7 @@ namespace NewHorizons.Builder.Props { // spawn a trigger for the vision torch var path = "DreamWorld_Body/Sector_DreamWorld/Sector_Underground/Sector_PrisonCell/Ghosts_PrisonCell/GhostNodeMap_PrisonCell_Lower/Prefab_IP_GhostBird_Prisoner/Ghostbird_IP_ANIM/Ghostbird_Skin_01:Ghostbird_Rig_V01:Base/Ghostbird_Skin_01:Ghostbird_Rig_V01:Root/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine03/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine04/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Head/PrisonerHeadDetector"; - GameObject g = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, Vector3.zero, 2, false); + var g = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, Vector3.zero, 2, false); if (g == null) { @@ -173,7 +173,7 @@ namespace NewHorizons.Builder.Props g.name = "VisionStaffDetector"; // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item - SlideInfo[] slides = info.slides; + var slides = info.slides; var slidesCount = slides.Length; var slideCollection = new SlideCollection(slidesCount); @@ -193,8 +193,8 @@ namespace NewHorizons.Builder.Props } // attatch a component to store all the data for the slides that play when a vision torch scans this target - VisionTorchTarget target = g.AddComponent(); - SlideCollectionContainer slideCollectionContainer = g.AddComponent(); + var target = g.AddComponent(); + var slideCollectionContainer = g.AddComponent(); slideCollectionContainer.slideCollection = slideCollection; target.slideCollection = g.AddComponent(); target.slideCollection._slideCollectionContainer = slideCollectionContainer; @@ -213,7 +213,7 @@ namespace NewHorizons.Builder.Props // var path = "RingWorld_Body/Sector_RingWorld/Sector_SecretEntrance/Interactibles_SecretEntrance/Experiment_1/VisionTorchApparatus/VisionTorchRoot/Prefab_IP_VisionTorchProjector"; - GameObject standingTorch = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, info.rotation, 1, false); + var standingTorch = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, info.rotation, 1, false); if (standingTorch == null) { @@ -225,7 +225,7 @@ namespace NewHorizons.Builder.Props // set some required properties on the torch // - MindSlideProjector mindSlideProjector = standingTorch.GetComponent(); + var mindSlideProjector = standingTorch.GetComponent(); mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); // @@ -233,7 +233,7 @@ namespace NewHorizons.Builder.Props // // The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item - SlideInfo[] slides = info.slides; + var slides = info.slides; var slidesCount = slides.Length; var slideCollection = new SlideCollection(slidesCount); @@ -252,9 +252,9 @@ namespace NewHorizons.Builder.Props } // set up the containers for the slides - SlideCollectionContainer slideCollectionContainer = standingTorch.AddComponent(); + var slideCollectionContainer = standingTorch.AddComponent(); slideCollectionContainer.slideCollection = slideCollection; - MindSlideCollection mindSlideCollection = standingTorch.AddComponent(); + var mindSlideCollection = standingTorch.AddComponent(); mindSlideCollection._slideCollectionContainer = slideCollectionContainer; // make sure that these slides play when the player wanders into the beam From ff8dfa21ad1dc5984df23a4d118f2ebaf9d4dc7a Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 10:40:44 -0400 Subject: [PATCH 13/22] added async texture loading to standing vision torches and vision torch targets --- .../Builder/Props/ProjectionBuilder.cs | 23 ++++++---- NewHorizons/Utility/ImageUtilities.cs | 44 +++++++++++++++++++ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 7745ee0e..b1228f90 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -177,20 +177,24 @@ namespace NewHorizons.Builder.Props var slidesCount = slides.Length; var slideCollection = new SlideCollection(slidesCount); - + + var imageLoader = g.AddComponent(); for (int i = 0; i < slidesCount; i++) { var slide = new Slide(); var slideInfo = slides[i]; // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days - var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); - slide.textureOverride = texture; //ImageUtilities.Invert(texture); + //var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); + //slide.textureOverride = texture; //ImageUtilities.Invert(texture); + imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath); AddModules(slideInfo, ref slide); slideCollection.slides[i] = slide; - } + } + imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index].textureOverride = tex; }); + // attatch a component to store all the data for the slides that play when a vision torch scans this target var target = g.AddComponent(); @@ -236,20 +240,23 @@ namespace NewHorizons.Builder.Props var slides = info.slides; var slidesCount = slides.Length; var slideCollection = new SlideCollection(slidesCount); - + + var imageLoader = standingTorch.AddComponent(); for (int i = 0; i < slidesCount; i++) { var slide = new Slide(); var slideInfo = slides[i]; // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days - var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); - slide.textureOverride = texture; //ImageUtilities.Invert(texture); + //var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); + //slide.textureOverride = texture; //ImageUtilities.Invert(texture); + imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath); AddModules(slideInfo, ref slide); slideCollection.slides[i] = slide; - } + } + imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index].textureOverride = tex; }); // set up the containers for the slides var slideCollectionContainer = standingTorch.AddComponent(); diff --git a/NewHorizons/Utility/ImageUtilities.cs b/NewHorizons/Utility/ImageUtilities.cs index 3a89b7ba..4de79971 100644 --- a/NewHorizons/Utility/ImageUtilities.cs +++ b/NewHorizons/Utility/ImageUtilities.cs @@ -1,8 +1,12 @@ using OWML.Common; using System; +using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + namespace NewHorizons.Utility { public static class ImageUtilities @@ -313,5 +317,45 @@ namespace NewHorizons.Utility newTexture.Apply(); return newTexture; } + } + + // Modified from https://stackoverflow.com/a/69141085/9643841 + public class AsyncImageLoader : MonoBehaviour + { + public List pathsToLoad = new List(); + + public class ImageLoadedEvent : UnityEvent { } + public ImageLoadedEvent imageLoadedEvent = new ImageLoadedEvent(); + + void Start() + { + for (int i = 0; i < pathsToLoad.Count; i++) + { + StartCoroutine(DownloadTexture(pathsToLoad[i], i)); + } + } + + IEnumerator DownloadTexture(string url, int index) + { + Logger.Log("loading img " + url); + using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url)) + { + yield return uwr.SendWebRequest(); + + var hasError = uwr.error != null && uwr.error != ""; + + if (hasError) // (uwr.result != UnityWebRequest.Result.Success) + { + Debug.Log(uwr.error); + } + else + { + // Get downloaded asset bundle + var texture = DownloadHandlerTexture.GetContent(uwr); + Logger.Log("Finished loading image " + url); + imageLoadedEvent.Invoke(texture, index); + } + } + } } } From 3f4b2fbe885138ecc84a9f76310d179dd4a71ecd Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 11:04:53 -0400 Subject: [PATCH 14/22] added async texture loading to autoprojectors and slide reels, also removed some dead code and uneeded comments --- .../Builder/Props/ProjectionBuilder.cs | 75 +++++++++++-------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index b1228f90..10963bac 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -62,21 +62,51 @@ namespace NewHorizons.Builder.Props // The base game ones only have 15 slides max var textures = new Texture2D[slidesCount >= 15 ? 15 : slidesCount]; + var imageLoader = slideReelObj.AddComponent(); for (int i = 0; i < slidesCount; i++) { var slide = new Slide(); var slideInfo = info.slides[i]; - var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); - slide.textureOverride = ImageUtilities.Invert(texture); - - // Track the first 15 to put on the slide reel object - if (i < 15) textures[i] = texture; + imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath); AddModules(slideInfo, ref slide); slideCollection.slides[i] = slide; - } + } + + // this variable just lets us track how many of the first 15 slides have been loaded. + // this way as soon as the last one is loaded (due to async loading, this may be + // slide 7, or slide 3, or whatever), we can build the slide reel texture. This allows us + // to avoid doing a "is every element in the array `textures` not null" check every time a texture finishes loading + int displaySlidesLoaded = 0; + imageLoader.imageLoadedEvent.AddListener( + (Texture2D tex, int index) => + { + slideCollection.slides[index].textureOverride = ImageUtilities.Invert(tex); + + // Track the first 15 to put on the slide reel object + if (index < 15) + { + textures[index] = tex; + displaySlidesLoaded++; // threading moment + } + + if (displaySlidesLoaded >= textures.Length) + { + // all textures required to build the reel's textures have been loaded + var slidesBack = slideReelObj.transform.Find("Props_IP_SlideReel_7/Slides_Back").GetComponent(); + var slidesFront = slideReelObj.transform.Find("Props_IP_SlideReel_7/Slides_Front").GetComponent(); + + // Now put together the textures into a 4x4 thing for the materials + var reelTexture = ImageUtilities.MakeReelTexture(textures); + slidesBack.material.mainTexture = reelTexture; + slidesBack.material.SetTexture(EmissionMap, reelTexture); + slidesFront.material.mainTexture = reelTexture; + slidesFront.material.SetTexture(EmissionMap, reelTexture); + } + } + ); // Else when you put them down you can't pick them back up slideReelObj.GetComponent()._physicsRemoved = false; @@ -89,16 +119,6 @@ namespace NewHorizons.Builder.Props OWAssetHandler.LoadObject(slideReelObj); sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(slideReelObj)); - var slidesBack = slideReelObj.transform.Find("Props_IP_SlideReel_7/Slides_Back").GetComponent(); - var slidesFront = slideReelObj.transform.Find("Props_IP_SlideReel_7/Slides_Front").GetComponent(); - - // Now put together the textures into a 4x4 thing for the materials - var reelTexture = ImageUtilities.MakeReelTexture(textures); - slidesBack.material.mainTexture = reelTexture; - slidesBack.material.SetTexture(EmissionMap, reelTexture); - slidesFront.material.mainTexture = reelTexture; - slidesFront.material.SetTexture(EmissionMap, reelTexture); - slideReelObj.SetActive(true); } @@ -130,19 +150,20 @@ namespace NewHorizons.Builder.Props // Now we replace the slides int slidesCount = info.slides.Length; var slideCollection = new SlideCollection(slidesCount); - + + var imageLoader = projectorObj.AddComponent(); for (int i = 0; i < slidesCount; i++) { var slide = new Slide(); var slideInfo = info.slides[i]; - var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); - slide.textureOverride = ImageUtilities.Invert(texture); + imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath); AddModules(slideInfo, ref slide); slideCollection.slides[i] = slide; } + imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index].textureOverride = ImageUtilities.Invert(tex); }); slideCollectionContainer.slideCollection = slideCollection; @@ -177,23 +198,20 @@ namespace NewHorizons.Builder.Props var slidesCount = slides.Length; var slideCollection = new SlideCollection(slidesCount); - + var imageLoader = g.AddComponent(); for (int i = 0; i < slidesCount; i++) { var slide = new Slide(); var slideInfo = slides[i]; - // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days - //var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); - //slide.textureOverride = texture; //ImageUtilities.Invert(texture); imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath); AddModules(slideInfo, ref slide); slideCollection.slides[i] = slide; - } - imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index].textureOverride = tex; }); + } + imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index].textureOverride = tex; }); // attatch a component to store all the data for the slides that play when a vision torch scans this target @@ -240,22 +258,19 @@ namespace NewHorizons.Builder.Props var slides = info.slides; var slidesCount = slides.Length; var slideCollection = new SlideCollection(slidesCount); - + var imageLoader = standingTorch.AddComponent(); for (int i = 0; i < slidesCount; i++) { var slide = new Slide(); var slideInfo = slides[i]; - // TODO: do this part asynchronously so that you can load all the slides you want without stalling the game out for 5 days - //var texture = ImageUtilities.GetTexture(mod, slideInfo.imagePath); - //slide.textureOverride = texture; //ImageUtilities.Invert(texture); imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath); AddModules(slideInfo, ref slide); slideCollection.slides[i] = slide; - } + } imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index].textureOverride = tex; }); // set up the containers for the slides From 5943e306ba5bc57a11b26a9dda2abd5bd7994d00 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 11:19:26 -0400 Subject: [PATCH 15/22] added a FindChild function to search utilities, disabled standing vision torches until all their textures have loaded --- .../Builder/Props/ProjectionBuilder.cs | 30 ++++++++++++++++--- NewHorizons/Utility/ImageUtilities.cs | 2 -- NewHorizons/Utility/SearchUtilities.cs | 12 +++++++- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 10963bac..b4bc971c 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -249,7 +249,12 @@ namespace NewHorizons.Builder.Props var mindSlideProjector = standingTorch.GetComponent(); mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); - + + // setup for visually supporting async texture loading + mindSlideProjector.enabled = false; + var visionBeamEffect = SearchUtilities.FindChild(standingTorch, "VisionBeam"); + visionBeamEffect.SetActive(false); + // // set up slides // @@ -271,7 +276,25 @@ namespace NewHorizons.Builder.Props slideCollection.slides[i] = slide; } - imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index].textureOverride = tex; }); + + // this variable just lets us track how many of the slides have been loaded. + // this way as soon as the last one is loaded (due to async loading, this may be + // slide 7, or slide 3, or whatever), we can enable the vision torch. This allows us + // to avoid doing a "is every element in the array `slideCollection.slides` not null" check every time a texture finishes loading + int displaySlidesLoaded = 0; + imageLoader.imageLoadedEvent.AddListener( + (Texture2D tex, int index) => + { + slideCollection.slides[index].textureOverride = tex; + displaySlidesLoaded++; // threading moment + + if (displaySlidesLoaded >= slides.Length) + { + mindSlideProjector.enabled = true; + visionBeamEffect.SetActive(true); + } + } + ); // set up the containers for the slides var slideCollectionContainer = standingTorch.AddComponent(); @@ -281,9 +304,8 @@ namespace NewHorizons.Builder.Props // make sure that these slides play when the player wanders into the beam // _slideCollectionItem is actually a reference to a SlideCollectionContainer. Not a slide reel item - standingTorch.GetComponent()._mindSlideCollection = mindSlideCollection; + mindSlideProjector._mindSlideCollection = mindSlideCollection; mindSlideProjector._slideCollectionItem = slideCollectionContainer; - mindSlideProjector._mindSlideCollection = mindSlideCollection; mindSlideProjector.SetMindSlideCollection(mindSlideCollection); diff --git a/NewHorizons/Utility/ImageUtilities.cs b/NewHorizons/Utility/ImageUtilities.cs index 4de79971..018abdd8 100644 --- a/NewHorizons/Utility/ImageUtilities.cs +++ b/NewHorizons/Utility/ImageUtilities.cs @@ -337,7 +337,6 @@ namespace NewHorizons.Utility IEnumerator DownloadTexture(string url, int index) { - Logger.Log("loading img " + url); using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url)) { yield return uwr.SendWebRequest(); @@ -352,7 +351,6 @@ namespace NewHorizons.Utility { // Get downloaded asset bundle var texture = DownloadHandlerTexture.GetContent(uwr); - Logger.Log("Finished loading image " + url); imageLoadedEvent.Invoke(texture, index); } } diff --git a/NewHorizons/Utility/SearchUtilities.cs b/NewHorizons/Utility/SearchUtilities.cs index 821e68ea..f1180e02 100644 --- a/NewHorizons/Utility/SearchUtilities.cs +++ b/NewHorizons/Utility/SearchUtilities.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -119,6 +119,16 @@ namespace NewHorizons.Utility } */ + public static GameObject FindChild(GameObject g, string childName) + { + foreach(Transform child in g.transform) + { + if (child.gameObject.name == childName) return child.gameObject; + } + + return null; + } + public static GameObject Find(string path) { if (CachedGameObjects.ContainsKey(path)) From 5cc232ee8c1916ad66b989ce4a145436c91a4301 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 17:42:18 -0400 Subject: [PATCH 16/22] fixed line endings --- NewHorizons/Builder/Props/DetailBuilder.cs | 6 +-- .../Builder/Props/ProjectionBuilder.cs | 44 +++++++++---------- NewHorizons/Utility/SearchUtilities.cs | 16 +++---- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index 7b687fe0..6a3add28 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -157,9 +157,9 @@ namespace NewHorizons.Builder.Props // Fix vision torch if (component is VisionTorchItem) { - (component as VisionTorchItem).enabled = true; - (component as VisionTorchItem).mindProjectorTrigger.enabled = true; - (component as VisionTorchItem).mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); + (component as VisionTorchItem).enabled = true; + (component as VisionTorchItem).mindProjectorTrigger.enabled = true; + (component as VisionTorchItem).mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); } } else diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index b4bc971c..9e3e03e0 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -73,11 +73,11 @@ namespace NewHorizons.Builder.Props AddModules(slideInfo, ref slide); slideCollection.slides[i] = slide; - } - - // this variable just lets us track how many of the first 15 slides have been loaded. - // this way as soon as the last one is loaded (due to async loading, this may be - // slide 7, or slide 3, or whatever), we can build the slide reel texture. This allows us + } + + // this variable just lets us track how many of the first 15 slides have been loaded. + // this way as soon as the last one is loaded (due to async loading, this may be + // slide 7, or slide 3, or whatever), we can build the slide reel texture. This allows us // to avoid doing a "is every element in the array `textures` not null" check every time a texture finishes loading int displaySlidesLoaded = 0; imageLoader.imageLoadedEvent.AddListener( @@ -93,7 +93,7 @@ namespace NewHorizons.Builder.Props } if (displaySlidesLoaded >= textures.Length) - { + { // all textures required to build the reel's textures have been loaded var slidesBack = slideReelObj.transform.Find("Props_IP_SlideReel_7/Slides_Back").GetComponent(); var slidesFront = slideReelObj.transform.Find("Props_IP_SlideReel_7/Slides_Front").GetComponent(); @@ -248,12 +248,12 @@ namespace NewHorizons.Builder.Props // var mindSlideProjector = standingTorch.GetComponent(); - mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); - - // setup for visually supporting async texture loading - mindSlideProjector.enabled = false; - var visionBeamEffect = SearchUtilities.FindChild(standingTorch, "VisionBeam"); - visionBeamEffect.SetActive(false); + mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); + + // setup for visually supporting async texture loading + mindSlideProjector.enabled = false; + var visionBeamEffect = SearchUtilities.FindChild(standingTorch, "VisionBeam"); + visionBeamEffect.SetActive(false); // // set up slides @@ -276,10 +276,10 @@ namespace NewHorizons.Builder.Props slideCollection.slides[i] = slide; } - - // this variable just lets us track how many of the slides have been loaded. - // this way as soon as the last one is loaded (due to async loading, this may be - // slide 7, or slide 3, or whatever), we can enable the vision torch. This allows us + + // this variable just lets us track how many of the slides have been loaded. + // this way as soon as the last one is loaded (due to async loading, this may be + // slide 7, or slide 3, or whatever), we can enable the vision torch. This allows us // to avoid doing a "is every element in the array `slideCollection.slides` not null" check every time a texture finishes loading int displaySlidesLoaded = 0; imageLoader.imageLoadedEvent.AddListener( @@ -289,8 +289,8 @@ namespace NewHorizons.Builder.Props displaySlidesLoaded++; // threading moment if (displaySlidesLoaded >= slides.Length) - { - mindSlideProjector.enabled = true; + { + mindSlideProjector.enabled = true; visionBeamEffect.SetActive(true); } } @@ -305,7 +305,7 @@ namespace NewHorizons.Builder.Props // make sure that these slides play when the player wanders into the beam // _slideCollectionItem is actually a reference to a SlideCollectionContainer. Not a slide reel item mindSlideProjector._mindSlideCollection = mindSlideCollection; - mindSlideProjector._slideCollectionItem = slideCollectionContainer; + mindSlideProjector._slideCollectionItem = slideCollectionContainer; mindSlideProjector.SetMindSlideCollection(mindSlideCollection); @@ -364,9 +364,9 @@ namespace NewHorizons.Builder.Props } } - public class VisionTorchTarget : MonoBehaviour + public class VisionTorchTarget : MonoBehaviour { - public MindSlideCollection slideCollection; - public SlideCollectionContainer slideCollectionContainer; + public MindSlideCollection slideCollection; + public SlideCollectionContainer slideCollectionContainer; } } diff --git a/NewHorizons/Utility/SearchUtilities.cs b/NewHorizons/Utility/SearchUtilities.cs index f1180e02..6697ebdc 100644 --- a/NewHorizons/Utility/SearchUtilities.cs +++ b/NewHorizons/Utility/SearchUtilities.cs @@ -119,14 +119,14 @@ namespace NewHorizons.Utility } */ - public static GameObject FindChild(GameObject g, string childName) - { - foreach(Transform child in g.transform) - { - if (child.gameObject.name == childName) return child.gameObject; - } - - return null; + public static GameObject FindChild(GameObject g, string childName) + { + foreach(Transform child in g.transform) + { + if (child.gameObject.name == childName) return child.gameObject; + } + + return null; } public static GameObject Find(string path) From 0955bda3f6748a4cff23d9e4e798c20d80f15195 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 17:44:05 -0400 Subject: [PATCH 17/22] added comment for future enhancement --- NewHorizons/Utility/ImageUtilities.cs | 84 ++++++++++++++------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/NewHorizons/Utility/ImageUtilities.cs b/NewHorizons/Utility/ImageUtilities.cs index 018abdd8..7eb0e869 100644 --- a/NewHorizons/Utility/ImageUtilities.cs +++ b/NewHorizons/Utility/ImageUtilities.cs @@ -1,12 +1,12 @@ using OWML.Common; using System; -using System.Collections; +using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; -using UnityEngine.Events; -using UnityEngine.Networking; - +using UnityEngine.Events; +using UnityEngine.Networking; + namespace NewHorizons.Utility { public static class ImageUtilities @@ -317,43 +317,47 @@ namespace NewHorizons.Utility newTexture.Apply(); return newTexture; } - } - - // Modified from https://stackoverflow.com/a/69141085/9643841 - public class AsyncImageLoader : MonoBehaviour - { - public List pathsToLoad = new List(); + } - public class ImageLoadedEvent : UnityEvent { } - public ImageLoadedEvent imageLoadedEvent = new ImageLoadedEvent(); + // Modified from https://stackoverflow.com/a/69141085/9643841 + public class AsyncImageLoader : MonoBehaviour + { + public List pathsToLoad = new List(); + + public class ImageLoadedEvent : UnityEvent { } + public ImageLoadedEvent imageLoadedEvent = new ImageLoadedEvent(); - void Start() - { - for (int i = 0; i < pathsToLoad.Count; i++) - { - StartCoroutine(DownloadTexture(pathsToLoad[i], i)); - } - } - - IEnumerator DownloadTexture(string url, int index) - { - using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url)) - { - yield return uwr.SendWebRequest(); - - var hasError = uwr.error != null && uwr.error != ""; - - if (hasError) // (uwr.result != UnityWebRequest.Result.Success) - { - Debug.Log(uwr.error); - } - else - { - // Get downloaded asset bundle - var texture = DownloadHandlerTexture.GetContent(uwr); - imageLoadedEvent.Invoke(texture, index); - } - } - } + // TODO: set up an optional “StartLoading” and “StartUnloading” condition on AsyncTextureLoader, + // and make use of that for at least for projector stuff (require player to be in the same sector as the slides + // for them to start loading, and unload when the player leaves) + + void Start() + { + for (int i = 0; i < pathsToLoad.Count; i++) + { + StartCoroutine(DownloadTexture(pathsToLoad[i], i)); + } + } + + IEnumerator DownloadTexture(string url, int index) + { + using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url)) + { + yield return uwr.SendWebRequest(); + + var hasError = uwr.error != null && uwr.error != ""; + + if (hasError) // (uwr.result != UnityWebRequest.Result.Success) + { + Debug.Log(uwr.error); + } + else + { + // Get downloaded asset bundle + var texture = DownloadHandlerTexture.GetContent(uwr); + imageLoadedEvent.Invoke(texture, index); + } + } + } } } From 9639ab6a568d791257c85bd98945edb2791176ef Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 17:54:12 -0400 Subject: [PATCH 18/22] changed line endings --- NewHorizons/Builder/Props/DetailBuilder.cs | 462 ++++++++++----------- 1 file changed, 231 insertions(+), 231 deletions(-) diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index 63287137..f21c5fd4 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -1,231 +1,231 @@ -using NewHorizons.External.Configs; -using NewHorizons.External.Modules; -using NewHorizons.Handlers; -using NewHorizons.Utility; -using OWML.Common; -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using Logger = NewHorizons.Utility.Logger; -namespace NewHorizons.Builder.Props -{ - public static class DetailBuilder - { - private static Dictionary detailInfoToCorrespondingSpawnedGameObject = new Dictionary(); - - public static GameObject GetSpawnedGameObjectByDetailInfo(PropModule.DetailInfo detail) - { - if (!detailInfoToCorrespondingSpawnedGameObject.ContainsKey(detail)) return null; - return detailInfoToCorrespondingSpawnedGameObject[detail]; - } - - public static void Make(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, PropModule.DetailInfo detail) - { - GameObject detailGO = null; - - if (detail.assetBundle != null) - { - var prefab = AssetBundleUtilities.LoadPrefab(detail.assetBundle, detail.path, mod); - - detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal); - } - else if (detail.objFilePath != null) - { - try - { - var prefab = mod.ModHelper.Assets.Get3DObject(detail.objFilePath, detail.mtlFilePath); - AssetBundleUtilities.ReplaceShaders(prefab); - prefab.SetActive(false); - 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 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 = detailGO.transform.Find(childPath); - if (childObj != null) childObj.gameObject.SetActive(false); - else Logger.LogWarning($"Couldn't find {childPath}"); - } - } - - if (detailGO != null && detail.removeComponents) - { - // Just swap all the children to a new game object - var newDetailGO = new GameObject(detailGO.name); - newDetailGO.transform.position = detailGO.transform.position; - newDetailGO.transform.parent = detailGO.transform.parent; - // Can't modify parents while looping through children bc idk - var children = new List(); - foreach (Transform child in detailGO.transform) - { - children.Add(child); - } - foreach (var child in children) - { - child.parent = newDetailGO.transform; - } - GameObject.Destroy(detailGO); - detailGO = newDetailGO; - } - - detailInfoToCorrespondingSpawnedGameObject[detail] = detailGO; - } - - 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); - } - - public static GameObject MakeDetail(GameObject planetGO, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) - { - if (prefab == null) return null; - - GameObject prop = prefab.InstantiateInactive(); - prop.transform.parent = sector?.transform ?? planetGO.transform; - prop.SetActive(false); - - if (sector != null) sector.OnOccupantEnterSector += (SectorDetector sd) => OWAssetHandler.OnOccupantEnterSector(prop, sd, sector); - OWAssetHandler.LoadObject(prop); - - foreach (var component in prop.GetComponents().Concat(prop.GetComponentsInChildren())) - { - // Enable all children or something - var enabledField = component?.GetType()?.GetField("enabled"); - if (enabledField != null && enabledField.FieldType == typeof(bool)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => enabledField.SetValue(component, true)); - - // Fix a bunch of sector stuff - if (sector != null) - { - if (component is Sector s) - { - s._parentSector = sector; - } - - // TODO: Make this work or smthng - if (component is GhostIK ik) ik.enabled = false; - if (component is GhostEffects effects) effects.enabled = false; - - if (component is DarkMatterVolume) - { - var probeVisuals = component.gameObject.transform.Find("ProbeVisuals"); - if (probeVisuals != null) probeVisuals.gameObject.SetActive(true); - } - - if (component is SectoredMonoBehaviour behaviour) - { - behaviour.SetSector(sector); - } - else - { - var sectorField = component?.GetType()?.GetField("_sector"); - if (sectorField != null && sectorField.FieldType == typeof(Sector)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => sectorField.SetValue(component, sector)); - } - - if (component is AnglerfishController angler) - { - try - { - angler._chaseSpeed += OWPhysics.CalculateOrbitVelocity(planetGO.GetAttachedOWRigidbody(), planetGO.GetComponent().GetPrimaryBody().GetAttachedOWRigidbody()).magnitude; - } - catch (Exception e) - { - Logger.LogError($"Couldn't update AnglerFish chase speed: {e.Message}"); - } - } - - // Fix slide reel - if (component is SlideCollectionContainer container) - { - sector.OnOccupantEnterSector.AddListener(_ => container.LoadStreamingTextures()); - } - - if (component is OWItemSocket socket) - { - socket._sector = sector; - } - - // Fix vision torch - if (component is VisionTorchItem) - { - (component as VisionTorchItem).enabled = true; - (component as VisionTorchItem).mindProjectorTrigger.enabled = true; - (component as VisionTorchItem).mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); - } - } - else - { - // Remove things that require sectors. Will just keep extending this as things pop up - - if (component is FogLight or SectoredMonoBehaviour) - { - GameObject.DestroyImmediate(component); - continue; - } - } - - // Fix a bunch of stuff when done loading - Main.Instance.ModHelper.Events.Unity.RunWhen(() => Main.IsSystemReady, () => - { - try - { - if (component is Animator animator) animator.enabled = true; - else if (component is Collider collider) collider.enabled = true; - else if (component is Renderer renderer) renderer.enabled = true; - else if (component is Shape shape) shape.enabled = true; - // If it's not a moving anglerfish make sure the anim controller is regular - else if (component is AnglerfishAnimController angler && angler.GetComponentInParent() == null) - { - Logger.Log("Enabling anglerfish animation"); - // Remove any reference to its angler - if (angler._anglerfishController) - { - angler._anglerfishController.OnChangeAnglerState -= angler.OnChangeAnglerState; - angler._anglerfishController.OnAnglerTurn -= angler.OnAnglerTurn; - angler._anglerfishController.OnAnglerSuspended -= angler.OnAnglerSuspended; - angler._anglerfishController.OnAnglerUnsuspended -= angler.OnAnglerUnsuspended; - } - angler.enabled = true; - angler.OnChangeAnglerState(AnglerfishController.AnglerState.Lurking); - } - } - catch (Exception e) - { - Logger.LogWarning($"Exception when modifying component [{component.GetType().Name}] on [{planetGO.name}] : {e.Message}, {e.StackTrace}"); - } - }); - } - - prop.transform.position = position == null ? planetGO.transform.position : planetGO.transform.TransformPoint((Vector3)position); - - Quaternion rot = rotation == null ? Quaternion.identity : Quaternion.Euler((Vector3)rotation); - if (alignWithNormal) - { - // Apply the rotation after aligning it with normal - var up = planetGO.transform.InverseTransformPoint(prop.transform.position).normalized; - prop.transform.rotation = Quaternion.FromToRotation(Vector3.up, up); - prop.transform.rotation *= rot; - } - else - { - prop.transform.rotation = planetGO.transform.TransformRotation(rot); - } - - prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale; - - prop.SetActive(true); - - return prop; - } - } -} ->>>>>>> dev +using NewHorizons.External.Configs; +using NewHorizons.External.Modules; +using NewHorizons.Handlers; +using NewHorizons.Utility; +using OWML.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; +namespace NewHorizons.Builder.Props +{ + public static class DetailBuilder + { + private static Dictionary detailInfoToCorrespondingSpawnedGameObject = new Dictionary(); + + public static GameObject GetSpawnedGameObjectByDetailInfo(PropModule.DetailInfo detail) + { + if (!detailInfoToCorrespondingSpawnedGameObject.ContainsKey(detail)) return null; + return detailInfoToCorrespondingSpawnedGameObject[detail]; + } + + public static void Make(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, PropModule.DetailInfo detail) + { + GameObject detailGO = null; + + if (detail.assetBundle != null) + { + var prefab = AssetBundleUtilities.LoadPrefab(detail.assetBundle, detail.path, mod); + + detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal); + } + else if (detail.objFilePath != null) + { + try + { + var prefab = mod.ModHelper.Assets.Get3DObject(detail.objFilePath, detail.mtlFilePath); + AssetBundleUtilities.ReplaceShaders(prefab); + prefab.SetActive(false); + 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 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 = detailGO.transform.Find(childPath); + if (childObj != null) childObj.gameObject.SetActive(false); + else Logger.LogWarning($"Couldn't find {childPath}"); + } + } + + if (detailGO != null && detail.removeComponents) + { + // Just swap all the children to a new game object + var newDetailGO = new GameObject(detailGO.name); + newDetailGO.transform.position = detailGO.transform.position; + newDetailGO.transform.parent = detailGO.transform.parent; + // Can't modify parents while looping through children bc idk + var children = new List(); + foreach (Transform child in detailGO.transform) + { + children.Add(child); + } + foreach (var child in children) + { + child.parent = newDetailGO.transform; + } + GameObject.Destroy(detailGO); + detailGO = newDetailGO; + } + + detailInfoToCorrespondingSpawnedGameObject[detail] = detailGO; + } + + 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); + } + + public static GameObject MakeDetail(GameObject planetGO, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal) + { + if (prefab == null) return null; + + GameObject prop = prefab.InstantiateInactive(); + prop.transform.parent = sector?.transform ?? planetGO.transform; + prop.SetActive(false); + + if (sector != null) sector.OnOccupantEnterSector += (SectorDetector sd) => OWAssetHandler.OnOccupantEnterSector(prop, sd, sector); + OWAssetHandler.LoadObject(prop); + + foreach (var component in prop.GetComponents().Concat(prop.GetComponentsInChildren())) + { + // Enable all children or something + var enabledField = component?.GetType()?.GetField("enabled"); + if (enabledField != null && enabledField.FieldType == typeof(bool)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => enabledField.SetValue(component, true)); + + // Fix a bunch of sector stuff + if (sector != null) + { + if (component is Sector s) + { + s._parentSector = sector; + } + + // TODO: Make this work or smthng + if (component is GhostIK ik) ik.enabled = false; + if (component is GhostEffects effects) effects.enabled = false; + + if (component is DarkMatterVolume) + { + var probeVisuals = component.gameObject.transform.Find("ProbeVisuals"); + if (probeVisuals != null) probeVisuals.gameObject.SetActive(true); + } + + if (component is SectoredMonoBehaviour behaviour) + { + behaviour.SetSector(sector); + } + else + { + var sectorField = component?.GetType()?.GetField("_sector"); + if (sectorField != null && sectorField.FieldType == typeof(Sector)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => sectorField.SetValue(component, sector)); + } + + if (component is AnglerfishController angler) + { + try + { + angler._chaseSpeed += OWPhysics.CalculateOrbitVelocity(planetGO.GetAttachedOWRigidbody(), planetGO.GetComponent().GetPrimaryBody().GetAttachedOWRigidbody()).magnitude; + } + catch (Exception e) + { + Logger.LogError($"Couldn't update AnglerFish chase speed: {e.Message}"); + } + } + + // Fix slide reel + if (component is SlideCollectionContainer container) + { + sector.OnOccupantEnterSector.AddListener(_ => container.LoadStreamingTextures()); + } + + if (component is OWItemSocket socket) + { + socket._sector = sector; + } + + // Fix vision torch + if (component is VisionTorchItem) + { + (component as VisionTorchItem).enabled = true; + (component as VisionTorchItem).mindProjectorTrigger.enabled = true; + (component as VisionTorchItem).mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); + } + } + else + { + // Remove things that require sectors. Will just keep extending this as things pop up + + if (component is FogLight or SectoredMonoBehaviour) + { + GameObject.DestroyImmediate(component); + continue; + } + } + + // Fix a bunch of stuff when done loading + Main.Instance.ModHelper.Events.Unity.RunWhen(() => Main.IsSystemReady, () => + { + try + { + if (component is Animator animator) animator.enabled = true; + else if (component is Collider collider) collider.enabled = true; + else if (component is Renderer renderer) renderer.enabled = true; + else if (component is Shape shape) shape.enabled = true; + // If it's not a moving anglerfish make sure the anim controller is regular + else if (component is AnglerfishAnimController angler && angler.GetComponentInParent() == null) + { + Logger.Log("Enabling anglerfish animation"); + // Remove any reference to its angler + if (angler._anglerfishController) + { + angler._anglerfishController.OnChangeAnglerState -= angler.OnChangeAnglerState; + angler._anglerfishController.OnAnglerTurn -= angler.OnAnglerTurn; + angler._anglerfishController.OnAnglerSuspended -= angler.OnAnglerSuspended; + angler._anglerfishController.OnAnglerUnsuspended -= angler.OnAnglerUnsuspended; + } + angler.enabled = true; + angler.OnChangeAnglerState(AnglerfishController.AnglerState.Lurking); + } + } + catch (Exception e) + { + Logger.LogWarning($"Exception when modifying component [{component.GetType().Name}] on [{planetGO.name}] : {e.Message}, {e.StackTrace}"); + } + }); + } + + prop.transform.position = position == null ? planetGO.transform.position : planetGO.transform.TransformPoint((Vector3)position); + + Quaternion rot = rotation == null ? Quaternion.identity : Quaternion.Euler((Vector3)rotation); + if (alignWithNormal) + { + // Apply the rotation after aligning it with normal + var up = planetGO.transform.InverseTransformPoint(prop.transform.position).normalized; + prop.transform.rotation = Quaternion.FromToRotation(Vector3.up, up); + prop.transform.rotation *= rot; + } + else + { + prop.transform.rotation = planetGO.transform.TransformRotation(rot); + } + + prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale; + + prop.SetActive(true); + + return prop; + } + } +} +>>>>>>> dev From 8aab28d6b0b2f29c3f88cf38c3a9d9aea657011a Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 17:54:45 -0400 Subject: [PATCH 19/22] removed artifact from merge conflict --- NewHorizons/Builder/Props/DetailBuilder.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index f21c5fd4..44e88666 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -227,5 +227,4 @@ namespace NewHorizons.Builder.Props return prop; } } -} ->>>>>>> dev +} \ No newline at end of file From 47dd2c2a3a941b85dbcc1a1391d81bde08b76331 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 17:56:18 -0400 Subject: [PATCH 20/22] removed artifact from merge conflict --- NewHorizons/External/Modules/PropModule.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index 0b21a8fa..0c658138 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -1,14 +1,10 @@ -<<<<<<< HEAD + using NewHorizons.Utility; using System.ComponentModel; -======= -using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; -using NewHorizons.Utility; using Newtonsoft.Json; using Newtonsoft.Json.Converters; ->>>>>>> dev namespace NewHorizons.External.Modules { @@ -510,13 +506,6 @@ namespace NewHorizons.External.Modules /// The ship log entries revealed after finishing this slide reel. /// public string[] reveals; -<<<<<<< HEAD - public SlideInfo[] slides; - - // enum values for this property: "autoProjector", "slideReel", "playerVisionTorchTarget", "standingVisionTorch" - // I don't know why the default value is capital 'S' SlideReel. it should be lower case as far as I can tell. - public string type = "SlideReel"; -======= /// /// The rotation of this slideshow. @@ -532,7 +521,6 @@ namespace NewHorizons.External.Modules /// The type of object this is. /// public SlideShowType type = SlideShowType.SlideReel; ->>>>>>> dev } [JsonObject] From bbd8e62fdb113b1edaf5acf752aa1784e9c9559c Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 17:56:36 -0400 Subject: [PATCH 21/22] changed line endings --- NewHorizons/Handlers/TitleSceneHandler.cs | 250 +++++++++++----------- 1 file changed, 125 insertions(+), 125 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index aff03cc2..6baf33ea 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -1,125 +1,125 @@ -using NewHorizons.Builder.Body; -using NewHorizons.External.Modules; -using NewHorizons.Utility; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using Logger = NewHorizons.Utility.Logger; -using NewHorizons.External.Modules.VariableSize; - -namespace NewHorizons.Handlers -{ - public static class TitleSceneHandler - { - public static void InitSubtitles() - { - GameObject subtitleContainer = GameObject.Find("TitleMenu/TitleCanvas/TitleLayoutGroup/Logo_EchoesOfTheEye"); - - if (subtitleContainer == null) - { - Logger.LogError("No subtitle container found! Failed to load subtitles."); - return; - } - - subtitleContainer.SetActive(true); - subtitleContainer.AddComponent(); - } - - public static void DisplayBodyOnTitleScreen(List bodies) - { - //Try loading one planet why not - //var eligible = BodyDict.Values.ToList().SelectMany(x => x).ToList().Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.Cloud != null) && b.Config.Star == null).ToArray(); - var eligible = bodies.Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.clouds != null) && b.Config.Star == null && b.Config.canShowOnTitle).ToArray(); - var eligibleCount = eligible.Count(); - if (eligibleCount == 0) return; - - var selectionCount = Mathf.Min(eligibleCount, 3); - var indices = RandomUtility.GetUniqueRandomArray(0, eligible.Count(), selectionCount); - - Logger.Log($"Displaying {selectionCount} bodies on the title screen"); - - GameObject body1, body2, body3; - - body1 = LoadTitleScreenBody(eligible[indices[0]]); - body1.transform.localRotation = Quaternion.Euler(15, 0, 0); - if (selectionCount > 1) - { - body1.transform.localScale = Vector3.one * (body1.transform.localScale.x) * 0.3f; - body1.transform.localPosition = new Vector3(0, -15, 0); - body1.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); - body2 = LoadTitleScreenBody(eligible[indices[1]]); - body2.transform.localScale = Vector3.one * (body2.transform.localScale.x) * 0.3f; - body2.transform.localPosition = new Vector3(7, 30, 0); - body2.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); - } - if (selectionCount > 2) - { - body3 = LoadTitleScreenBody(eligible[indices[2]]); - body3.transform.localScale = Vector3.one * (body3.transform.localScale.x) * 0.3f; - body3.transform.localPosition = new Vector3(-5, 10, 0); - body3.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); - } - - GameObject.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire").SetActive(false); - GameObject.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false); - - var lightGO = new GameObject("Light"); - lightGO.transform.parent = GameObject.Find("Scene/Background").transform; - lightGO.transform.localPosition = new Vector3(-47.9203f, 145.7596f, 43.1802f); - var light = lightGO.AddComponent(); - light.color = new Color(1f, 1f, 1f, 1f); - light.range = 100; - light.intensity = 0.8f; - } - - private static GameObject LoadTitleScreenBody(NewHorizonsBody body) - { - Logger.Log($"Displaying {body.Config.name} on the title screen"); - GameObject titleScreenGO = new GameObject(body.Config.name + "_TitleScreen"); - HeightMapModule heightMap = new HeightMapModule(); - var minSize = 15; - var maxSize = 30; - float size = minSize; - if (body.Config.HeightMap != null) - { - size = Mathf.Clamp(body.Config.HeightMap.maxHeight / 10, minSize, maxSize); - heightMap.textureMap = body.Config.HeightMap.textureMap; - heightMap.heightMap = body.Config.HeightMap.heightMap; - heightMap.maxHeight = size; - heightMap.minHeight = body.Config.HeightMap.minHeight * size / body.Config.HeightMap.maxHeight; - } - if (body.Config.Atmosphere?.clouds?.texturePath != null) - { - // Hacky but whatever I just want a sphere - size = Mathf.Clamp(body.Config.Atmosphere.size / 10, minSize, maxSize); - heightMap.maxHeight = heightMap.minHeight = size + 1; - heightMap.textureMap = body.Config.Atmosphere.clouds.texturePath; - } - - HeightMapBuilder.Make(titleScreenGO, null, heightMap, body.Mod); - - GameObject pivot = GameObject.Instantiate(GameObject.Find("Scene/Background/PlanetPivot"), GameObject.Find("Scene/Background").transform); - pivot.GetComponent()._degreesPerSecond = 10f; - foreach (Transform child in pivot.transform) - { - GameObject.Destroy(child.gameObject); - } - pivot.name = "Pivot"; - - if (body.Config.Ring != null) - { - RingModule newRing = new RingModule(); - newRing.innerRadius = size * 1.2f; - newRing.outerRadius = size * 2f; - newRing.texture = body.Config.Ring.texture; - var ring = RingBuilder.Make(titleScreenGO, null, newRing, body.Mod); - titleScreenGO.transform.localScale = Vector3.one * 0.8f; - } - - titleScreenGO.transform.parent = pivot.transform; - titleScreenGO.transform.localPosition = Vector3.zero; - - return titleScreenGO; - } - } -} +using NewHorizons.Builder.Body; +using NewHorizons.External.Modules; +using NewHorizons.Utility; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; +using NewHorizons.External.Modules.VariableSize; + +namespace NewHorizons.Handlers +{ + public static class TitleSceneHandler + { + public static void InitSubtitles() + { + GameObject subtitleContainer = GameObject.Find("TitleMenu/TitleCanvas/TitleLayoutGroup/Logo_EchoesOfTheEye"); + + if (subtitleContainer == null) + { + Logger.LogError("No subtitle container found! Failed to load subtitles."); + return; + } + + subtitleContainer.SetActive(true); + subtitleContainer.AddComponent(); + } + + public static void DisplayBodyOnTitleScreen(List bodies) + { + //Try loading one planet why not + //var eligible = BodyDict.Values.ToList().SelectMany(x => x).ToList().Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.Cloud != null) && b.Config.Star == null).ToArray(); + var eligible = bodies.Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.clouds != null) && b.Config.Star == null && b.Config.canShowOnTitle).ToArray(); + var eligibleCount = eligible.Count(); + if (eligibleCount == 0) return; + + var selectionCount = Mathf.Min(eligibleCount, 3); + var indices = RandomUtility.GetUniqueRandomArray(0, eligible.Count(), selectionCount); + + Logger.Log($"Displaying {selectionCount} bodies on the title screen"); + + GameObject body1, body2, body3; + + body1 = LoadTitleScreenBody(eligible[indices[0]]); + body1.transform.localRotation = Quaternion.Euler(15, 0, 0); + if (selectionCount > 1) + { + body1.transform.localScale = Vector3.one * (body1.transform.localScale.x) * 0.3f; + body1.transform.localPosition = new Vector3(0, -15, 0); + body1.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); + body2 = LoadTitleScreenBody(eligible[indices[1]]); + body2.transform.localScale = Vector3.one * (body2.transform.localScale.x) * 0.3f; + body2.transform.localPosition = new Vector3(7, 30, 0); + body2.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); + } + if (selectionCount > 2) + { + body3 = LoadTitleScreenBody(eligible[indices[2]]); + body3.transform.localScale = Vector3.one * (body3.transform.localScale.x) * 0.3f; + body3.transform.localPosition = new Vector3(-5, 10, 0); + body3.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); + } + + GameObject.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire").SetActive(false); + GameObject.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false); + + var lightGO = new GameObject("Light"); + lightGO.transform.parent = GameObject.Find("Scene/Background").transform; + lightGO.transform.localPosition = new Vector3(-47.9203f, 145.7596f, 43.1802f); + var light = lightGO.AddComponent(); + light.color = new Color(1f, 1f, 1f, 1f); + light.range = 100; + light.intensity = 0.8f; + } + + private static GameObject LoadTitleScreenBody(NewHorizonsBody body) + { + Logger.Log($"Displaying {body.Config.name} on the title screen"); + GameObject titleScreenGO = new GameObject(body.Config.name + "_TitleScreen"); + HeightMapModule heightMap = new HeightMapModule(); + var minSize = 15; + var maxSize = 30; + float size = minSize; + if (body.Config.HeightMap != null) + { + size = Mathf.Clamp(body.Config.HeightMap.maxHeight / 10, minSize, maxSize); + heightMap.textureMap = body.Config.HeightMap.textureMap; + heightMap.heightMap = body.Config.HeightMap.heightMap; + heightMap.maxHeight = size; + heightMap.minHeight = body.Config.HeightMap.minHeight * size / body.Config.HeightMap.maxHeight; + } + if (body.Config.Atmosphere?.clouds?.texturePath != null) + { + // Hacky but whatever I just want a sphere + size = Mathf.Clamp(body.Config.Atmosphere.size / 10, minSize, maxSize); + heightMap.maxHeight = heightMap.minHeight = size + 1; + heightMap.textureMap = body.Config.Atmosphere.clouds.texturePath; + } + + HeightMapBuilder.Make(titleScreenGO, null, heightMap, body.Mod); + + GameObject pivot = GameObject.Instantiate(GameObject.Find("Scene/Background/PlanetPivot"), GameObject.Find("Scene/Background").transform); + pivot.GetComponent()._degreesPerSecond = 10f; + foreach (Transform child in pivot.transform) + { + GameObject.Destroy(child.gameObject); + } + pivot.name = "Pivot"; + + if (body.Config.Ring != null) + { + RingModule newRing = new RingModule(); + newRing.innerRadius = size * 1.2f; + newRing.outerRadius = size * 2f; + newRing.texture = body.Config.Ring.texture; + var ring = RingBuilder.Make(titleScreenGO, null, newRing, body.Mod); + titleScreenGO.transform.localScale = Vector3.one * 0.8f; + } + + titleScreenGO.transform.parent = pivot.transform; + titleScreenGO.transform.localPosition = Vector3.zero; + + return titleScreenGO; + } + } +} From 4879c68184e9a1cdf22c7f01552f6ad0245814b8 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Wed, 25 May 2022 18:15:57 -0400 Subject: [PATCH 22/22] made lines pretty --- NewHorizons/Builder/Props/DetailBuilder.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index 44e88666..1fe65895 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -155,11 +155,11 @@ namespace NewHorizons.Builder.Props } // Fix vision torch - if (component is VisionTorchItem) + if (component is VisionTorchItem torchItem) { - (component as VisionTorchItem).enabled = true; - (component as VisionTorchItem).mindProjectorTrigger.enabled = true; - (component as VisionTorchItem).mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); + torchItem.enabled = true; + torchItem.mindProjectorTrigger.enabled = true; + torchItem.mindSlideProjector._mindProjectorImageEffect = GameObject.Find("Player_Body/PlayerCamera").GetComponent(); } } else