private static void DisableSwim(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self)
        {
            orig(self);

            if (RandomizerMod.Instance.Settings.RandomizeSwim && self.FsmName == "Surface Water Region")
            {
                if (self.gameObject.LocateFSM("Acid Armour Check") != null)
                {
                    return;                                                         // acid
                }
                FsmState       splash    = self.GetState("Big Splash?");
                FsmStateAction acidDeath = new FsmStateActions.RandomizerExecuteLambda(() =>
                {
                    if (!RandomizerMod.Instance.Settings.GetBool(name: "canSwim"))
                    {
                        // this is actually the spike death despite the enum, because the acid death splashes green stuff
                        HeroController.instance.TakeDamage(self.gameObject, CollisionSide.other, 1, (int)HazardType.ACID);
                        PlayMakerFSM.BroadcastEvent("SWIM DEATH");
                    }
                });

                splash.AddFirstAction(acidDeath);
                splash.AddTransition("SWIM DEATH", "Idle");
            }
        }
Пример #2
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);
        }
Пример #3
0
        private static void ModifyFsm(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self)
        {
            switch (self.FsmName)
            {
            // first spit baldurs
            case "Blocker Control" when self.name == "Blocker": {
                self.GetState("Idle").ChangeTransition("ATTACK", "Can Roller?");
                break;
            }

            // gruz drop room
            case "Bouncer Control" when self.name.StartsWith("Fly") && GameManager.instance.sceneName == "Crossroads_07": {
                HeroController.instance.StartCoroutine(FixGruzDrop(self));
                break;
            }

            // remove shade spells
            case "Shade Control" when self.name.StartsWith("Hollow Shade"): {
                self.GetState("Init").RemoveAction(6);
                self.FsmVariables.FindFsmInt("SP").Value = 0;
                break;
            }

            // make furious vengeflies trigger later
            case "Control" when self.name.StartsWith("Angry Buzzer"): {
                self.gameObject.GetComponentInChildren <AlertRange>().transform.localScale = new Vector3(10, 10, 1.3f);
                break;
            }
            }

            orig(self);
        }
        private static void FixVoidHeart(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self)
        {
            orig(self);
            if (currentSettings.blockZoteDeath && self.FsmName == "Check Zote Death")
            {
                GameObject.Destroy(self);
                return;
            }

            if (currentSettings.fixVoidHeart)
            {
                if (self.FsmName == "Shade Control")
                {
                    if (self.gameObject?.name?.StartsWith("Hollow Shade") ?? false)
                    {
                        self.FsmVariables.FindFsmBool("Friendly").Value = false;
                        self.GetState("Pause").ClearTransitions();
                        self.GetState("Pause").AddTransition("FINISHED", "Init");
                    }
                }
                else if (self.FsmName == "Control")
                {
                    if (self.gameObject?.name?.StartsWith("Shade Sibling") ?? false)
                    {
                        self.FsmVariables.FindFsmBool("Friendly").Value = false;
                        self.GetState("Pause").ClearTransitions();
                        self.GetState("Pause").AddTransition("FINISHED", "Init");
                    }
                }
            }
        }
        // For the time being, let's keep some fsm scene edits here rather than in the SceneChanged function.
        // This way, they work even when the previous scene is a boss scene.
        public static void FsmSceneEdits(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self)
        {
            EditStagStations(self);
            DisableInfectedCrossroads(self);
            BossRewardReplacement.DestroyGruzmomGeo(self);

            orig(self);
        }
Пример #6
0
        private static void ShowSkillsInInventory(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self)
        {
            orig(self);

            if (self.FsmName == "Build Equipment List" && self.gameObject.name == "Equipment")
            {
                self.GetState("Walljump").GetActionOfType <PlayerDataBoolTest>().boolName.Value = "hasWalljumpAny";

                PlayerDataBoolTest[] dashChecks = self.GetState("Dash").GetActionsOfType <PlayerDataBoolTest>();
                dashChecks[0].boolName.Value = "hasDashAny";
            }
        }
Пример #7
0
        private static void ModifyFSM(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self)
        {
            switch (self.FsmName)
            {
            case "Control" when self.name == "Initial Fall Impact" && NoHardFalls:
                self.ChangeTransition("Idle", "LAND", "Return Control");
                break;

            case "Call Lever" when self.name.StartsWith("Lift Call Lever") && Televator:
                // Don't change big elevators.
                if (self.GetState("Check Already Called") == null)
                {
                    break;
                }

                self.ChangeTransition("Left", "FINISHED", "Send Msg");

                self.ChangeTransition("Right", "FINISHED", "Send Msg");
                break;

            case "Bottle Control" when self.GetState("Shatter") is FsmState shatter && GrubsThroughWalls:
            {
                shatter.RemoveAllOfType <BoolTest>();
                break;
            }

            case "Switch Control" when self.name.Contains("Ruins Lever") && LeverSkips:
            {
                self.GetState("Range").RemoveAllOfType <BoolTest>();
                self.GetState("Check If Nail").RemoveAllOfType <BoolTest>();
                break;
            }

            case "Dream Nail" when self.name == "Knight" && Storage:
                ((ListenForDreamNail)self.GetState("Cancelable").Actions.First(a => a.GetType() == typeof(ListenForDreamNail))).activeBool      = true;
                ((ListenForDreamNail)self.GetState("Cancelable Dash").Actions.First(a => a.GetType() == typeof(ListenForDreamNail))).activeBool = true;
                ((ListenForDreamNail)self.GetState("Queuing").Actions.First(a => a.GetType() == typeof(ListenForDreamNail))).activeBool         = true;
                self.GetState("Queuing").Actions = self.GetState("Queuing").Actions.Where(a => a.GetType() != typeof(BoolTest)).ToArray();
                break;
            }

            orig(self);
        }
        // Seems to remove Zote death triggers and also affect dream nail storage? Not entirely sure.
        private static void ModifyFSM(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self)
        {
            if (self.Fsm.FsmComponent.FsmName == "Check Zote Death")
            {
                Object.Destroy(self);
                return;
            }

            orig(self);

            if (self.gameObject.name != "Knight" || self.FsmName != "Dream Nail")
            {
                return;
            }

            self.GetState("Cancelable").GetActionsOfType <ListenForDreamNail>()[0].activeBool      = true;
            self.GetState("Cancelable Dash").GetActionsOfType <ListenForDreamNail>()[0].activeBool = true;
            self.GetState("Queuing").GetActionsOfType <ListenForDreamNail>()[0].activeBool         = true;
            self.GetState("Queuing").RemoveActionsOfType <BoolTest>();
        }
Пример #9
0
        private static void ModifyFsm(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self)
        {
            switch (self.FsmName)
            {
            // vengful spirit pickup
            case "Get Fireball" when self.name == "Knight Get Fireball":
                self.GetState("Start").GetAction <Wait>().time  = 0;
                self.GetState("Rumble").GetAction <Wait>().time = 0;

                self.GetState("Start").RemoveAllOfType <iTweenMoveBy>();
                self.GetState("Rumble").RemoveAllOfType <iTweenMoveBy>();
                self.GetState("Get").RemoveAllOfType <iTweenMoveBy>();
                break;

            case "Check Fall" when self.name == "Knight Cutscene Animator":
                self.GetState("Black").RemoveAction <Wait>();
                self.GetState("Fade Back").GetAction <Wait>().time = 3;
                break;

            // shade soul pickup
            case "Get Fireball" when self.name == "Knight Get Fireball Lv2":
                self.GetState("Start").GetAction <Wait>().time = 0;
                self.GetState("Start").ChangeTransition("FINISHED", "Get PlayerData");

                self.GetState("Start").RemoveAllOfType <iTweenMoveBy>();
                self.GetState("Rumble").RemoveAllOfType <iTweenMoveBy>();
                self.GetState("Get").RemoveAllOfType <iTweenMoveBy>();
                break;

            // howling wraiths pickup
            case "Get Scream" when self.name == "Knight Get Scream":
                self.GetState("Start").GetAction <Wait>().time = 0.1f;
                self.GetState("Fall").GetAction <Wait>().time  = 0.3f;

                self.GetState("Start").ChangeTransition("FINISHED", "Get");

                self.GetState("Start").RemoveAction <AudioPlayerOneShotSingle>();
                self.GetState("Start").RemoveAllOfType <iTweenMoveBy>();
                self.GetState("Get").RemoveAllOfType <iTweenMoveBy>();
                self.gameObject.GetComponentsInChildren <Transform>().First(transform => transform.name == "Orbs").gameObject.SetActive(false);
                break;

            // shade cloak pickup
            case "Get Shadow Dash" when self.name == "Dish Plat":
                self.GetState("Fall").GetAction <Wait>().time = 1;
                self.GetState("Fall").ChangeTransition("FINISHED", "UI Msg");
                break;

            // desolate dive pickup
            case "corpse" when self.name == "Corpse Mage Lord 2(Clone)":
                self.GetState("Steam").GetAction <Wait>().time = 0;
                self.GetState("Ready").GetAction <Wait>().time = 0;
                self.GetState("Pause").GetAction <Wait>().time = 0;
                self.GetState("Land").GetAction <Wait>().time  = 0;

                self.gameObject.GetComponentsInChildren <Transform>().Where(transform => transform.name == "Soul Breath").ToList().ForEach(transform => transform.gameObject.SetActive(false));
                break;

            case "Pickup" when self.name == "Quake Pickup":
                self.GetState("Wait").ChangeTransition("FINISHED", "Appear");
                self.GetState("Wait").GetAction <Wait>().time = 0.5f;
                break;

            case "Get Quake" when self.name == "Knight Get Quake":
                self.GetState("Start").GetAction <Wait>().time = 0.1f;
                self.GetState("Fall").GetAction <Wait>().time  = 0.3f;

                self.GetState("Start").ChangeTransition("FINISHED", "Get");

                self.GetState("Start").RemoveAction <AudioPlayerOneShotSingle>();
                self.GetState("Start").RemoveAllOfType <iTweenMoveBy>();
                self.GetState("Get").RemoveAllOfType <iTweenMoveBy>();
                self.gameObject.GetComponentsInChildren <Transform>().First(transform => transform.name == "Orbs").gameObject.SetActive(false);
                break;

            // descending dark pickup
            case "Control" when self.name == "Crystal Shaman":
                self.GetState("Land Hero").ChangeTransition("FINISHED", "Get PlayerData 2");
                break;

            // dream nail cutscene enter
            case "Conversation Control" when self.name == "Dreamer Plaque Inspect":
                self.GetState("Hero Anim").ChangeTransition("FINISHED", "Map Msg?");
                break;

            case "Control" when self.name == "Dreamer Scene 2":
                self.GetState("Fade Out").GetAction <Wait>().time = 1;
                self.GetState("Take Control").ChangeTransition("FINISHED", "Fade Out");
                self.GetState("Fade Out").ChangeTransition("FINISHED", "Set Compass Point");
                break;

            // gruz mother
            case "corpse" when self.name == "Corpse Big Fly 1(Clone)":
                self.GetState("Init").GetAction <Wait>().time  = 0;
                self.GetState("Steam").GetAction <Wait>().time = 0;
                self.GetState("Ready").GetAction <Wait>().time = 0;
                break;

            case "burster" when self.name == "Corpse Big Fly Burster(Clone)":
                self.GetState("Landed").RemoveAction <Wait>();
                self.GetState("Stop Emit").RemoveAction <Wait>();
                self.GetState("Stop").RemoveAction <Wait>();
                self.GetState("Gurg 1").RemoveAction <Wait>();
                self.GetState("Burst").RemoveAction <Wait>();
                self.GetState("State 1").RemoveAction <Wait>();
                break;

            // dreamer cutscene skip
            case "Control" when self.name == "Dreamer NPC":
                self.GetState("Cinematic").RemoveAction <FindGameObject>();
                self.GetState("Cinematic").RemoveAction <SendMessage>();
                self.GetState("Cinematic").RemoveAction <FadeAudio>();
                self.GetState("Cinematic").AddAction(new NextFrameEvent {
                    sendEvent = self.GetState("Cinematic").Fsm.GetEvent("CINEMATIC END")
                });

                self.GetState("Set Hegemol").ChangeTransition("FINISHED", "Return");
                self.GetState("Set Lurien").ChangeTransition("FINISHED", "Return");
                self.GetState("Set Monomon").ChangeTransition("FINISHED", "Return");
                break;

            // spawn soul master on the right for all skills fight
            case "Mage Lord" when self.name == "Mage Lord":
                FsmState setEntryPoint = self.GetState("Set Entry Point");

                // remove knight position check and left spawn point
                for (int i = 0; i < 4; i++)
                {
                    setEntryPoint.RemoveAction(2);
                }

                break;

            // early broken vessel fight start
            case "IK Control" when self.name == "Infected Knight": {
                // 1221 early spell hits
                FsmState start = self.GetState("Roar Start");
                FsmState end   = self.GetState("Roar End");

                start.AddAction(end.GetAction <SetInvincible>());
                start.AddAction(end.GetAction <SetCollider>());
                start.AddAction(end.GetAction <SetIsKinematic2d>());

                end.RemoveAction <SetInvincible>();
                end.RemoveAction <SetCollider>();
                end.RemoveAction <SetIsKinematic2d>();

                // use the godhome wait for normal world fight as well to allow for left side fight start
                self.GetState("Waiting").ChangeTransition("BATTLE START", "GG Wait");

                break;
            }

            // fast toll benches
            case "Toll Machine Bench" when self.name == "Toll Machine Bench": {
                // set wait times for each state
                self.GetState("Pause Before Box Drop").GetAction <Wait>().time = 0.1f;
                self.GetState("Box Down").GetAction <Wait>().time = 0.8f;
                self.GetState("Bench Up").GetAction <Wait>().time = 1.3f;

                // fast toll disappearing
                self.gameObject.GetComponent <tk2dSpriteAnimator>().GetClipByName("Box_disappear").fps = 45;    // 3x speed, 15 default
                self.GetState("Box Down").RemoveAction <AudioPlayerOneShotSingle>();

                // fast bench animation, synced with audio
                self.GetState("Bench Up").GetAction <Tk2dPlayAnimationWithEvents>().gameObject.GameObject.Value.GetComponent <tk2dSpriteAnimator>().DefaultClip.fps = 32;   // 2x speed, 16 default
                ((AudioPlayerOneShotSingle)self.GetState("Bench Up").Actions[6]).delay = 0.45f;
                ((AudioPlayerOneShotSingle)self.GetState("Bench Up").Actions[7]).delay = 0.95f;

                // move rise audio one state earlier to make it sync better
                AudioPlayerOneShotSingle rise = (AudioPlayerOneShotSingle)self.GetState("Bench Up").Actions[5];
                rise.delay = 0.7f;
                self.GetState("Box Down").AddAction(rise);
                self.GetState("Bench Up").RemoveAction(5);

                break;
            }

            // fast trap bench
            case "Fade" when self.name == "RestBench Spider": {
                self.GetState("Idle").ChangeTransition("FIRST STRUGGLE", "Start Fade");
                self.GetState("Finish Fade").ChangeTransition("FINISHED", "Capture End");

                string[] waitStates = { "Start Fade", "Capture End", "Fade Up", "Land" };
                foreach (string waitState in waitStates)
                {
                    self.GetState(waitState).GetAction <Wait>().time = 0.5f;
                }
                break;
            }

            // fast lifeblood door
            case "Control" when self.name == "Blue Plinth": {
                self.GetState("Send Event").GetAction <Wait>().time = 0.15f;    // wait inbetween blue heart count increment

                string[] waitStates = { "Start Pause", "Glow Start", "Complete Pause", "Final Glow" };
                foreach (string waitState in waitStates)
                {
                    self.GetState(waitState).RemoveAction <Wait>();
                }
                break;
            }
            }

            orig(self);
        }