using HarmonyLib; using System.Reflection; namespace ManifoldGardenArchipelago { [HarmonyPatch(typeof(LineDoorController), "SetDoorOpenCloseStateAnimated")] static class LineDoorControllerSetDoorOpenCloseStateAnimatedPatch { static bool Prefix(LineDoorController __instance, bool open) { SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance); if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription)) { if (sceneDescription.doors.TryGetValue(sir.index, out var requirement)) { if (open != requirement.Check()) { return false; } } } return true; } } [HarmonyPatch(typeof(ButtonLineActivator), "ToggleButtonPress")] static class ButtonLineActivatorToggleButtonPressPatch { static void Prefix(ButtonLineActivator __instance, bool setPressed) { SceneItemReference sir = GameState.GetButtonSceneReference(__instance); Plugin.Logger.LogInfo($"Button {sir} state {setPressed}"); if (!GameData.listenersByButton.TryGetValue(sir, out GameStateListeners listeners)) { return; } if (setPressed) { Plugin.slotSave.ActivatedButtons.Add(sir); } else { Plugin.slotSave.ActivatedButtons.Remove(sir); } GameState.EvaluateGameStateListeners(listeners); } } [HarmonyPatch(typeof(CubeReceiverController), "SetActivatorActive")] static class CubeReceiverControllerSetActivatorActivePatch { static void Prefix(CubeReceiverController __instance, bool active) { SceneItemReference sir = GameState.GetSocketSceneReference(__instance); Plugin.Logger.LogInfo($"Socket {sir} state {active}"); if (!GameData.listenersBySocket.TryGetValue(sir, out GameStateListeners listeners)) { return; } if (active) { Plugin.slotSave.ActivatedSockets.Add(sir); } else { Plugin.slotSave.ActivatedSockets.Remove(sir); } GameState.EvaluateGameStateListeners(listeners); } } [HarmonyPatch(typeof(CubeLineActivator), "SetActivatorActive")] static class CubeLineActivatorSetActivatorActivePatch { static void Prefix(CubeLineActivator __instance, bool setActive) { SceneItemReference sir = GameState.GetPadSceneReference(__instance); Plugin.Logger.LogInfo($"Pad {sir} state {setActive}"); if (!GameData.listenersByPad.TryGetValue(sir, out GameStateListeners listeners)) { return; } if (setActive) { Plugin.slotSave.ActivatedPads.Add(sir); } else { Plugin.slotSave.ActivatedPads.Remove(sir); } GameState.EvaluateGameStateListeners(listeners); } } [HarmonyPatch(typeof(WaterDetector), "SetActivatorActive")] static class WaterDetectorSetActivatorActivePatch { static void Prefix(WaterDetector __instance, bool setActive) { SceneItemReference sir = GameState.GetWaterwheelSceneReference(__instance); Plugin.Logger.LogInfo($"Waterwheel {sir} state {setActive}"); if (!GameData.listenersByWaterwheel.TryGetValue(sir, out GameStateListeners listeners)) { return; } if (setActive) { Plugin.slotSave.ActivatedWaterwheels.Add(sir); } else { Plugin.slotSave.ActivatedWaterwheels.Remove(sir); } GameState.EvaluateGameStateListeners(listeners); } } [HarmonyPatch(typeof(SphereController), nameof(SphereController.SetState))] static class SphereControllerSetStatePatch { static void Prefix(SphereController __instance, SphereController.State newState) { SceneItemReference sir = GameState.GetSphereSceneReference(__instance); Plugin.Logger.LogInfo($"Sphere {sir} state {newState}"); if (!GameData.listenersBySphere.TryGetValue(sir, out GameStateListeners listeners)) { return; } if (newState == SphereController.State.AtDestination) { Plugin.slotSave.ActivatedSpheres.Add(sir); } else { Plugin.slotSave.ActivatedSpheres.Remove(sir); } GameState.EvaluateGameStateListeners(listeners); } } [HarmonyPatch(typeof(LineDoorController), nameof(LineDoorController.OnLevelEnable))] static class LineDoorControllerOnLevelEnablePatch { static void Prefix(LineDoorController __instance) { SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance); if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription)) { if (sceneDescription.doors.TryGetValue(sir.index, out var requirement)) { FieldInfo fieldInfo = typeof(LineDoorController).GetField("doorShouldOpenImmediatelyOnEnable", BindingFlags.Instance | BindingFlags.NonPublic); fieldInfo.SetValue(__instance, requirement.Check()); __instance.chains.Clear(); } } } } [HarmonyPatch(typeof(LineDoorController), nameof(LineDoorController.OnLoad))] static class LineDoorControllerOnLoadPatch { static void Prefix(LineDoorController __instance) { SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance); if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription)) { if (sceneDescription.doors.TryGetValue(sir.index, out var requirement)) { FieldInfo fieldInfo = typeof(LineDoorController).GetField("doorShouldOpenImmediatelyOnEnable", BindingFlags.Instance | BindingFlags.NonPublic); fieldInfo.SetValue(__instance, requirement.Check()); __instance.chains.Clear(); } } } } [HarmonyPatch(typeof(LevelLoader), nameof(LevelLoader.MovePlayerIntoNewScene))] static class LevelLoaderMovePlayerIntoNewScenePatch { static void Postfix(LevelSystems newLevel) { Plugin.slotSave.VisitedScenes.Add(newLevel.levelName); if (GameData.listenersByScene.TryGetValue(newLevel.levelName, out var listeners)) { GameState.EvaluateGameStateListeners(listeners); } } } [HarmonyPatch(typeof(DarkModeCollapsedCubeWorldGrow), nameof(DarkModeCollapsedCubeWorldGrow.OnChainFillComplete))] static class DarkModeCollapsedCubeWorldGrowOnChainFillCompletePatch { static bool Prefix() { return false; } } [HarmonyPatch(typeof(DarkModeCollapsedCubeWorldGrow), nameof(DarkModeCollapsedCubeWorldGrow.OnLevelEnable))] static class DarkModeCollapsedCubeWorldGrowOnLevelEnablePatch { static void Prefix(DarkModeCollapsedCubeWorldGrow __instance) { SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance); if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription) && sceneDescription.worldGrows.TryGetValue(sir.index, out var requirement) && requirement.Check()) { FieldInfo fieldInfo = typeof(DarkModeCollapsedCubeWorldGrow).GetField("m_grown", BindingFlags.Instance | BindingFlags.NonPublic); fieldInfo.SetValue(__instance, true); } } } [HarmonyPatch(typeof(DarkModeCollider), nameof(DarkModeCollider.OnLevelUpdate))] static class DarkModeColliderOnLevelUpdatePatch { static void Postfix(DarkModeCollider __instance) { if (__instance.gameObject.scene.name == "World_000_Optimized") { __instance.gameObject.SetActive(false); } } } }