using HarmonyLib;
using System.Reflection;
using UnityEngine;
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))
{
Requirement.Decision decision = requirement.Check();
if (decision != Requirement.Decision.Maybe)
{
bool shouldOpen = (decision == Requirement.Decision.Yes);
if (open != shouldOpen)
{
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;
}
Plugin.slotSave.ActivatedButtons[sir] = setPressed;
GameState.EvaluateGameStateListeners(listeners);
}
}
[HarmonyPatch(typeof(ButtonLineActivator), "ForceButtonPressedImmediately")]
static class ButtonLineActivatorForceButtonPressedImmediatelyPatch
{
static void Prefix(ButtonLineActivator __instance, bool _pressed)
{
SceneItemReference sir = GameState.GetButtonSceneReference(__instance);
Plugin.Logger.LogInfo($"Button {sir} forced state {_pressed}");
if (!GameData.listenersByButton.TryGetValue(sir, out GameStateListeners listeners))
{
return;
}
Plugin.slotSave.ActivatedButtons[sir] = _pressed;
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;
}
Plugin.slotSave.ActivatedSockets[sir] = active;
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;
}
Plugin.slotSave.ActivatedPads[sir] = setActive;
GameState.EvaluateGameStateListeners(listeners);
}
}
[HarmonyPatch(typeof(CubeLineActivator), "ForceActivatorToTurnOnAsCorrectCubeOnSwitch")]
static class CubeLineActivatorForceActivatorToTurnOnAsCorrectCubeOnSwitchPatch
{
static void Prefix(CubeLineActivator __instance)
{
SceneItemReference sir = GameState.GetPadSceneReference(__instance);
Plugin.Logger.LogInfo($"Pad {sir} forced on");
if (!GameData.listenersByPad.TryGetValue(sir, out GameStateListeners listeners))
{
return;
}
Plugin.slotSave.ActivatedPads[sir] = true;
GameState.EvaluateGameStateListeners(listeners);
}
}
[HarmonyPatch(typeof(CubeLineActivator), "ForceActivatorToTurnOffAsCorrectCubeNotOnSwitch")]
static class CubeLineActivatorForceActivatorToTurnOffAsCorrectCubeNotOnSwitchPatch
{
static void Prefix(CubeLineActivator __instance)
{
SceneItemReference sir = GameState.GetPadSceneReference(__instance);
Plugin.Logger.LogInfo($"Pad {sir} forced off");
if (!GameData.listenersByPad.TryGetValue(sir, out GameStateListeners listeners))
{
return;
}
Plugin.slotSave.ActivatedPads[sir] = false;
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;
}
Plugin.slotSave.ActivatedWaterwheels[sir] = setActive;
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;
}
Plugin.slotSave.ActivatedSpheres[sir] = (newState == SphereController.State.AtDestination);
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))
{
Requirement.Decision decision = requirement.Check();
if (decision != Requirement.Decision.Maybe)
{
bool shouldOpen = (decision == Requirement.Decision.Yes);
FieldInfo fieldInfo = typeof(LineDoorController).GetField("doorShouldOpenImmediatelyOnEnable", BindingFlags.Instance | BindingFlags.NonPublic);
fieldInfo.SetValue(__instance, shouldOpen);
FieldInfo animatorInfo = typeof(LineDoorController).GetField("m_animator", BindingFlags.Instance | BindingFlags.NonPublic);
Animator animator = (Animator)animatorInfo.GetValue(__instance);
AnimatorExt.PlayDoorStateThenDisable(animator, __instance.DoorOpenAnimationString, shouldOpen ? 1f : -1f, true);
__instance.chains.Clear();
}
}
}
}
}
[HarmonyPatch(typeof(LineDoorController), nameof(LineDoorController.OnLoad))]
static class LineDoorControllerOnLoadPatch
{
static void Prefix(LineDoorController __instance)
{
//Plugin.Logger.LogInfo("LineDoorControllerOnLoadPatch entered");
SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance);
//Plugin.Logger.LogInfo($"Got sir {sir}");
if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription))
{
//Plugin.Logger.LogInfo($"{sceneDescription.doors.Count} doors in scene");
if (sceneDescription.doors.TryGetValue(sir.index, out var requirement))
{
//Plugin.Logger.LogInfo($"Found req {requirement}");
Requirement.Decision decision = requirement.Check();
if (decision != Requirement.Decision.Maybe)
{
bool shouldOpen = (decision == Requirement.Decision.Yes);
FieldInfo fieldInfo = typeof(LineDoorController).GetField("doorShouldOpenImmediatelyOnEnable", BindingFlags.Instance | BindingFlags.NonPublic);
fieldInfo.SetValue(__instance, shouldOpen);
FieldInfo animatorInfo = typeof(LineDoorController).GetField("m_animator", BindingFlags.Instance | BindingFlags.NonPublic);
Animator animator = (Animator)animatorInfo.GetValue(__instance);
AnimatorExt.PlayDoorStateThenDisable(animator, __instance.DoorOpenAnimationString, shouldOpen ? 1f : -1f, true);
__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))
{
Plugin.Logger.LogInfo($"Evaluating for scene {newLevel.levelName}");
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() == Requirement.Decision.Yes)
{
FieldInfo fieldInfo = typeof(DarkModeCollapsedCubeWorldGrow).GetField("m_grown", BindingFlags.Instance | BindingFlags.NonPublic);
fieldInfo.SetValue(__instance, true);
}
}
}
[HarmonyPatch(typeof(SolidStateController), nameof(SolidStateController.OnChainFillComplete))]
static class SolidStateControllerOnChainFillCompletePatch
{
static bool Prefix(SolidStateController __instance)
{
SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance);
if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription))
{
if (sceneDescription.smokeWalls.TryGetValue(sir.index, out var requirement))
{
Requirement.Decision decision = requirement.Check();
if (decision == Requirement.Decision.No)
{
return false;
}
}
}
return true;
}
}
[HarmonyPatch(typeof(SolidStateController), nameof(SolidStateController.OnUnfilled))]
static class SolidStateControllerOnUnfilledPatch
{
static bool Prefix(SolidStateController __instance)
{
SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance);
if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription))
{
if (sceneDescription.smokeWalls.TryGetValue(sir.index, out var requirement))
{
Requirement.Decision decision = requirement.Check();
if (decision == Requirement.Decision.Yes)
{
return false;
}
}
}
return 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);
}
}
}
[HarmonyPatch(typeof(MiniatureWorldButton), "IInteractable.OnLookAt")]
static class MiniatureWorldButtonOnLookAtPatch
{
static bool Prefix(MiniatureWorldButton __instance, ref bool __result)
{
__result =
!GameManager.DarkModeController.IsDarkMode &&
GameManager.MandalaManager.LevelsActiveInMandala.Contains(__instance.LevelToGoIntoName) &&
__instance.myMandalaController.myGravityDirection == GameManager.PlayerController.gravityDirection;
return false;
}
}
[HarmonyPatch(typeof(MiniatureWorldButton), "IInteractable.CanInteract")]
static class MiniatureWorldButtonCanInteractPatch
{
static bool Prefix(MiniatureWorldButton __instance, ref bool __result)
{
__result =
!GameManager.DarkModeController.IsDarkMode &&
GameManager.MandalaManager.LevelsActiveInMandala.Contains(__instance.LevelToGoIntoName) &&
__instance.myMandalaController.myGravityDirection == GameManager.PlayerController.gravityDirection;
return false;
}
}
[HarmonyPatch(typeof(MiniatureWorldButton), "IInteractable.OnInteract")]
static class MiniatureWorldButtonOnInteractPatch
{
static bool Prefix(MiniatureWorldButton __instance)
{
__instance.myMandalaController.ShrinkIntoLevel(__instance);
return false;
}
}
}