Ejemplo n.º 1
0
        private static void CheckFireball(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self)
        {
            // Wall Impact state doesn't exist in shade soul control
            // Fireballs get recycled so we've gotta check for the state this method adds as well
            if (self.FsmName != "Fireball Control" || self.GetState("Wall Impact") == null || self.GetState("Idle (No Collision)") != null)
            {
                orig(self);
                return;
            }

            // Store the terrain checker reference, prevent it from being enabled
            GameObject terrainChecker = self.GetAction <ActivateGameObject>("Pause", 3).gameObject.GameObject.Value;

            self.GetState("Pause").RemoveAction(3);

            // Create a new state before the regular idle
            FsmState idleNoCol = self.CopyState("R", "Idle (No Collision)");

            idleNoCol.RemoveAction(0);

            self.GetState("L").ChangeTransition("FINISHED", "Idle (No Collision)");
            self.GetState("R").ChangeTransition("FINISHED", "Idle (No Collision)");

            idleNoCol.AddTransition("FINISHED", "Idle");

            // New state needs to start the fireball moving
            idleNoCol.AddAction(new SetVelocity2d {
                gameObject = new FsmOwnerDefault(),
                vector     = Vector2.zero,
                x          = self.FsmVariables.FindFsmFloat("Velocity"),
                y          = 0,
                everyFrame = false
            });

            // Small waiting period before proceeding to the old idle state
            idleNoCol.AddAction(new Wait {
                time        = NO_COLLISION_TIME,
                finishEvent = FsmEvent.FindEvent("FINISHED"),
                realTime    = false
            });

            FsmState idle = self.GetState("Idle");

            // Idle state needs to activate the collision now
            idle.InsertAction(0, new ActivateGameObject {
                gameObject = new FsmOwnerDefault {
                    GameObject  = terrainChecker,
                    OwnerOption = OwnerDefaultOption.SpecifyGameObject
                },
                activate    = true,
                recursive   = false,
                resetOnExit = false,
                everyFrame  = false
            });

            // Account for the additional waiting time before Idle
            idle.GetAction <Wait>(8).time.Value -= NO_COLLISION_TIME;

            orig(self);
        }
Ejemplo n.º 2
0
        public override void Process(string scene, UnityEngine.Object changeObj)
        {
            if (scene != _sceneName || !(changeObj is PlayMakerFSM fsm) || fsm.FsmName != _fsmName ||
                fsm.gameObject.name != _objectName)
            {
                return;
            }

            SendEvent sender = new SendEvent
            {
                eventTarget = new FsmEventTarget
                {
                    target      = FsmEventTarget.EventTarget.BroadcastAll,
                    excludeSelf = true
                },
                sendEvent  = FsmEvent.FindEvent(_eventName) ?? new FsmEvent(_eventName),
                delay      = 0,
                everyFrame = false
            };

            foreach (string stateName in _stateNames)
            {
                if (fsm.GetState(stateName) is FsmState state)
                {
                    state.AddFirstAction(sender);
                }
            }
        }
Ejemplo n.º 3
0
    public FsmEvent AddEvent(string eventName)
    {
        events.Add(eventName);
        FsmEvent fsmEvent = FsmEvent.FindEvent(eventName) ?? FsmEvent.GetFsmEvent(eventName);

        fsmEvent.IsGlobal = true;
        return(fsmEvent);
    }
Ejemplo n.º 4
0
 private static void PatchWaterFSM(PlayMakerFSM fsm)
 {
     fsm.GetState("Enter").AddAction(new SendEvent
     {
         eventTarget = FsmEventTarget.Self,
         sendEvent   = FsmEvent.FindEvent("FINISHED"),
         delay       = 0,
         everyFrame  = false
     });
 }
Ejemplo n.º 5
0
        public override void OnEnter()
        {
            eventTarget              = new FsmEventTarget();
            eventTarget.target       = FsmEventTarget.EventTarget.FSMComponent;
            eventTarget.fsmComponent = target.Value as PlayMakerFSM;

            if (delay.Value < 0.001f)
            {
                Fsm.Event(eventTarget, sendEvent.Value);
                if (!everyFrame)
                {
                    Finish();
                }
            }
            else
            {
                delayedEvent = Fsm.DelayedEvent(eventTarget, FsmEvent.FindEvent(sendEvent.Value), delay.Value);
            }
        }
        public static void SceneChanged(Scene newScene)
        {
            switch (newScene.name)
            {
            case SceneNames.Room_temple:
                // Handle completion restrictions
                ProcessRestrictions();
                break;

            case SceneNames.Room_Final_Boss_Core when AreaRando.Instance.Settings.AllBosses:
                // Trigger Radiance fight without requiring dream nail hit
                // Prevents skipping the fight in all bosses mode
                PlayMakerFSM dreamFSM      = FSMUtility.LocateFSM(newScene.FindGameObject("Dream Enter"), "Control");
                SendEvent    enterRadiance = new SendEvent
                {
                    eventTarget = new FsmEventTarget
                    {
                        target       = FsmEventTarget.EventTarget.FSMComponent,
                        fsmComponent = dreamFSM
                    },
                    sendEvent  = FsmEvent.FindEvent("NAIL HIT"),
                    delay      = 0,
                    everyFrame = false
                };

                PlayMakerFSM bossFSM =
                    FSMUtility.LocateFSM(newScene.FindGameObject("Hollow Knight Boss"), "Control");
                bossFSM.GetState("H Collapsed").AddAction(enterRadiance);

                break;

            case SceneNames.Cliffs_06 when AreaRando.Instance.Settings.AllBosses:
                // Prevent banish ending in all bosses
                Object.Destroy(GameObject.Find("Brumm Lantern NPV"));
                break;
            }
        }
        /*
         * Room changes required for the randomizer to function on any mode
         * For example, removing certain vanilla item locations which can't be handled by RandomizerAction
         */

        public static void ApplyRandomizerChanges(Scene newScene)
        {
            switch (newScene.name)
            {
            // Prevent Grimm encounter which gives Grimmchild
            case SceneNames.Grimm_Main_Tent:
                PlayerData.instance.metGrimm = true;
                break;

            // Prevent reading tablet which gives completion percentage
            case SceneNames.Room_Final_Boss_Atrium:
                GameObject.Find("Tut_tablet_top").LocateMyFSM("Inspection").GetState("Init").ClearTransitions();
                break;

            // Removes the prompt to donate to the 3000 geo fountain in Basin
            case SceneNames.Abyss_04:
                Object.Destroy(GameObject.Find("Fountain Donation"));
                break;

            // Opens lifeblood door in Abyss with any amount of blue health
            case SceneNames.Abyss_06_Core:
                if (PlayerData.instance.healthBlue > 0 || PlayerData.instance.joniHealthBlue > 0 || GameManager.instance.entryGateName == "left1")
                {
                    PlayerData.instance.SetBoolInternal("blueVineDoor", true);
                    PlayMakerFSM BlueDoorFSM = GameObject.Find("Blue Door").LocateMyFSM("Control");
                    BlueDoorFSM.GetState("Init").RemoveTransitionsTo("Got Charm");
                }
                break;

            // Removes trigger for Void Heart sequence
            case SceneNames.Abyss_15:
                GameObject.Find("Dream Enter Abyss").LocateMyFSM("Control").GetState("Init").RemoveTransitionsTo("Idle");
                GameObject.Find("Dream Enter Abyss").LocateMyFSM("Control").GetState("Init").AddTransition("FINISHED", "Inactive");
                break;

            // Automatically unlock Godseeker and add an action to the Godtuner spot to remove simple key on purchase
            case SceneNames.GG_Waterways:
                PlayerData.instance.SetBool("godseekerUnlocked", true);
                if (GameObject.Find("Randomizer Shiny") != null)
                {
                    PlayMakerFSM godtuner = GameObject.Find("Randomizer Shiny").LocateMyFSM("Shiny Control");
                    godtuner.GetState(godtuner.GetState("Charm?").Transitions.First(t => t.EventName == "YES").ToState).AddFirstAction(new RandomizerExecuteLambda(() => PlayerData.instance.DecrementInt("simpleKeys")));
                }
                break;

            // Spawns mawlek shard out of bounds and moves it inbounds when mawlek is killed
            case SceneNames.Crossroads_09:
                if (GameObject.Find("Randomizer Shiny") is GameObject mawlekShard)
                {
                    mawlekShard.transform.SetPositionY(100f);
                    IEnumerator mawlekDead()
                    {
                        yield return(new WaitUntil(() => PlayerData.instance.killedMawlek));

                        mawlekShard.transform.SetPositionY(10f);
                        mawlekShard.transform.SetPositionX(61.5f);
                    }

                    GameManager.instance.StartCoroutine(mawlekDead());
                }
                break;

            // Removes Grubfather rewards corresponding to randomizer items
            case SceneNames.Crossroads_38:
                Object.Destroy(GameObject.Find("Reward 5"));      //Mask
                Object.Destroy(GameObject.Find("Reward 10"));     //Charm
                Object.Destroy(GameObject.Find("Reward 16"));     //Rancid Egg
                Object.Destroy(GameObject.Find("Reward 23"));     //Relic
                Object.Destroy(GameObject.Find("Reward 31"));     //Pale Ore
                Object.Destroy(GameObject.Find("Reward 38"));     //Relic
                Object.Destroy(GameObject.Find("Reward 46"));     //Charm
                break;

            // Remove gate from Ancestral Mound
            case SceneNames.Crossroads_ShamanTemple:
                Object.Destroy(GameObject.Find("Bone Gate"));
                break;

            // Remove Beast's Den hardsave, allow rear access from entrance, destroy Herrah
            case SceneNames.Deepnest_Spider_Town:
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Deepnest_Spider_Town",
                    id             = "Collapser Small (12)",
                    activated      = true,
                    semiPersistent = false
                });

                FsmState denHardSave = GameObject.Find("RestBench Spider").LocateMyFSM("Fade").GetState("Land");
                denHardSave.RemoveActionsOfType <CallMethodProper>();
                denHardSave.RemoveActionsOfType <SendMessage>();
                denHardSave.RemoveActionsOfType <SetPlayerDataBool>();

                Object.Destroy(GameObject.Find("Dreamer Hegemol"));
                Object.Destroy(GameObject.Find("Dream Enter"));
                Object.Destroy(GameObject.Find("Dream Impact"));
                Object.Destroy(GameObject.Find("Shield"));
                break;

            // Edits Dream Nail location to change scene to seer
            case SceneNames.Dream_Nailcollection:
                FSMUtility.LocateFSM(GameObject.Find("Randomizer Shiny"), "Shiny Control").GetState("Finish")
                .AddAction(new RandomizerChangeScene("RestingGrounds_07", "right1"));
                break;

            // Edit Hornet room to open gates after boss fight, and removes dreamer cutscene
            case SceneNames.Fungus1_04:
                foreach (PlayMakerFSM childFSM in GameObject.Find("Cloak Corpse")
                         .GetComponentsInChildren <PlayMakerFSM>(true))
                {
                    if (childFSM.FsmName == "Shiny Control")
                    {
                        SendEvent openGate = new SendEvent
                        {
                            eventTarget = new FsmEventTarget
                            {
                                target      = FsmEventTarget.EventTarget.BroadcastAll,
                                excludeSelf = true
                            },
                            sendEvent  = FsmEvent.FindEvent("BG OPEN"),
                            delay      = 0,
                            everyFrame = false
                        };
                        childFSM.GetState("Destroy").AddFirstAction(openGate);
                        childFSM.GetState("Finish").AddFirstAction(openGate);

                        break;
                    }
                }

                ObjectDestroyer.Destroy("Dreamer Scene 1");
                ObjectDestroyer.Destroy("Hornet Saver");
                ObjectDestroyer.Destroy("Cutscene Dreamer");
                ObjectDestroyer.Destroy("Dream Scene Activate");

                if (!Ref.PD.hornet1Defeated)
                {
                    Object.Destroy(FSMUtility.LocateFSM(GameObject.Find("Camera Locks Boss"), "FSM"));
                }
                break;

            // Make city crest gate openable infinite times and not hard save
            case SceneNames.Fungus2_21:
                FSMUtility.LocateFSM(GameObject.Find("City Gate Control"), "Conversation Control")
                .GetState("Activate").RemoveActionsOfType <SetPlayerDataBool>();

                FsmState gateSlam = FSMUtility.LocateFSM(GameObject.Find("Ruins_gate_main"), "Open")
                                    .GetState("Slam");
                gateSlam.RemoveActionsOfType <SetPlayerDataBool>();
                gateSlam.RemoveActionsOfType <CallMethodProper>();
                gateSlam.RemoveActionsOfType <SendMessage>();
                break;

            // Removes Leg Eater dialogue tree, preventing him from dying
            case SceneNames.Fungus2_26:
                PlayMakerFSM legEater       = FSMUtility.LocateFSM(GameObject.Find("Leg Eater"), "Conversation Control");
                FsmState     legEaterChoice = legEater.GetState("Convo Choice");
                legEaterChoice.RemoveTransitionsTo("Convo 1");
                legEaterChoice.RemoveTransitionsTo("Convo 2");
                legEaterChoice.RemoveTransitionsTo("Convo 3");
                legEaterChoice.RemoveTransitionsTo("Infected Crossroad");
                legEaterChoice.RemoveTransitionsTo("Bought Charm");
                legEaterChoice.RemoveTransitionsTo("Gold Convo");
                legEaterChoice.RemoveTransitionsTo("All Gold");
                legEaterChoice.RemoveTransitionsTo("Ready To Leave");
                legEater.GetState("All Gold?").RemoveTransitionsTo("No Shop");
                Ref.PD.legEaterLeft = false;
                break;

            // Destroy Monomon and remove Quirrel encounter
            case SceneNames.Fungus3_archive_02:
                PlayerData.instance.SetBool("summonedMonomon", true);
                Object.Destroy(GameObject.Find("Inspect Region"));
                Object.Destroy(GameObject.Find("Quirrel Wounded"));
                Object.Destroy(GameObject.Find("Quirrel"));
                Object.Destroy(GameObject.Find("Monomon"));
                Object.Destroy(GameObject.Find("Dream Enter"));
                Object.Destroy(GameObject.Find("Dream Impact"));
                Object.Destroy(GameObject.Find("Shield"));
                break;

            // Make tolls always interactable, in the rare case that lantern is not randomized but RG access through the dark room is expected
            case SceneNames.Mines_33:
                if (RandomizerMod.Instance.Settings.DarkRooms && !RandomizerMod.Instance.Settings.RandomizeKeys)
                {
                    GameObject[] tolls = new GameObject[] { GameObject.Find("Toll Gate Machine"), GameObject.Find("Toll Gate Machine (1)") };
                    foreach (GameObject toll in tolls)
                    {
                        Object.Destroy(FSMUtility.LocateFSM(toll, "Disable if No Lantern"));
                    }
                }
                break;

            // Move Seer back to make room for items, and remove essence rewards
            case SceneNames.RestingGrounds_07:
                GameObject.Find("Dream Moth").transform.Translate(new Vector3(-5f, 0f));

                PlayMakerFSM moth = FSMUtility.LocateFSM(GameObject.Find("Dream Moth"), "Conversation Control");

                PlayerData.instance.dreamReward1 = true;
                moth.FsmVariables.GetFsmBool("Got Reward 1").Value = true;      //Relic
                PlayerData.instance.dreamReward3 = true;
                moth.FsmVariables.GetFsmBool("Got Reward 3").Value = true;      //Pale Ore
                PlayerData.instance.dreamReward4 = true;
                moth.FsmVariables.GetFsmBool("Got Reward 4").Value = true;      //Charm
                PlayerData.instance.dreamReward5 = true;
                moth.FsmVariables.GetFsmBool("Got Reward 5").Value = true;      //Vessel Fragment
                PlayerData.instance.dreamReward5b = true;
                moth.FsmVariables.GetFsmBool("Got Reward 5b").Value = true;     //Skill
                PlayerData.instance.dreamReward6 = true;
                moth.FsmVariables.GetFsmBool("Got Reward 6").Value = true;      //Relic
                PlayerData.instance.dreamReward7 = true;
                moth.FsmVariables.GetFsmBool("Got Reward 7").Value = true;      //Mask Shard
                PlayerData.instance.dreamReward8 = true;
                moth.FsmVariables.GetFsmBool("Got Reward 8").Value = true;      //Skill
                break;

            // Make Sly pickup send Sly back upstairs -- warps player out to prevent resulting softlock from trying to enter the shop from a missing transition
            case SceneNames.Room_Sly_Storeroom:
                FsmState slyFinish = FSMUtility.LocateFSM(GameObject.Find("Randomizer Shiny"), "Shiny Control").GetState("Finish");
                slyFinish.AddAction(new RandomizerSetBool("SlyCharm", true));
                slyFinish.AddAction(new RandomizerChangeScene("Town", "door_sly"));
                break;

            // Many changes to make the desolate dive pickup work properly
            case SceneNames.Ruins1_24:
                // Stop spell container from destroying itself
                PlayMakerFSM quakePickup = FSMUtility.LocateFSM(GameObject.Find("Quake Pickup"), "Pickup");
                quakePickup.GetState("Idle").RemoveActionsOfType <IntCompare>();
                foreach (PlayMakerFSM childFSM in quakePickup.gameObject.GetComponentsInChildren <PlayMakerFSM>(true))
                {
                    if (childFSM.FsmName == "Shiny Control")
                    {
                        // Make spell container spawn shiny instead
                        quakePickup.GetState("Appear").GetActionsOfType <ActivateGameObject>()[1].gameObject
                        .GameObject.Value = childFSM.gameObject;

                        // Make shiny open gates on pickup/destroy
                        SendEvent openGate = new SendEvent
                        {
                            eventTarget = new FsmEventTarget
                            {
                                target      = FsmEventTarget.EventTarget.BroadcastAll,
                                excludeSelf = true
                            },
                            sendEvent  = FsmEvent.FindEvent("BG OPEN"),
                            delay      = 0,
                            everyFrame = false
                        };
                        childFSM.GetState("Destroy").AddFirstAction(openGate);
                        childFSM.GetState("Finish").AddFirstAction(openGate);
                        break;
                    }
                }

                // Stop the weird invisible floor from appearing if dive has been obtained
                if (Ref.PD.quakeLevel > 0)
                {
                    Object.Destroy(GameObject.Find("Roof Collider Battle"));
                }

                // Change battle gate to be destroyed if Soul Master is dead instead of it the player has quake
                FsmState checkQuake = FSMUtility.LocateFSM(GameObject.Find("Battle Gate (1)"), "Destroy if Quake").GetState("Check");
                checkQuake.RemoveActionsOfType <FsmStateAction>();
                checkQuake.AddAction(new RandomizerBoolTest(nameof(PlayerData.killedMageLord), null, "DESTROY", true));
                break;

            // Prevent simple key softlocks
            case SceneNames.Ruins2_04:
                FsmState hotSpringsKey = GameObject.Find("Inspect").LocateMyFSM("Conversation Control").GetState("Got Key?");
                hotSpringsKey.RemoveActionsOfType <IntCompare>();
                hotSpringsKey.AddAction(new RandomizerExecuteLambda(() =>
                {
                    if (GameManager.instance.GetPlayerDataInt("simpleKeys") > 1 || (PlayerData.instance.openedWaterwaysManhole && GameManager.instance.GetPlayerDataInt("simpleKeys") > 0))
                    {
                        PlayMakerFSM.BroadcastEvent("YES");
                    }
                    else
                    {
                        PlayMakerFSM.BroadcastEvent("NO");
                    }
                }));
                break;

            // Destroy Lurien
            case SceneNames.Ruins2_Watcher_Room:
                Object.Destroy(GameObject.Find("Dreamer Lurien"));
                Object.Destroy(GameObject.Find("Dream Enter"));
                Object.Destroy(GameObject.Find("Dream Impact"));
                Object.Destroy(GameObject.Find("Shield"));
                break;

            // Open all colosseum trials
            case SceneNames.Room_Colosseum_01:
                PlayerData.instance.colosseumBronzeOpened = true;
                PlayerData.instance.colosseumSilverOpened = true;
                PlayerData.instance.colosseumGoldOpened   = true;
                GameObject.Find("Silver Trial Board").LocateMyFSM("Conversation Control").GetState("Hero Anim").ClearTransitions();
                GameObject.Find("Silver Trial Board").LocateMyFSM("Conversation Control").GetState("Hero Anim").AddTransition("FINISHED", "Box Up YN");
                GameObject.Find("Gold Trial Board").LocateMyFSM("Conversation Control").GetState("Hero Anim").ClearTransitions();
                GameObject.Find("Gold Trial Board").LocateMyFSM("Conversation Control").GetState("Hero Anim").AddTransition("FINISHED", "Box Up YN");
                break;

            // Destroy Grey Mourner after the flower has been delivered
            case SceneNames.Room_Mansion:
                if (PlayerData.instance.xunFlowerGiven)
                {
                    PlayerData.instance.xunRewardGiven = true;
                }
                break;

            // Removes King's Brand cutscene trigger
            case SceneNames.Room_Wyrm:
                Object.Destroy(GameObject.Find("Avalanche End"));
                break;

            // Open Colosseum gates after picking up resp. items
            case SceneNames.Room_Colosseum_Bronze:
                GameObject.Find("Colosseum Manager").LocateMyFSM("Geo Pool").GetState("Open Gates").AddFirstAction(new RandomizerSetBool("colosseumBronzeCompleted", true, true));
                break;

            case SceneNames.Room_Colosseum_Silver:
                GameObject.Find("Colosseum Manager").LocateMyFSM("Geo Pool").GetState("Open Gates").AddFirstAction(new RandomizerSetBool("colosseumSilverCompleted", true, true));
                break;

            // Prevent simple key softlocks
            case SceneNames.Town:
                FsmState jijiKey = GameObject.Find("Jiji Door").LocateMyFSM("Conversation Control").GetState("Key?");
                jijiKey.RemoveActionsOfType <GetPlayerDataInt>();
                jijiKey.RemoveActionsOfType <IntCompare>();
                jijiKey.AddAction(new RandomizerExecuteLambda(() =>
                {
                    if (GameManager.instance.GetPlayerDataInt("simpleKeys") > 1 || (PlayerData.instance.openedWaterwaysManhole && GameManager.instance.GetPlayerDataInt("simpleKeys") > 0))
                    {
                        PlayMakerFSM.BroadcastEvent("KEY");
                    }
                    else
                    {
                        PlayMakerFSM.BroadcastEvent("NOKEY");
                    }
                }));
                break;
            }
        }
Ejemplo n.º 8
0
 public static void AddTransition(this PMFSM fsm, string stateName, string fsmEvent, string toState)
 {
     AddTransition(fsm.GetState(stateName), FsmEvent.FindEvent(fsmEvent), fsm.GetState(toState));
 }
Ejemplo n.º 9
0
 public static void AddTransition(this FsmState state, string fsmEvent, string toState)
 {
     AddTransition(state, FsmEvent.FindEvent(fsmEvent), state.Fsm.GetState(toState));
 }
Ejemplo n.º 10
0
 public static void AddTransition(this FsmState state, string fsmEvent, FsmState toState)
 {
     AddTransition(state, FsmEvent.FindEvent(fsmEvent), toState);
 }
        private static void ApplyGeneralChanges(Scene newScene)
        {
            switch (newScene.name)
            {
            case SceneNames.Crossroads_38:
                // Faster daddy
                PlayMakerFSM grubDaddy = FSMUtility.LocateFSM(GameObject.Find("Grub King"), "King Control");
                grubDaddy.GetState("Final Reward?").RemoveTransitionsTo("Recover");
                grubDaddy.GetState("Final Reward?").AddTransition("FINISHED", "Recheck");
                grubDaddy.GetState("Recheck").RemoveTransitionsTo("Gift Anim");
                grubDaddy.GetState("Recheck").AddTransition("FINISHED", "Activate Reward");

                // Terrible code to make a terrible fsm work not terribly
                int geoTotal = 0;
                grubDaddy.GetState("All Given").AddAction(new RandomizerAddGeo(grubDaddy.gameObject, 0, true));
                grubDaddy.GetState("Recheck").AddAction(new RandomizerExecuteLambda(() =>
                                                                                    grubDaddy.GetState("All Given").GetActionsOfType <RandomizerAddGeo>()[0].SetGeo(geoTotal)));

                foreach (PlayMakerFSM grubFsm in grubDaddy.gameObject.GetComponentsInChildren <PlayMakerFSM>(true))
                {
                    if (grubFsm.FsmName == "grub_reward_geo")
                    {
                        FsmState grubGeoState = grubFsm.GetState("Remaining?");
                        int      geo          = grubGeoState.GetActionsOfType <IntCompare>()[0].integer1.Value;

                        grubGeoState.RemoveActionsOfType <FsmStateAction>();
                        grubGeoState.AddAction(new RandomizerExecuteLambda(() => geoTotal += geo));
                        grubGeoState.AddTransition("FINISHED", "End");
                    }
                }

                break;

            case SceneNames.Deepnest_East_16:
                // Great Hopper%
                GameObject hopper1 = newScene.FindGameObject("Giant Hopper");
                GameObject hopper2 = newScene.FindGameObject("Giant Hopper (1)");

                for (int i = 0; i < 10; i++)
                {
                    GameObject newHopper1 = Object.Instantiate(hopper1, hopper1.transform.parent);
                    GameObject newHopper2 = Object.Instantiate(hopper2, hopper2.transform.parent);

                    // Don't want people abusing the easter egg as a geo farm
                    HealthManager hopper1HM = newHopper1.GetComponent <HealthManager>();
                    hopper1HM.SetGeoSmall(0);
                    hopper1HM.SetGeoMedium(0);
                    hopper1HM.SetGeoLarge(0);

                    HealthManager hopper2HM = newHopper2.GetComponent <HealthManager>();
                    hopper2HM.SetGeoSmall(0);
                    hopper2HM.SetGeoMedium(0);
                    hopper2HM.SetGeoLarge(0);

                    Vector3 hopper1Pos = newHopper1.transform.localPosition;
                    hopper1Pos = new Vector3(
                        hopper1Pos.x + Rnd.Next(5),
                        hopper1Pos.y,
                        hopper1Pos.z);
                    newHopper1.transform.localPosition = hopper1Pos;

                    Vector3 hopper2Pos = newHopper2.transform.localPosition;
                    hopper2Pos = new Vector3(
                        hopper2Pos.x + Rnd.Next(5) - 4,
                        hopper2Pos.y,
                        hopper2Pos.z);
                    newHopper2.transform.localPosition = hopper2Pos;
                }

                break;

            case SceneNames.Fungus1_04:
                // Open gates after Hornet fight
                foreach (PlayMakerFSM childFSM in GameObject.Find("Cloak Corpse")
                         .GetComponentsInChildren <PlayMakerFSM>(true))
                {
                    if (childFSM.FsmName == "Shiny Control")
                    {
                        SendEvent openGate = new SendEvent
                        {
                            eventTarget = new FsmEventTarget
                            {
                                target      = FsmEventTarget.EventTarget.BroadcastAll,
                                excludeSelf = true
                            },
                            sendEvent  = FsmEvent.FindEvent("BG OPEN"),
                            delay      = 0,
                            everyFrame = false
                        };
                        childFSM.GetState("Destroy").AddFirstAction(openGate);
                        childFSM.GetState("Finish").AddFirstAction(openGate);

                        break;
                    }
                }

                // Destroy everything relating to the dreamer cutscene
                // This stuff is in another scene and doesn't exist immediately, so I can't use Object.Destroy
                ObjectDestroyer.Destroy("Dreamer Scene 1");
                ObjectDestroyer.Destroy("Hornet Saver");
                ObjectDestroyer.Destroy("Cutscene Dreamer");
                ObjectDestroyer.Destroy("Dream Scene Activate");

                // Fix the camera lock zone by removing the FSM that destroys it
                if (!Ref.PD.hornet1Defeated)
                {
                    Object.Destroy(FSMUtility.LocateFSM(GameObject.Find("Camera Locks Boss"), "FSM"));
                }

                break;

            case SceneNames.Mines_35:
                // Make descending dark spikes pogoable like on old patches
                foreach (NonBouncer nonBounce in Object.FindObjectsOfType <NonBouncer>())
                {
                    if (nonBounce.gameObject.name.StartsWith("Spike Collider"))
                    {
                        nonBounce.active = false;
                        nonBounce.gameObject.AddComponent <RandomizerTinkEffect>();
                    }
                }

                break;

            case SceneNames.RestingGrounds_04:
                // Make dream nail plaque not take 20 years to activate
                FsmState dreamerPlaqueInspect = FSMUtility
                                                .LocateFSM(GameObject.Find("Dreamer Plaque Inspect"), "Conversation Control")
                                                .GetState("Hero Anim");
                dreamerPlaqueInspect.RemoveActionsOfType <ActivateGameObject>();
                dreamerPlaqueInspect.RemoveTransitionsTo("Fade Up");
                dreamerPlaqueInspect.AddTransition("FINISHED", "Map Msg?");

                PlayMakerFSM dreamerScene2 = FSMUtility.LocateFSM(GameObject.Find("Dreamer Scene 2"), "Control");
                dreamerScene2.GetState("Take Control").RemoveTransitionsTo("Blast");
                dreamerScene2.GetState("Take Control").AddTransition("FINISHED", "Fade Out");
                dreamerScene2.GetState("Fade Out").RemoveTransitionsTo("Dial Wait");
                dreamerScene2.GetState("Fade Out").AddTransition("FINISHED", "Set Compass Point");
                break;

            case SceneNames.Ruins1_05b when AreaRando.Instance.Settings.Lemm:
                // Lemm sell all
                PlayMakerFSM lemm = FSMUtility.LocateFSM(GameObject.Find("Relic Dealer"), "npc_control");
                lemm.GetState("Convo End").AddAction(new RandomizerSellRelics());
                break;
            }
        }
        private static void ApplyRandomizerChanges(Scene newScene)
        {
            string sceneName = newScene.name;

            // Remove quake floors in Soul Sanctum to prevent soft locks
            if (Ref.PD.quakeLevel <= 0 && Ref.PD.killedMageLord &&
                (sceneName == SceneNames.Ruins1_23 || sceneName == SceneNames.Ruins1_30 ||
                 sceneName == SceneNames.Ruins1_32))
            {
                Ref.PD.SetBool(nameof(PlayerData.brokenMageWindow), true);
                Ref.PD.SetBool(nameof(PlayerData.brokenMageWindowGlass), true);

                foreach (GameObject obj in newScene.GetRootGameObjects())
                {
                    if (obj.name.Contains("Quake Floor"))
                    {
                        Object.Destroy(obj);
                    }
                }
            }

            // Make baldurs always able to spit rollers
            if (sceneName == SceneNames.Crossroads_11_alt || sceneName == SceneNames.Crossroads_ShamanTemple ||
                sceneName == SceneNames.Fungus1_28)
            {
                foreach (GameObject obj in Object.FindObjectsOfType <GameObject>())
                {
                    if (obj.name.Contains("Blocker"))
                    {
                        PlayMakerFSM fsm = FSMUtility.LocateFSM(obj, "Blocker Control");
                        if (fsm != null)
                        {
                            fsm.GetState("Can Roller?").RemoveActionsOfType <IntCompare>();
                        }
                    }
                }
            }

            switch (sceneName)
            {
            case SceneNames.Room_Ouiji:
                if (PlayerData.instance.shadeScene != "None")
                {
                    PlayMakerFSM jijiFsm  = GameObject.Find("Jiji NPC").LocateMyFSM("Conversation Control");
                    FsmState     HasShade = jijiFsm.GetState("Has Shade?");
                    HasShade.RemoveTransitionsTo("Check Location");
                    HasShade.AddTransition("YES", "Offer");
                }
                else if (AreaRando.Instance.Settings.Jiji)
                {
                    PlayerData.instance.SetString("shadeMapZone", "HIVE");
                    PlayMakerFSM jijiFsm = GameObject.Find("Jiji NPC").LocateMyFSM("Conversation Control");
                    FsmState     BoxUp   = jijiFsm.GetState("Box Up");
                    BoxUp.ClearTransitions();
                    BoxUp.AddFirstAction(jijiFsm.GetState("Convo Choice").GetActionsOfType <GetPlayerDataInt>()[0]);
                    BoxUp.AddTransition("FINISHED", "Offer");
                    FsmState SendText = jijiFsm.GetState("Send Text");
                    SendText.RemoveTransitionsTo("Yes");
                    SendText.AddTransition("YES", "Check Location");
                    FsmState CheckLocation = jijiFsm.GetState("Check Location");
                    CheckLocation.AddFirstAction(BoxUp.GetActionsOfType <SendEventByName>()[0]);
                    CheckLocation.AddFirstAction(jijiFsm.GetState("Convo Choice").GetActionsOfType <GetPlayerDataInt>()[0]);
                    CheckLocation.AddFirstAction(jijiFsm.GetState("Yes").GetActionsOfType <PlayerDataIntAdd>()[0]);
                    CheckLocation.AddFirstAction(jijiFsm.GetState("Yes").GetActionsOfType <SendEventByName>()[0]);
                }
                break;

            case SceneNames.Grimm_Main_Tent:
                PlayerData.instance.metGrimm = true;
                break;

            case SceneNames.Room_Final_Boss_Atrium:
                if (AreaRando.Instance.Settings.RandomizeDreamers)
                {
                    GameObject.Find("Tut_tablet_top").LocateMyFSM("Inspection").GetState("Init").ClearTransitions();
                }
                break;

            case SceneNames.Abyss_04:
                if (AreaRando.Instance.Settings.RandomizeVesselFragments)
                {
                    Object.Destroy(GameObject.Find("Fountain Donation"));
                }
                break;

            case SceneNames.Abyss_06_Core:
                // Opens door to LBC
                if (PlayerData.instance.healthBlue > 0 || PlayerData.instance.joniHealthBlue > 0 || GameManager.instance.entryGateName == "left1")
                {
                    PlayerData.instance.SetBoolInternal("blueVineDoor", true);
                    PlayMakerFSM BlueDoorFSM = GameObject.Find("Blue Door").LocateMyFSM("Control");
                    BlueDoorFSM.GetState("Init").RemoveTransitionsTo("Got Charm");
                }
                break;

            case SceneNames.Abyss_12:
                // Destroy shriek pickup if the player doesn't have wraiths
                if (Ref.PD.screamLevel == 0)
                {
                    Object.Destroy(GameObject.Find("Randomizer Shiny"));
                }
                break;

            case SceneNames.Abyss_15:
                GameObject.Find("Dream Enter Abyss").LocateMyFSM("Control").GetState("Init").RemoveTransitionsTo("Idle");
                GameObject.Find("Dream Enter Abyss").LocateMyFSM("Control").GetState("Init").AddTransition("FINISHED", "Inactive");
                if (!PlayerData.instance.hasDreamNail)
                {
                    Object.Destroy(GameObject.Find("New Shiny"));
                }
                break;

            case SceneNames.GG_Waterways:
                PlayerData.instance.SetBool("godseekerUnlocked", true);
                if (PlayerData.instance.simpleKeys < 1 || (!PlayerData.instance.openedWaterwaysManhole && PlayerData.instance.simpleKeys < 2))
                {
                    Object.Destroy(GameObject.Find("Randomizer Shiny"));
                }
                else
                {
                    GameObject.Find("Randomizer Shiny").LocateMyFSM("Shiny Control").GetState("Charm?").AddFirstAction(new RandomizerExecuteLambda(() => PlayerData.instance.DecrementInt("simpleKeys")));
                }
                break;

            case SceneNames.Crossroads_09:
                // Mawlek shard
                if (AreaRando.Instance.Settings.RandomizeMaskShards)
                {
                    Object.Destroy(GameObject.Find("Heart Piece"));
                }
                break;

            case SceneNames.Crossroads_38:

                if (AreaRando.Instance.Settings.RandomizeMaskShards)
                {
                    Object.Destroy(GameObject.Find("Reward 5"));
                }

                if (AreaRando.Instance.Settings.RandomizeCharms)
                {
                    Object.Destroy(GameObject.Find("Reward 10"));
                    Object.Destroy(GameObject.Find("Reward 46"));
                }

                if (AreaRando.Instance.Settings.RandomizeRancidEggs)
                {
                    Object.Destroy(GameObject.Find("Reward 16"));
                }

                if (AreaRando.Instance.Settings.RandomizeRelics)
                {
                    Object.Destroy(GameObject.Find("Reward 23"));
                    Object.Destroy(GameObject.Find("Reward 38"));
                }

                if (AreaRando.Instance.Settings.RandomizePaleOre)
                {
                    Object.Destroy(GameObject.Find("Reward 31"));
                }

                break;

            case SceneNames.Deepnest_East_02:
                if (GameManager.instance.entryGateName.StartsWith("bot2"))
                {
                    Object.Destroy(GameObject.Find("Quake Floor").FindGameObjectInChildren("Active").FindGameObjectInChildren("msk_generic"));
                    Object.Destroy(GameObject.Find("Quake Floor").FindGameObjectInChildren("Active").FindGameObjectInChildren("msk_generic (1)"));
                    Object.Destroy(GameObject.Find("Quake Floor").FindGameObjectInChildren("Active").FindGameObjectInChildren("msk_generic (2)"));
                    Object.Destroy(GameObject.Find("Quake Floor").FindGameObjectInChildren("Active").FindGameObjectInChildren("msk_generic (3)"));
                }
                break;

            case SceneNames.Crossroads_ShamanTemple:
                // Remove gate in shaman hut
                Object.Destroy(GameObject.Find("Bone Gate"));

                // Add hard save to shaman shiny
                FSMUtility.LocateFSM(GameObject.Find("Randomizer Shiny"), "Shiny Control").GetState("Finish")
                .AddAction(new RandomizerSetHardSave());

                break;

            case SceneNames.Deepnest_Spider_Town:
                // Make it so the first part of Beast's Den can't become inaccessible
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Deepnest_Spider_Town",
                    id             = "Collapser Small (12)",
                    activated      = true,
                    semiPersistent = false
                });
                if (AreaRando.Instance.Settings.RandomizeDreamers)
                {
                    Object.Destroy(GameObject.Find("Dreamer Hegemol"));
                    Object.Destroy(GameObject.Find("Dream Enter"));
                    Object.Destroy(GameObject.Find("Dream Impact"));
                    Object.Destroy(GameObject.Find("Shield"));
                    if (!PlayerData.instance.hasDreamNail)
                    {
                        Object.Destroy(GameObject.Find("New Shiny"));
                    }
                }
                break;

            case SceneNames.Dream_Nailcollection:
                // Make picking up shiny load new scene
                FSMUtility.LocateFSM(GameObject.Find("Randomizer Shiny"), "Shiny Control").GetState("Finish")
                .AddAction(new RandomizerChangeScene("RestingGrounds_07", "right1"));
                break;

            case SceneNames.Fungus2_15:
                if (GameManager.instance.entryGateName.StartsWith("left"))
                {
                    Object.Destroy(GameObject.Find("deepnest_mantis_gate").FindGameObjectInChildren("Collider"));
                    Object.Destroy(GameObject.Find("deepnest_mantis_gate"));
                }
                break;

            case SceneNames.Fungus2_21:
                // Make city crest gate openable infinite times and not hard save
                FSMUtility.LocateFSM(GameObject.Find("City Gate Control"), "Conversation Control")
                .GetState("Activate").RemoveActionsOfType <SetPlayerDataBool>();

                FsmState gateSlam = FSMUtility.LocateFSM(GameObject.Find("Ruins_gate_main"), "Open")
                                    .GetState("Slam");
                gateSlam.RemoveActionsOfType <SetPlayerDataBool>();
                gateSlam.RemoveActionsOfType <CallMethodProper>();
                gateSlam.RemoveActionsOfType <SendMessage>();
                break;

            case SceneNames.Fungus2_25:
                if (GameManager.instance.entryGateName.StartsWith("right"))
                {
                    Object.Destroy(GameObject.Find("mantis_big_door"));
                }
                break;

            case SceneNames.Fungus2_26:
                // Prevent leg eater from doing anything but opening the shop
                PlayMakerFSM legEater       = FSMUtility.LocateFSM(GameObject.Find("Leg Eater"), "Conversation Control");
                FsmState     legEaterChoice = legEater.GetState("Convo Choice");
                legEaterChoice.RemoveTransitionsTo("Convo 1");
                legEaterChoice.RemoveTransitionsTo("Convo 2");
                legEaterChoice.RemoveTransitionsTo("Convo 3");
                legEaterChoice.RemoveTransitionsTo("Infected Crossroad");
                legEaterChoice.RemoveTransitionsTo("Bought Charm");
                legEaterChoice.RemoveTransitionsTo("Gold Convo");
                legEaterChoice.RemoveTransitionsTo("All Gold");
                legEaterChoice.RemoveTransitionsTo("Ready To Leave");
                legEater.GetState("All Gold?").RemoveTransitionsTo("No Shop");

                // Just in case something other than the "Ready To Leave" state controls this
                Ref.PD.legEaterLeft = false;
                break;

            case SceneNames.Fungus3_archive_02:
                if (AreaRando.Instance.Settings.RandomizeDreamers)
                {
                    PlayerData.instance.SetBool("summonedMonomon", true);
                    Object.Destroy(GameObject.Find("Inspect Region"));
                    Object.Destroy(GameObject.Find("Quirrel Wounded"));
                    Object.Destroy(GameObject.Find("Quirrel"));
                    Object.Destroy(GameObject.Find("Monomon"));
                    Object.Destroy(GameObject.Find("Dream Enter"));
                    Object.Destroy(GameObject.Find("Dream Impact"));
                    Object.Destroy(GameObject.Find("Shield"));
                    if (!PlayerData.instance.hasDreamNail)
                    {
                        Object.Destroy(GameObject.Find("New Shiny"));
                    }
                }
                break;

            case SceneNames.Fungus3_44:
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Fungus3_44",
                    id             = "Secret Mask",
                    activated      = true,
                    semiPersistent = false
                });
                break;

            case SceneNames.Mines_33:
                // Make tolls always interactable
                if (AreaRando.Instance.Settings.MiscSkips && !AreaRando.Instance.Settings.RandomizeKeys)
                {
                    GameObject[] tolls = new GameObject[] { GameObject.Find("Toll Gate Machine"), GameObject.Find("Toll Gate Machine (1)") };
                    foreach (GameObject toll in tolls)
                    {
                        Object.Destroy(FSMUtility.LocateFSM(toll, "Disable if No Lantern"));
                    }
                }
                break;

            case SceneNames.RestingGrounds_07:
                // Make Moth NPC not give items since those are now shinies
                PlayMakerFSM moth = FSMUtility.LocateFSM(GameObject.Find("Dream Moth"), "Conversation Control");
                if (AreaRando.Instance.Settings.RandomizeRelics)
                {
                    PlayerData.instance.dreamReward1 = true;
                    moth.FsmVariables.GetFsmBool("Got Reward 1").Value = true;
                    PlayerData.instance.dreamReward6 = true;
                    moth.FsmVariables.GetFsmBool("Got Reward 6").Value = true;
                }
                if (AreaRando.Instance.Settings.RandomizePaleOre)
                {
                    PlayerData.instance.dreamReward3 = true;
                    moth.FsmVariables.GetFsmBool("Got Reward 3").Value = true;
                }
                if (AreaRando.Instance.Settings.RandomizeCharms)
                {
                    PlayerData.instance.dreamReward4 = true;
                    moth.FsmVariables.GetFsmBool("Got Reward 4").Value = true;
                }
                if (AreaRando.Instance.Settings.RandomizeVesselFragments)
                {
                    PlayerData.instance.dreamReward5 = true;
                    moth.FsmVariables.GetFsmBool("Got Reward 5").Value = true;
                }
                if (AreaRando.Instance.Settings.RandomizeSkills)
                {
                    PlayerData.instance.dreamReward5b = true;
                    moth.FsmVariables.GetFsmBool("Got Reward 5b").Value = true;
                }
                if (AreaRando.Instance.Settings.RandomizeMaskShards)
                {
                    PlayerData.instance.dreamReward7 = true;
                    moth.FsmVariables.GetFsmBool("Got Reward 7").Value = true;
                }
                break;

            case SceneNames.Room_Sly_Storeroom:
                // Make Sly pickup send Sly back upstairs
                FsmState slyFinish = FSMUtility.LocateFSM(GameObject.Find("Randomizer Shiny"), "Shiny Control")
                                     .GetState("Finish");
                slyFinish.AddAction(new RandomizerSetBool("SlyCharm", true));

                // The game breaks if you leave the storeroom after this, so just send the player out of the shop completely
                // People will think it's an intentional feature to cut out pointless walking anyway
                slyFinish.AddAction(new RandomizerChangeScene("Town", "door_sly"));
                break;

            case SceneNames.Ruins1_05:
                // Slight adjustment to breakable so wings is enough to progress, just like on old patches
                GameObject chandelier = GameObject.Find("ruind_dressing_light_02 (10)");
                chandelier.transform.SetPositionX(chandelier.transform.position.x - 2);
                chandelier.GetComponent <NonBouncer>().active = false;

                break;

            case SceneNames.Ruins1_09:
                if (GameManager.instance.entryGateName.StartsWith("t"))
                {
                    Object.Destroy(GameObject.Find("Battle Gate"));
                    Object.Destroy(GameObject.Find("Battle Scene"));
                }
                break;

            case SceneNames.Ruins1_24:
                // Pickup (Quake Pickup) -> Idle -> GetPlayerDataInt (quakeLevel)
                // Quake (Quake Item) -> Get -> SetPlayerDataInt (quakeLevel)
                // Stop spell container from destroying itself
                PlayMakerFSM quakePickup = FSMUtility.LocateFSM(GameObject.Find("Quake Pickup"), "Pickup");
                quakePickup.GetState("Idle").RemoveActionsOfType <IntCompare>();
                foreach (PlayMakerFSM childFSM in quakePickup.gameObject.GetComponentsInChildren <PlayMakerFSM>(true)
                         )
                {
                    if (childFSM.FsmName == "Shiny Control")
                    {
                        // Make spell container spawn shiny instead
                        quakePickup.GetState("Appear").GetActionsOfType <ActivateGameObject>()[1].gameObject
                        .GameObject.Value = childFSM.gameObject;

                        // Make shiny open gates on pickup/destroy
                        SendEvent openGate = new SendEvent
                        {
                            eventTarget = new FsmEventTarget
                            {
                                target      = FsmEventTarget.EventTarget.BroadcastAll,
                                excludeSelf = true
                            },
                            sendEvent  = FsmEvent.FindEvent("BG OPEN"),
                            delay      = 0,
                            everyFrame = false
                        };
                        childFSM.GetState("Destroy").AddFirstAction(openGate);
                        childFSM.GetState("Finish").AddFirstAction(openGate);

                        // Add hard save after picking up item
                        childFSM.GetState("Finish").AddFirstAction(new RandomizerSetHardSave());

                        break;
                    }
                }

                // Stop the weird invisible floor from appearing if dive has been obtained
                // I don't think it really serves any purpose, so destroying it should be fine
                if (Ref.PD.quakeLevel > 0)
                {
                    Object.Destroy(GameObject.Find("Roof Collider Battle"));
                }

                // Change battle gate to be destroyed if Soul Master is dead instead of it the player has quake
                FsmState checkQuake = FSMUtility.LocateFSM(GameObject.Find("Battle Gate (1)"), "Destroy if Quake")
                                      .GetState("Check");
                checkQuake.RemoveActionsOfType <FsmStateAction>();
                checkQuake.AddAction(new RandomizerBoolTest(nameof(PlayerData.killedMageLord), null, "DESTROY",
                                                            true));
                break;

            case SceneNames.Ruins1_32 when !Ref.PD.hasWalljump:
                // Platform after soul master
                GameObject plat = Object.Instantiate(GameObject.Find("ruind_int_plat_float_02 (3)"));
                plat.SetActive(true);
                plat.transform.position = new Vector2(40.5f, 72f);
                break;

            case SceneNames.Ruins2_04:
                // Shield husk doesn't walk as far as on old patches, making something pogoable to make up for this
                GameObject.Find("Direction Pole White Palace").GetComponent <NonBouncer>().active = false;

                // Prevent simple key softlocks
                FsmState hotSpringsKey = GameObject.Find("Inspect").LocateMyFSM("Conversation Control").GetState("Got Key?");
                hotSpringsKey.RemoveActionsOfType <IntCompare>();
                hotSpringsKey.AddAction(new RandomizerExecuteLambda(() =>
                {
                    if (GameManager.instance.GetPlayerDataInt("simpleKeys") > 1 || (PlayerData.instance.openedWaterwaysManhole && GameManager.instance.GetPlayerDataInt("simpleKeys") > 0))
                    {
                        PlayMakerFSM.BroadcastEvent("YES");
                    }
                    else
                    {
                        PlayMakerFSM.BroadcastEvent("NO");
                    }
                }));
                break;

            case SceneNames.Ruins2_11:
                // Prevent the jars below Collector from being permanently destroyed
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Ruins2_11",
                    id             = "Break Jar",
                    activated      = false,
                    semiPersistent = false
                });
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Ruins2_11",
                    id             = "Break Jar (1)",
                    activated      = false,
                    semiPersistent = false
                });
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Ruins2_11",
                    id             = "Break Jar (2)",
                    activated      = false,
                    semiPersistent = false
                });
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Ruins2_11",
                    id             = "Break Jar (3)",
                    activated      = false,
                    semiPersistent = false
                });
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Ruins2_11",
                    id             = "Break Jar (4)",
                    activated      = false,
                    semiPersistent = false
                });
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Ruins2_11",
                    id             = "Break Jar (5)",
                    activated      = false,
                    semiPersistent = false
                });
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Ruins2_11",
                    id             = "Break Jar (6)",
                    activated      = false,
                    semiPersistent = false
                });
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Ruins2_11",
                    id             = "Break Jar (7)",
                    activated      = false,
                    semiPersistent = false
                });
                GameManager.instance.sceneData.SaveMyState(new PersistentBoolData
                {
                    sceneName      = "Ruins2_11",
                    id             = "Break Jar (8)",
                    activated      = false,
                    semiPersistent = false
                });
                break;

            case SceneNames.Ruins2_Watcher_Room:
                if (AreaRando.Instance.Settings.RandomizeDreamers)
                {
                    Object.Destroy(GameObject.Find("Dreamer Lurien"));
                    Object.Destroy(GameObject.Find("Dream Enter"));
                    Object.Destroy(GameObject.Find("Dream Impact"));
                    Object.Destroy(GameObject.Find("Shield"));
                    if (!PlayerData.instance.hasDreamNail)
                    {
                        Object.Destroy(GameObject.Find("New Shiny"));
                    }
                }
                break;

            case SceneNames.Room_Mansion:
                if (!PlayerData.instance.xunFlowerGiven)
                {
                    Object.Destroy(GameObject.Find("Randomizer Shiny"));                                          //Should not actually be necessary, but left in as a precaution
                }
                break;

            case SceneNames.Room_Wyrm:
                //Make King's Brand cutscene function properly
                //This stops only stops the cutscene, not the avalanche itself
                Object.Destroy(GameObject.Find("Avalanche End"));
                break;

            case SceneNames.Room_Colosseum_Bronze:
                GameObject.Find("Colosseum Manager").LocateMyFSM("Geo Pool").GetState("Open Gates").AddFirstAction(new RandomizerSetBool("colosseumBronzeCompleted", true, true));
                break;

            case SceneNames.Room_Colosseum_Silver:
                GameObject.Find("Colosseum Manager").LocateMyFSM("Geo Pool").GetState("Open Gates").AddFirstAction(new RandomizerSetBool("colosseumSilverCompleted", true, true));
                break;

            case SceneNames.Town:
                // Prevent simple key softlocks
                FsmState jijiKey = GameObject.Find("Jiji Door").LocateMyFSM("Conversation Control").GetState("Key?");
                jijiKey.RemoveActionsOfType <GetPlayerDataInt>();
                jijiKey.RemoveActionsOfType <IntCompare>();
                jijiKey.AddAction(new RandomizerExecuteLambda(() =>
                {
                    if (GameManager.instance.GetPlayerDataInt("simpleKeys") > 1 || (PlayerData.instance.openedWaterwaysManhole && GameManager.instance.GetPlayerDataInt("simpleKeys") > 0))
                    {
                        PlayMakerFSM.BroadcastEvent("KEY");
                    }
                    else
                    {
                        PlayMakerFSM.BroadcastEvent("NOKEY");
                    }
                }));
                break;

            case SceneNames.Waterways_01:
                if (GameManager.instance.entryGateName.StartsWith("t"))
                {
                    Object.Destroy(GameObject.Find("waterways_manhole_open"));
                }
                break;

            case SceneNames.Waterways_03:
                if (AreaRando.Instance.Settings.Jiji)
                {
                    LanguageStringManager.SetLanguageString("TUK_RANCIDEGG_MIN", "Prices", "800");
                    LanguageStringManager.SetLanguageString("TUK_RANCIDEGG_MAX", "Prices", "1000");
                }
                else
                {
                    LanguageStringManager.SetLanguageString("TUK_RANCIDEGG_MIN", "Prices", "80");
                    LanguageStringManager.SetLanguageString("TUK_RANCIDEGG_MAX", "Prices", "100");
                }
                break;

            case SceneNames.Waterways_09:
                if (GameManager.instance.entryGateName.StartsWith("left"))
                {
                    Object.Destroy(GameObject.Find("Waterways Gate"));
                }
                GameObject.Find("Ruins Lever").LocateMyFSM("Switch Control").GetState("Hit").AddFirstAction(new RandomizerExecuteLambda(() => GameManager.instance.SetPlayerDataBool("waterwaysGate", true)));
                break;
            }
        }
Ejemplo n.º 13
0
        public void CR_Change_Room_temple(Scene scene)
        {
            if (scene.name != "Room_temple")
            {
                return;
            }

            Log("CR_Change_Room_temple()");
            //yield return null;

            #region Hornet NPC FSM

            GameObject   hornetNpcGo     = scene.FindRoot("Hornet Black Egg NPC");
            PlayMakerFSM hornetNpcFsm    = hornetNpcGo.LocateMyFSM("Conversation Control");
            FsmVariables hornetNpcFsmVar = hornetNpcFsm.FsmVariables;

            hornetNpcFsm.CopyState("Greet", "Give Item");
            hornetNpcFsm.RemoveAction("Give Item", 0);

            hornetNpcFsm.GetAction <CallMethodProper>("Give Item", 0).parameters = new FsmVar[]
            {
                new FsmVar(typeof(string))
                {
                    stringValue = "CUSTOM_HORNET_PRE_FINAL_BATTLE"
                },
                new FsmVar(typeof(string))
                {
                    stringValue = "Hornet"
                }
            };

            var pdbtAction = new PlayerDataBoolTest();
            pdbtAction.gameObject = hornetNpcFsm.GetAction <PlayerDataBoolTest>("Choice", 1).gameObject;
            pdbtAction.boolName   = "SFGrenadeTestOfTeamworkHornetCompanion";
            pdbtAction.isFalse    = FsmEvent.GetFsmEvent("ABSENT");

            hornetNpcFsm.InsertAction("Choice", pdbtAction, 1);

            hornetNpcFsm.AddTransition("Choice", "ABSENT", "Give Item");

            #endregion

            #region Shiny FSM

            GameObject shinyParent = GameObject.Instantiate(PrefabHolder.shinyPrefab);
            shinyParent.name = "Necklace";
            shinyParent.SetActive(false);
            shinyParent.transform.GetChild(0).gameObject.SetActive(true);
            shinyParent.transform.position = new Vector3(29.0f, 4.3f, 0.0f);

            hornetNpcFsm.CopyState("Box Up", "Give Item Spawn");

            hornetNpcFsm.ChangeTransition("Give Item Spawn", FsmEvent.Finished.Name, "Talk Finish");
            hornetNpcFsm.GetState("Give Item").Transitions.First(x => x.ToState == "Talk Finish").ToState = "Give Item Spawn";

            hornetNpcFsm.RemoveAction("Give Item Spawn", 5);
            hornetNpcFsm.RemoveAction("Give Item Spawn", 4);
            hornetNpcFsm.RemoveAction("Give Item Spawn", 3);
            hornetNpcFsm.RemoveAction("Give Item Spawn", 2);
            hornetNpcFsm.RemoveAction("Give Item Spawn", 1);
            hornetNpcFsm.RemoveAction("Give Item Spawn", 0);

            var agoAction = new ActivateGameObject();
            agoAction.gameObject             = new FsmOwnerDefault();
            agoAction.gameObject.OwnerOption = OwnerDefaultOption.SpecifyGameObject;
            agoAction.gameObject.GameObject  = shinyParent;
            agoAction.activate    = true;
            agoAction.recursive   = false;
            agoAction.resetOnExit = false;
            agoAction.everyFrame  = false;
            hornetNpcFsm.AddAction("Give Item Spawn", agoAction);
            hornetNpcFsm.AddAction("Give Item Spawn", new NextFrameEvent()
            {
                sendEvent = FsmEvent.Finished
            });

            PlayMakerFSM shinyFsm     = shinyParent.transform.GetChild(0).gameObject.LocateMyFSM("Shiny Control");
            FsmVariables shinyFsmVars = shinyFsm.FsmVariables;
            shinyFsmVars.FindFsmInt("Charm ID").Value         = 0;
            shinyFsmVars.FindFsmInt("Type").Value             = 0;
            shinyFsmVars.FindFsmBool("Activated").Value       = false;
            shinyFsmVars.FindFsmBool("Charm").Value           = false;
            shinyFsmVars.FindFsmBool("Dash Cloak").Value      = false;
            shinyFsmVars.FindFsmBool("Exit Dream").Value      = false;
            shinyFsmVars.FindFsmBool("Fling L").Value         = false;
            shinyFsmVars.FindFsmBool("Fling On Start").Value  = true;
            shinyFsmVars.FindFsmBool("Journal").Value         = false;
            shinyFsmVars.FindFsmBool("King's Brand").Value    = false;
            shinyFsmVars.FindFsmBool("Mantis Claw").Value     = false;
            shinyFsmVars.FindFsmBool("Pure Seed").Value       = false;
            shinyFsmVars.FindFsmBool("Quake").Value           = false;
            shinyFsmVars.FindFsmBool("Show Charm Tute").Value = false;
            shinyFsmVars.FindFsmBool("Slug Fling").Value      = false;
            shinyFsmVars.FindFsmBool("Super Dash").Value      = false;
            shinyFsmVars.FindFsmString("Item Name").Value     = Consts.LanguageStrings.HornetInvNameKey;
            shinyFsmVars.FindFsmString("PD Bool Name").Value  = "SFGrenadeTestOfTeamworkHornetCompanion";

            IntSwitch isAction     = shinyFsm.GetAction <IntSwitch>("Trinket Type", 0);
            var       tmpCompareTo = new List <FsmInt>(isAction.compareTo);
            tmpCompareTo.Add(tmpCompareTo.Count + 1);
            isAction.compareTo = tmpCompareTo.ToArray();
            shinyFsmVars.FindFsmInt("Trinket Num").Value = tmpCompareTo.Count;
            var tmpSendEvent = new List <FsmEvent>(isAction.sendEvent);
            tmpSendEvent.Add(FsmEvent.FindEvent("PURE SEED"));
            isAction.sendEvent = tmpSendEvent.ToArray();

            shinyFsm.CopyState("Love Key", "Necklace");

            shinyFsm.GetAction <SetPlayerDataBool>("Necklace", 0).boolName     = "SFGrenadeTestOfTeamworkHornetCompanion";
            shinyFsm.GetAction <SetSpriteRendererSprite>("Necklace", 1).sprite = TestOfTeamwork.Instance.SpriteDict.Get(TextureStrings.InvHornetKey);
            shinyFsm.GetAction <GetLanguageString>("Necklace", 2).convName     = Consts.LanguageStrings.HornetInvNameKey;

            shinyFsm.AddTransition("Trinket Type", "PURE SEED", "Necklace");

            #endregion

            Log("~CR_Change_Room_temple()");
        }
Ejemplo n.º 14
0
        private static void ApplyRandomizerChanges(Scene newScene)
        {
            string sceneName = newScene.name;

            // Remove quake floors in Soul Sanctum to prevent soft locks
            if (Ref.PD.quakeLevel <= 0 && Ref.PD.killedMageLord &&
                (sceneName == SceneNames.Ruins1_23 || sceneName == SceneNames.Ruins1_30 ||
                 sceneName == SceneNames.Ruins1_32))
            {
                Ref.PD.SetBool(nameof(PlayerData.brokenMageWindow), true);
                Ref.PD.SetBool(nameof(PlayerData.brokenMageWindowGlass), true);

                foreach (GameObject obj in newScene.GetRootGameObjects())
                {
                    if (obj.name.Contains("Quake Floor"))
                    {
                        Object.Destroy(obj);
                    }
                }
            }

            // Make baldurs always able to spit rollers
            if (sceneName == SceneNames.Crossroads_11_alt || sceneName == SceneNames.Crossroads_ShamanTemple ||
                sceneName == SceneNames.Fungus1_28)
            {
                foreach (GameObject obj in Object.FindObjectsOfType <GameObject>())
                {
                    if (obj.name.Contains("Blocker"))
                    {
                        PlayMakerFSM fsm = FSMUtility.LocateFSM(obj, "Blocker Control");
                        if (fsm != null)
                        {
                            fsm.GetState("Can Roller?").RemoveActionsOfType <IntCompare>();
                        }
                    }
                }
            }

            switch (sceneName)
            {
            case SceneNames.Abyss_12:
                // Destroy shriek pickup if the player doesn't have wraiths
                if (Ref.PD.screamLevel == 0)
                {
                    Object.Destroy(GameObject.Find("Randomizer Shiny"));
                }

                break;

            case SceneNames.Crossroads_ShamanTemple:
                // Remove gate in shaman hut
                Object.Destroy(GameObject.Find("Bone Gate"));

                // Add hard save to shaman shiny
                FSMUtility.LocateFSM(GameObject.Find("Randomizer Shiny"), "Shiny Control").GetState("Finish")
                .AddAction(new RandomizerSetHardSave());

                break;

            case SceneNames.Dream_Nailcollection:
                // Make picking up shiny load new scene
                FSMUtility.LocateFSM(GameObject.Find("Randomizer Shiny"), "Shiny Control").GetState("Finish")
                .AddAction(new RandomizerChangeScene("RestingGrounds_07", "right1"));
                break;

            case SceneNames.Fungus2_21:
                // Make city crest gate openable infinite times and not hard save
                FSMUtility.LocateFSM(GameObject.Find("City Gate Control"), "Conversation Control")
                .GetState("Activate").RemoveActionsOfType <SetPlayerDataBool>();

                FsmState gateSlam = FSMUtility.LocateFSM(GameObject.Find("Ruins_gate_main"), "Open")
                                    .GetState("Slam");
                gateSlam.RemoveActionsOfType <SetPlayerDataBool>();
                gateSlam.RemoveActionsOfType <CallMethodProper>();
                gateSlam.RemoveActionsOfType <SendMessage>();
                break;

            case SceneNames.Fungus2_26:
                // Prevent leg eater from doing anything but opening the shop
                PlayMakerFSM legEater       = FSMUtility.LocateFSM(GameObject.Find("Leg Eater"), "Conversation Control");
                FsmState     legEaterChoice = legEater.GetState("Convo Choice");
                legEaterChoice.RemoveTransitionsTo("Convo 1");
                legEaterChoice.RemoveTransitionsTo("Convo 2");
                legEaterChoice.RemoveTransitionsTo("Convo 3");
                legEaterChoice.RemoveTransitionsTo("Infected Crossroad");
                legEaterChoice.RemoveTransitionsTo("Bought Charm");
                legEaterChoice.RemoveTransitionsTo("Gold Convo");
                legEaterChoice.RemoveTransitionsTo("All Gold");
                legEaterChoice.RemoveTransitionsTo("Ready To Leave");
                legEater.GetState("All Gold?").RemoveTransitionsTo("No Shop");

                // Just in case something other than the "Ready To Leave" state controls this
                Ref.PD.legEaterLeft = false;
                break;

            case SceneNames.Mines_33:
                // Make tolls always interactable
                GameObject[] tolls =
                { GameObject.Find("Toll Gate Machine"), GameObject.Find("Toll Gate Machine (1)") };
                foreach (GameObject toll in tolls)
                {
                    Object.Destroy(FSMUtility.LocateFSM(toll, "Disable if No Lantern"));
                }

                break;

            case SceneNames.RestingGrounds_07:
                // Make Moth NPC not give items since those are now shinies
                Ref.PD.dreamReward4  = true;
                Ref.PD.dreamReward5b = true;

                PlayMakerFSM moth = FSMUtility.LocateFSM(GameObject.Find("Dream Moth"), "Conversation Control");
                moth.FsmVariables.GetFsmBool("Got Reward 4").Value  = true;
                moth.FsmVariables.GetFsmBool("Got Reward 5b").Value = true;
                break;

            case SceneNames.Room_Colosseum_02:
                // Move the upward loads in colo downward to prevent bench soft lock
                GameObject coloTransition1 = GameObject.Find("top1");
                GameObject coloTransition2 = GameObject.Find("top2");

                coloTransition1.transform.SetPositionY(coloTransition1.transform.position.y - 9f);
                coloTransition2.transform.SetPositionY(coloTransition2.transform.position.y - 9f);
                break;

            case SceneNames.Room_Sly_Storeroom:
                // Make Sly pickup send Sly back upstairs
                FsmState slyFinish = FSMUtility.LocateFSM(GameObject.Find("Randomizer Shiny"), "Shiny Control")
                                     .GetState("Finish");
                slyFinish.AddAction(new RandomizerSetBool("SlyCharm", true));

                // The game breaks if you leave the storeroom after this, so just send the player out of the shop completely
                // People will think it's an intentional feature to cut out pointless walking anyway
                slyFinish.AddAction(new RandomizerChangeScene("Town", "door_sly"));
                break;

            case SceneNames.Ruins1_05:
                // Slight adjustment to breakable so wings is enough to progress, just like on old patches
                GameObject chandelier = GameObject.Find("ruind_dressing_light_02 (10)");
                chandelier.transform.SetPositionX(chandelier.transform.position.x - 2);
                chandelier.GetComponent <NonBouncer>().active = false;

                break;

            case SceneNames.Ruins1_24:
                // Pickup (Quake Pickup) -> Idle -> GetPlayerDataInt (quakeLevel)
                // Quake (Quake Item) -> Get -> SetPlayerDataInt (quakeLevel)
                // Stop spell container from destroying itself
                PlayMakerFSM quakePickup = FSMUtility.LocateFSM(GameObject.Find("Quake Pickup"), "Pickup");
                quakePickup.GetState("Idle").RemoveActionsOfType <IntCompare>();

                foreach (PlayMakerFSM childFSM in quakePickup.gameObject.GetComponentsInChildren <PlayMakerFSM>(true)
                         )
                {
                    if (childFSM.FsmName == "Shiny Control")
                    {
                        // Make spell container spawn shiny instead
                        quakePickup.GetState("Appear").GetActionsOfType <ActivateGameObject>()[1].gameObject
                        .GameObject.Value = childFSM.gameObject;

                        // Make shiny open gates on pickup/destroy
                        SendEvent openGate = new SendEvent
                        {
                            eventTarget = new FsmEventTarget
                            {
                                target      = FsmEventTarget.EventTarget.BroadcastAll,
                                excludeSelf = true
                            },
                            sendEvent  = FsmEvent.FindEvent("BG OPEN"),
                            delay      = 0,
                            everyFrame = false
                        };
                        childFSM.GetState("Destroy").AddFirstAction(openGate);
                        childFSM.GetState("Finish").AddFirstAction(openGate);

                        // Add hard save after picking up item
                        childFSM.GetState("Finish").AddFirstAction(new RandomizerSetHardSave());

                        break;
                    }
                }

                // Stop the weird invisible floor from appearing if dive has been obtained
                // I don't think it really serves any purpose, so destroying it should be fine
                if (Ref.PD.quakeLevel > 0)
                {
                    Object.Destroy(GameObject.Find("Roof Collider Battle"));
                }

                // Change battle gate to be destroyed if Soul Master is dead instead of it the player has quake
                FsmState checkQuake = FSMUtility.LocateFSM(GameObject.Find("Battle Gate (1)"), "Destroy if Quake")
                                      .GetState("Check");
                checkQuake.RemoveActionsOfType <FsmStateAction>();
                checkQuake.AddAction(new RandomizerBoolTest(nameof(PlayerData.killedMageLord), null, "DESTROY",
                                                            true));
                break;

            case SceneNames.Ruins1_32 when !Ref.PD.hasWalljump:
                // Platform after soul master
                GameObject plat = Object.Instantiate(GameObject.Find("ruind_int_plat_float_02 (3)"));
                plat.SetActive(true);
                plat.transform.position = new Vector2(40.5f, 72f);
                break;

            case SceneNames.Ruins2_04:
                // Shield husk doesn't walk as far as on old patches, making something pogoable to make up for this
                GameObject.Find("Direction Pole White Palace").GetComponent <NonBouncer>().active = false;
                break;
            }
        }