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); }
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); } } }
public FsmEvent AddEvent(string eventName) { events.Add(eventName); FsmEvent fsmEvent = FsmEvent.FindEvent(eventName) ?? FsmEvent.GetFsmEvent(eventName); fsmEvent.IsGlobal = true; return(fsmEvent); }
private static void PatchWaterFSM(PlayMakerFSM fsm) { fsm.GetState("Enter").AddAction(new SendEvent { eventTarget = FsmEventTarget.Self, sendEvent = FsmEvent.FindEvent("FINISHED"), delay = 0, everyFrame = false }); }
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; } }
public static void AddTransition(this PMFSM fsm, string stateName, string fsmEvent, string toState) { AddTransition(fsm.GetState(stateName), FsmEvent.FindEvent(fsmEvent), fsm.GetState(toState)); }
public static void AddTransition(this FsmState state, string fsmEvent, string toState) { AddTransition(state, FsmEvent.FindEvent(fsmEvent), state.Fsm.GetState(toState)); }
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; } }
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()"); }
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; } }