summary refs log blame commit diff stats
path: root/GameplayPatches.cs
blob: bdcbcae5200fe018979b5b5c3b93db994d8033ad (plain) (tree)
1
2
3
                        
                  












                                                                                          

                                                                        
                     




                                                                                 



















                                                                                               













                                                                                               
             
                       
             
                                                             















                                                                                               
                                                           
















                                                                                            













                                                                                            
             
                       
             














                                                                                                
             
                       
             
                                                       








                                                                                       
                                                                           




                                                                                                   
                                                                  
















                                                                                               
                                                                                                       














                                                                                          











                                                                                                                                                                       
 
                                                  








                                                                                 
                                                                             
                                                                                          
                                                      

                                                                                 
                                                                                          
                                                                                       












                                                                                                                                                                       
 
                                                  












                                                                                             
                                                                                    





















                                                                                                                      
                                                                




                                                                                                                                                 
 














































                                                                                                  









                                                                                    


































                                                                                                                   
 
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;
        }
    }
}