diff --git a/QSB/EchoesOfTheEye/DreamLantern/Patches/DreamLanternPatches.cs b/QSB/EchoesOfTheEye/DreamLantern/Patches/DreamLanternPatches.cs index de3ca8c4b..48db5e028 100644 --- a/QSB/EchoesOfTheEye/DreamLantern/Patches/DreamLanternPatches.cs +++ b/QSB/EchoesOfTheEye/DreamLantern/Patches/DreamLanternPatches.cs @@ -8,12 +8,13 @@ namespace QSB.EchoesOfTheEye.DreamLantern.Patches; +[HarmonyPatch(typeof(DreamLanternController))] public class DreamLanternPatches : QSBPatch { public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect; [HarmonyPrefix] - [HarmonyPatch(typeof(DreamLanternController), nameof(DreamLanternController.SetLit))] + [HarmonyPatch(nameof(DreamLanternController.SetLit))] public static void SetLit(DreamLanternController __instance, bool lit) { if (Remote) @@ -41,7 +42,7 @@ public static void SetLit(DreamLanternController __instance, bool lit) } [HarmonyPrefix] - [HarmonyPatch(typeof(DreamLanternController), nameof(DreamLanternController.SetConcealed))] + [HarmonyPatch(nameof(DreamLanternController.SetConcealed))] public static void SetConcealed(DreamLanternController __instance, bool concealed) { if (Remote) @@ -69,7 +70,7 @@ public static void SetConcealed(DreamLanternController __instance, bool conceale } [HarmonyPrefix] - [HarmonyPatch(typeof(DreamLanternController), nameof(DreamLanternController.SetFocus))] + [HarmonyPatch(nameof(DreamLanternController.SetFocus))] public static void SetFocus(DreamLanternController __instance, float focus) { if (Remote) @@ -98,7 +99,7 @@ public static void SetFocus(DreamLanternController __instance, float focus) } [HarmonyPrefix] - [HarmonyPatch(typeof(DreamLanternController), nameof(DreamLanternController.SetRange))] + [HarmonyPatch(nameof(DreamLanternController.SetRange))] public static void SetRange(DreamLanternController __instance, float minRange, float maxRange) { if (Remote) @@ -125,10 +126,134 @@ public static void SetRange(DreamLanternController __instance, float minRange, f qsbDreamLantern.SendMessage(new SetRangeMessage(minRange, maxRange)); } + [HarmonyPrefix] + [HarmonyPatch(nameof(DreamLanternController.UpdateVisuals))] + public static bool UpdateVisuals(DreamLanternController __instance) + { + if (!QSBWorldSync.AllObjectsReady) + { + return true; + } + + var worldObject = __instance.GetWorldObject(); + + if (worldObject.IsGhostLantern || worldObject.DreamLanternItem._lanternType == DreamLanternType.Malfunctioning) + { + return true; + } + + if (__instance._dirtyFlag_heldByPlayer) + { + var localHeldItem = Locator.GetToolModeSwapper().GetItemCarryTool().GetHeldItem(); + var heldByLocalPlayer = localHeldItem != null && (DreamLanternItem)localHeldItem == worldObject.DreamLanternItem; + // Only change to VM group when the local player is holding, not remote players + if (heldByLocalPlayer) + { + if (__instance._worldModelGroup != null) + { + __instance._worldModelGroup.SetActive(!__instance._heldByPlayer); + } + + if (__instance._viewModelGroup != null) + { + __instance._viewModelGroup.SetActive(__instance._heldByPlayer); + } + } + } + + if (__instance._dirtyFlag_lit || __instance._dirtyFlag_flameStrength) + { + var vector = new Vector4(1f, 1f, 0f, 0f); + vector.w = Mathf.Lerp(0.5f, 0f, __instance._flameStrength); + foreach (var flame in __instance._flameRenderers) + { + flame.SetActivation(__instance._lit || __instance._flameStrength > 0f); + flame.SetMaterialProperty(__instance._propID_MainTex_ST, vector); + } + } + + if (__instance._dirtyFlag_lensFlareStrength) + { + __instance._lensFlare.brightness = __instance._lensFlareStrength; + __instance._lensFlare.enabled = __instance._lensFlareStrength > 0f; + } + + if (__instance._dirtyFlag_focus) + { + var petalRotation = new Vector3(0f, 0f, Mathf.Lerp(90f, 0f, __instance._focus)); + for (var j = 0; j < __instance._focuserPetals.Length; j++) + { + __instance._focuserPetals[j].localEulerAngles = __instance._focuserPetalsBaseEulerAngles[j] + petalRotation; + worldObject.NonVMFocuserPetals[j].localEulerAngles = __instance._focuserPetalsBaseEulerAngles[j] + petalRotation; + } + } + + if (__instance._dirtyFlag_concealment) + { + var rootScale = new Vector3(1f, Mathf.Lerp(0.5f, 1f, __instance._concealment), 1f); + for (var k = 0; k < __instance._concealerRoots.Length; k++) + { + __instance._concealerRoots[k].localScale = Vector3.Scale(__instance._concealerRootsBaseScale[k], rootScale); + worldObject.NonVMConcealerRoots[k].localScale = Vector3.Scale(__instance._concealerRootsBaseScale[k], rootScale); + } + + for (var l = 0; l < __instance._concealerCovers.Length; l++) + { + __instance._concealerCovers[l].localPosition = Vector3.Lerp(__instance._concealerCoverTargets[l], __instance._concealerCoversStartPos[l], __instance._concealment); + __instance._concealerCoversVMPrepass[l].localPosition = Vector3.Lerp(__instance._concealerCoverTargets[l], __instance._concealerCoversStartPos[l], __instance._concealment); + worldObject.NonVMConcealerCovers[l].localPosition = Vector3.Lerp(__instance._concealerCoverTargets[l], __instance._concealerCoversStartPos[l], __instance._concealment); + } + } + + if (__instance._dirtyFlag_flameStrength) + { + var flameActive = __instance._flameStrength > 0f; + __instance._light.SetActivation(flameActive); + } + + if (__instance._dirtyFlag_focus || __instance._dirtyFlag_flameStrength || __instance._dirtyFlag_range) + { + var num = Mathf.Lerp(__instance._minRange, __instance._maxRange, Mathf.Pow(__instance._focus, 5f)) * __instance._flameStrength; + var num2 = Mathf.Lerp(__instance._maxAngle, __instance._minAngle, __instance._focus); + __instance._light.range = num; + __instance._light.GetLight().spotAngle = num2; + __instance.SetDetectorPositionAndSize(num, num2); + } + + if (__instance._grabbedByGhost) + { + var num3 = Mathf.MoveTowards(__instance._light.GetIntensity(), 1.2f, Time.deltaTime * 0.2f); + __instance._light.SetIntensity(num3); + } + else if (__instance._dirtyFlag_socketed || __instance._dirtyFlag_grabbedByGhost) + { + __instance._light.SetIntensity(__instance._socketed ? 0f : 1f); + } + + if (__instance._dirtyFlag_flameStrength) + { + foreach (var light in __instance._flameLights) + { + light.SetActivation(__instance._flameStrength > 0f); + light.SetIntensityScale(__instance._flameStrength); + } + } + + if ((__instance._dirtyFlag_focus || __instance._dirtyFlag_lit || __instance._dirtyFlag_concealed) && __instance._simLightConeUnfocused != null && __instance._simLightConeFocused != null) + { + var flag2 = __instance.IsFocused(0.9f); + __instance._simLightConeUnfocused.SetActive(__instance._lit && !__instance._concealed && !flag2); + __instance._simLightConeFocused.SetActive(__instance._lit && !__instance._concealed && flag2); + } + + __instance.ClearDirtyFlags(); + return false; + } + #region flare stuff [HarmonyPrefix] - [HarmonyPatch(typeof(DreamLanternController), nameof(DreamLanternController.Update))] + [HarmonyPatch(nameof(DreamLanternController.Update))] public static bool Update(DreamLanternController __instance) { // mmm i love not using transpiler LOL cry about it diff --git a/QSB/EchoesOfTheEye/DreamLantern/WorldObjects/QSBDreamLanternController.cs b/QSB/EchoesOfTheEye/DreamLantern/WorldObjects/QSBDreamLanternController.cs index 28e3c232e..97e4617c0 100644 --- a/QSB/EchoesOfTheEye/DreamLantern/WorldObjects/QSBDreamLanternController.cs +++ b/QSB/EchoesOfTheEye/DreamLantern/WorldObjects/QSBDreamLanternController.cs @@ -3,6 +3,8 @@ using QSB.Messaging; using QSB.WorldSync; using System.Threading; +using QSB.Utility; +using UnityEngine; namespace QSB.EchoesOfTheEye.DreamLantern.WorldObjects; @@ -10,16 +12,63 @@ public class QSBDreamLanternController : WorldObject { public DreamLanternItem DreamLanternItem { get; private set; } + public Transform[] NonVMFocuserPetals; + public Transform[] NonVMConcealerRoots; + public override async UniTask Init(CancellationToken ct) { // Ghosts don't have the item and instead the effects are controlled by GhostEffects if (!IsGhostLantern) { + DebugLog.DebugWrite($"Not GhostLantern, getting DreamLanternItem"); DreamLanternItem = AttachedObject.GetComponent(); + if (DreamLanternItem == null) // ghost lanterns don't have DreamLanternItems attached + { + return; + } + + DebugLog.DebugWrite($"_lanternType is {DreamLanternItem._lanternType}"); + if (DreamLanternItem._lanternType == DreamLanternType.Malfunctioning) + { + DebugLog.DebugWrite($"returning..."); + return; + } + AttachedObject._lensFlare.brightness = 0.5f; // ghost lanterns use this. in vanilla its 0 // also has blue lens flare instead of green. keep it like that for gamplay or wtv AttachedObject._origLensFlareBrightness = AttachedObject._lensFlare.brightness; + + // Find non-viewmodel transforms for remote player animations + + var focuser = AttachedObject._worldModelGroup.transform.Find("Focuser"); + NonVMFocuserPetals = new Transform[5] + { + focuser.Find("Panel_01"), + focuser.Find("Panel_02"), + focuser.Find("Panel_03"), + focuser.Find("Panel_04"), + focuser.Find("Panel_05") + }; + + var lanternHood = AttachedObject._worldModelGroup.transform.Find("LanternHood"); + var hoodBottom = lanternHood.Find("Hood_Bottom"); + var hoodTop = lanternHood.Find("Hood_Top"); + NonVMConcealerRoots = new Transform[2] + { + hoodBottom, + hoodTop + }; + + NonVMConcealerCovers = new Transform[6] + { + hoodTop.Find("Cover_01"), + hoodTop.Find("Cover_02"), + hoodTop.Find("Cover_03"), + hoodBottom.Find("Cover_04"), + hoodBottom.Find("Cover_05"), + hoodBottom.Find("Cover_06") + }; } } diff --git a/QSB/EchoesOfTheEye/DreamLantern/WorldObjects/QSBDreamLanternItem.cs b/QSB/EchoesOfTheEye/DreamLantern/WorldObjects/QSBDreamLanternItem.cs index 02912b01b..27dbc1919 100644 --- a/QSB/EchoesOfTheEye/DreamLantern/WorldObjects/QSBDreamLanternItem.cs +++ b/QSB/EchoesOfTheEye/DreamLantern/WorldObjects/QSBDreamLanternItem.cs @@ -1,45 +1,17 @@ -using Cysharp.Threading.Tasks; -using QSB.ItemSync.WorldObjects.Items; -using System.Linq; -using System.Threading; +using QSB.ItemSync.WorldObjects.Items; using UnityEngine; namespace QSB.EchoesOfTheEye.DreamLantern.WorldObjects; public class QSBDreamLanternItem : QSBItem { - private Material[] _materials; - - public override async UniTask Init(CancellationToken ct) - { - await base.Init(ct); - - // Some lanterns (ie, nonfunctioning) don't have a view model group - if (AttachedObject._lanternType != DreamLanternType.Nonfunctioning) - { - _materials = AttachedObject._lanternController._viewModelGroup?.GetComponentsInChildren(true)?.SelectMany(x => x.materials)?.ToArray(); - } - } - public override void PickUpItem(Transform holdTransform) { base.PickUpItem(holdTransform); - // Fixes #502: Artifact is visible through the walls if (AttachedObject._lanternType != DreamLanternType.Nonfunctioning) { - foreach (var m in _materials) - { - if (m.renderQueue >= 2000) - { - m.renderQueue -= 2000; - } - } - - // The view model looks much smaller than the dropped item AttachedObject.gameObject.transform.localScale = Vector3.one * 2f; - - // BUG: iirc grapple totem fov change doesnt show on viewmodel so it looks weird with other players holding the lanterns } AttachedObject.EnableInteraction(true); @@ -51,15 +23,7 @@ public override void DropItem(Vector3 worldPosition, Vector3 worldNormal, Transf if (AttachedObject._lanternType != DreamLanternType.Nonfunctioning) { - foreach (var m in _materials) - { - if (m.renderQueue < 2000) - { - m.renderQueue += 2000; - } - } - - AttachedObject.gameObject.transform.localScale = Vector3.one; + if (AttachedObject._lanternType != DreamLanternType.Nonfunctioning) } // If in the DreamWorld, don't let other people pick up your lantern