예제 #1
0
 MidPriorityBinaryOperatorLookup(LookupDictionary <MidPriorityBinaryOperator> lookup)
     : base(lookup)
 {
     lookup.Add("*", new MidPriorityBinaryOperator("*", (x, y) => x * y));
     lookup.Add("/", new MidPriorityBinaryOperator("/", (x, y) => x / y));
     lookup.Add("%", new MidPriorityBinaryOperator("%", (x, y) => x % y));
 }
 FunctionLookup(LookupDictionary <Function> lookup)
     : base(lookup)
 {
     lookup.Add("abs", new Function("abs", x => Math.Abs(x)));
     lookup.Add("ceiling", new Function("ceiling", x => Math.Ceiling(x)));
     lookup.Add("cos", new Function("cos", x => Math.Cos(x)));
     lookup.Add("exp", new Function("exp", x => Math.Exp(x)));
     lookup.Add("floor", new Function("floor", x => Math.Floor(x)));
     lookup.Add("log", new Function("log", x => Math.Log10(x)));
     lookup.Add("sin", new Function("sin", x => Math.Sin(x)));
     lookup.Add("sqrt", new Function("sqrt", x => Math.Sqrt(x)));
     lookup.Add("tan", new Function("tan", x => Math.Tan(x)));
     lookup.Add("truncate", new Function("truncate", x => Math.Truncate(x)));
 }
예제 #3
0
        static LookupDictionary <Seed, GenerationResult> ReadKnownSeeds()
        {
            var seeds = new LookupDictionary <Seed, GenerationResult>(r => r.Seed);

            if (!File.Exists(GeneratedSeedsFileName))
            {
                return(seeds);
            }

            var lines = File.ReadAllLines(GeneratedSeedsFileName);

            foreach (var line in lines)
            {
                var segments = line.Split(',');

                if (!Seed.TryParse(segments[0], out var seed) ||
                    !int.TryParse(segments[1], out var itterations) ||
                    !TimeSpan.TryParse(segments[1], out var time))
                {
                    continue;
                }

                var result = new GenerationResult
                {
                    Seed        = seed,
                    Itterations = itterations,
                    Elapsed     = time
                };

                seeds.Add(result);
            }

            return(seeds);
        }
예제 #4
0
        void DetectNewScreens()
        {
            foundScreens.Clear();

            foreach (var screen in GetScreens())
            {
                if (hookedScreens.Contains(screen))
                {
                    foundScreens.Add(screen);

                    if (screen.GetType() == GamePlayScreenType)
                    {
                        itemLocationMap = ((GameplayScreen)hookedScreens[screen]).ItemLocations;
                    }

                    continue;
                }

                if (!Screen.RegisteredTypes.TryGetValue(screen.GetType(), out var handlerType))
                {
                    continue;
                }

                var screenHandler = (Screen)Activator.CreateInstance(handlerType, this, screen);
                hookedScreens.Add(screenHandler);
                foundScreens.Add(screen);

                screenHandler.Initialize(itemLocationMap, (GCM)Dynamic.GCM);
            }

            if (foundScreens.Count != hookedScreens.Count)
            {
                hookedScreens.Filter(foundScreens, s => s.Unload());
            }
        }
예제 #5
0
        static TextReplacer()
        {
            TextReplacers.Add(new TextReplacer(16, 26, (level, itemLocations, options) =>
            {
                var concussions = level.GameSave.GetConcussionCount();

                var replacement = "What—? I don't *think* I hit my head...";
                switch (concussions)
                {
                case 1:
                    replacement = "What—? I feel like I've suffered a concussion...";
                    break;

                case int c when(c > 1):
                    replacement = $"What—? I feel like I've suffered {concussions} concussions...";
                    break;
                }
                TimeSpinnerGame.Localizer.OverrideKey("cs_tem_1_lun_01", replacement);
            }));
            TextReplacers.Add(new TextReplacer(11, 4, (level, itemLocations, options) => {
                if (options.GyreArchives)
                {
                    TimeSpinnerGame.Localizer.OverrideKey("q_ram_4_lun_29alt",
                                                          "It says, 'Redacted Temporal Research: Lord of Ravens'. Maybe I should ask the crow about this...");
                }
            }));
            TextReplacers.Add(new TextReplacer(2, 51, (level, itemLocations, options) => {
                if (!options.GyreArchives)
                {
                    return;
                }
                TimeSpinnerGame.Localizer.OverrideKey("cs_pro_lun_02",
                                                      "Yorne? Oh... not quite. Is this... his memory?");
                TimeSpinnerGame.Localizer.OverrideKey("cs_pro_lun_03",
                                                      "I still can't believe they picked *her*, I deserved this.");
                TimeSpinnerGame.Localizer.OverrideKey("cs_pro_lun_04",
                                                      "*sigh* Even as just a reflection... Yorne is still as Yorne as ever.");
                TimeSpinnerGame.Localizer.OverrideKey("cs_pro_lun_05",
                                                      "I have to find where that Kobo has run off to.");
                TimeSpinnerGame.Localizer.OverrideKey("cs_pro_lun_06",
                                                      "'Kobo'... There's no one in our village by that name... I don't think this 'memory' is real.");
            }));
        }
예제 #6
0
        public ItemUnlockingMap(Seed seed)
        {
            var random = new Random((int)seed.Id);

            unlockingSpecifications = new LookupDictionary <ItemIdentifier, UnlockingSpecification>(26, s => s.Item)
            {
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.TimespinnerWheel), R.TimespinnerWheel, R.TimeStop),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.DoubleJump), R.DoubleJump, R.TimeStop),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.Dash), R.ForwardDash),
                new UnlockingSpecification(new ItemIdentifier(EInventoryOrbType.Flame, EOrbSlot.Passive), R.AntiWeed),
                new UnlockingSpecification(new ItemIdentifier(EInventoryOrbType.Flame, EOrbSlot.Melee), R.AntiWeed),
                new UnlockingSpecification(new ItemIdentifier(EInventoryOrbType.Flame, EOrbSlot.Spell), R.AntiWeed),
                new UnlockingSpecification(new ItemIdentifier(EInventoryOrbType.Book, EOrbSlot.Spell), R.AntiWeed),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.ScienceKeycardA), R.CardA, R.CardB | R.CardC | R.CardD),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.ScienceKeycardB), R.CardB, R.CardC | R.CardD),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.ScienceKeycardC), R.CardC, R.CardD),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.ScienceKeycardD), R.CardD),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.ElevatorKeycard), R.CardE),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.ScienceKeycardV), R.CardV),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.WaterMask), R.Swimming),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.TimespinnerSpindle), R.TimespinnerSpindle),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.TimespinnerGear1), R.TimespinnerPiece1),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.TimespinnerGear2), R.TimespinnerPiece2),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.TimespinnerGear3), R.TimespinnerPiece3),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.EssenceOfSpace), R.UpwardDash, R.DoubleJump | R.TimeStop),
                new UnlockingSpecification(new ItemIdentifier(EInventoryOrbType.Barrier, EOrbSlot.Spell), R.UpwardDash, R.DoubleJump | R.TimeStop),
                new UnlockingSpecification(new ItemIdentifier(EInventoryOrbType.Pink, EOrbSlot.Melee), R.PinkOrb),
                new UnlockingSpecification(new ItemIdentifier(EInventoryOrbType.Pink, EOrbSlot.Spell), R.PinkOrb),
                new UnlockingSpecification(new ItemIdentifier(EInventoryOrbType.Pink, EOrbSlot.Passive), R.PinkOrb),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.AirMask), R.GasMask),
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.Tablet), R.Tablet),
                new UnlockingSpecification(new ItemIdentifier(EInventoryOrbType.Eye, EOrbSlot.Passive), R.OculusRift),
                new UnlockingSpecification(new ItemIdentifier(EInventoryFamiliarType.Kobo), R.Kobo),
                new UnlockingSpecification(new ItemIdentifier(EInventoryFamiliarType.MerchantCrow), R.MerchantCrow),
            };

            if (seed.Options.SpecificKeys)
            {
                MakeKeyCardUnlocksCardSpecific();
            }

            var pyramidUnlockingSpecification =
                new UnlockingSpecification(new ItemIdentifier(EInventoryRelicType.PyramidsKey), R.None, R.Teleport);

            SetTeleporterPickupAction(random, pyramidUnlockingSpecification, seed.Options);

            unlockingSpecifications.Add(pyramidUnlockingSpecification);
        }
        public void Should_generate_a_hundert_beatable_seeds()
        {
            var seeds = new LookupDictionary <Seed, GenerationResult>(r => r.Seed);

            while (seeds.Count != 100)
            {
                var result = Randomizer.Generate(FillingMethod.Random, SeedOptions.None);

                if (!seeds.Contains(result.Seed))
                {
                    seeds.Add(result);
                }
            }

            var longestGeneration = seeds.OrderByDescending(s => s.Elapsed).First();
            var validSeeds        = string.Join("\n", seeds.Select(s => s.Seed));

            Assert.That(seeds, Is.Not.Empty);
        }
예제 #8
0
        void MarkAvailableItemLocations()
        {
            preservedRoomStates = new LookupDictionary <Roomkey, MinimapRoomState>(r => r.RoomKey);

            var visableAreas = (List <EMinimapEraType>)Dynamic._availableEras;

            foreach (var itemLocation in GetAvailableItemLocations())
            {
                var roomKey = new Roomkey(itemLocation.Key.LevelId, itemLocation.Key.RoomId);                 //somehow they keys dont match if we use itemLocation.Key directly
                if (preservedRoomStates.Contains(roomKey))
                {
                    continue;
                }

                var room = GetRoom(roomKey);

                MakeSureEraIsVisable(visableAreas, room);
                preservedRoomStates.Add(new MinimapRoomState(roomKey, room));

                foreach (var block in room.Blocks.Values)
                {
                    if (block.IsSolidWall)
                    {
                        continue;
                    }

                    block.IsKnown   = true;
                    block.IsVisited = true;

                    if (block.IsTransition || block.IsCheckpoint || block.IsBoss)
                    {
                        block.IsTransition = false;
                        block.IsCheckpoint = false;
                        block.RoomColor    = EMinimapRoomColor.Yellow;
                    }
                    else
                    {
                        block.RoomColor = EMinimapRoomColor.Orange;
                    }
                }
            }
        }
 LowPriorityBinaryOperatorLookup(LookupDictionary <LowPriorityBinaryOperator> lookup)
     : base(lookup)
 {
     lookup.Add("+", new LowPriorityBinaryOperator("+", (x, y) => x + y));
     lookup.Add("-", new LowPriorityBinaryOperator("-", (x, y) => x - y));
 }
 HighPriorityBinaryOperatorLookup(LookupDictionary <HighPriorityBinaryOperator> lookup)
     : base(lookup)
 {
     lookup.Add("^", new HighPriorityBinaryOperator("^", (x, y) => Math.Pow(x, y)));
 }
예제 #11
0
        static RoomTrigger()
        {
            RoomTriggers.Add(new RoomTrigger(0, 3, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (seedOptions.StartWithJewelryBox)
                {
                    level.AsDynamic().UnlockRelic(EInventoryRelicType.JewelryBox);
                }

                if (seedOptions.StartWithMeyef)
                {
                    level.GameSave.AddItem(level, new ItemIdentifier(EInventoryFamiliarType.Meyef));
                    level.GameSave.Inventory.EquippedFamiliar = EInventoryFamiliarType.Meyef;

                    var luniasObject    = level.MainHero.AsDynamic();
                    var familiarManager = ((object)luniasObject._familiarManager).AsDynamic();

                    familiarManager.ChangeFamiliar(EInventoryFamiliarType.Meyef);
                    familiarManager.AddFamiliarPoofAnimation();
                }

                if (seedOptions.StartWithTalaria)
                {
                    level.AsDynamic().UnlockRelic(EInventoryRelicType.Dash);
                }
            }));
            RoomTriggers.Add(new RoomTrigger(17, 8, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // False boss room
                SpawnBoss(level, seedOptions, TargetBossId);
            }));
            RoomTriggers.Add(new RoomTrigger(17, 13, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // False boss room
                SpawnBoss(level, seedOptions, TargetBossId);
            }));
            RoomTriggers.Add(new RoomTrigger(1, 0, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Inverted mode triggers
                if (!seedOptions.Inverted || level.GameSave.GetSaveBool("TSRandomizerHasTeleportedPlayer"))
                {
                    return;
                }

                level.GameSave.SetValue("TSRandomizerHasTeleportedPlayer", true);
                level.GameSave.SetValue("HasUsedCityTS", true);
                level.GameSave.SetCutsceneTriggered("City1_Frame", true);
                level.GameSave.SetCutsceneTriggered("City2_Spindle", true);
                level.GameSave.SetCutsceneTriggered("City3_Warp", true);
                level.GameSave.SetCutsceneTriggered("LakeDesolation1_Entrance", true);                 // Fixes music when returning to Lake Desolation later

                level.RequestChangeLevel(new LevelChangeRequest {
                    LevelID = 3, RoomID = 28
                });                                                                                            // Waterfall cutscene
            }));
            RoomTriggers.Add(new RoomTrigger(3, 28, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (!seedOptions.Inverted)
                {
                    return;
                }
                CreateAndCallCutsceneMethod.InvokeStatic(CutsceneEnumType.GetEnumValue("Forest0_Warp"), level, new Point(200, 200));
            }));
            RoomTriggers.Add(new RoomTrigger(1, 5, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Boots
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.FelineSentry);

                if (!itemLocation.IsPickedUp &&
                    level.GameSave.GetSaveBool("TSRando_IsBossDead_RoboKitty") &&
                    level.AsDynamic()._newObjects.Count == 0)                        // Orb Pedestal event
                {
                    SpawnItemDropPickup(level, itemLocation.ItemInfo, 200, 208);
                }
            }));
            RoomTriggers.Add(new RoomTrigger(2, 29, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Varndagroth
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Varndagroth);

                if (!itemLocation.IsPickedUp &&
                    level.GameSave.GetSaveBool("TSRando_IsBossDead_Varndagroth"))
                {
                    SpawnItemDropPickup(level, itemLocation.ItemInfo, 280, 222);
                }
            }));
            RoomTriggers.Add(new RoomTrigger(7, 0, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Azure Queen
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.AzureQueen);
            }));
            RoomTriggers.Add(new RoomTrigger(6, 15, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Aelana
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Aelana);
            }));
            RoomTriggers.Add(new RoomTrigger(8, 7, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Maw
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                if (seedOptions.GasMaw && !level.GameSave.GetSettings().BossRando.Value)
                {
                    FillRoomWithGas(level);
                }
                CreateBossWarp(level, (int)EBossID.Maw);
            }));
            RoomTriggers.Add(new RoomTrigger(12, 20, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Nuvius
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Nuvius);
            }));
            RoomTriggers.Add(new RoomTrigger(13, 1, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Terrilis
                if (level.GameSave.GetSettings().BossRando.Value)
                {
                    CreateAndCallCutsceneMethod.InvokeStatic(CutsceneEnumType.GetEnumValue("Alt1_Vol"), level, new Point(200, 200));
                }
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Vol);
            }));
            RoomTriggers.Add(new RoomTrigger(13, 0, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Prince
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Prince);
            }));
            RoomTriggers.Add(new RoomTrigger(9, 7, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Xarion
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Xarion);
            }));
            RoomTriggers.Add(new RoomTrigger(14, 4, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Ravenlord
                if (level.GameSave.GetSettings().BossRando.Value)
                {
                    SpawnMovingPlatform(level, 185, 520);
                    SpawnMovingPlatform(level, 615, 520);
                    SpawnCirclePlatform(level, 185, 415, true);
                    SpawnCirclePlatform(level, 615, 415, false);
                    SpawnMovingPlatform(level, 185, 220);
                    SpawnMovingPlatform(level, 615, 220);
                }

                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Ravenlord);
            }));
            RoomTriggers.Add(new RoomTrigger(14, 5, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Ifrit
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Ifrit);
            }));
            RoomTriggers.Add(new RoomTrigger(16, 4, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Sandman
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Sandman);
            }));
            RoomTriggers.Add(new RoomTrigger(16, 5, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Clear final boss saves
                level.GameSave.SetValue("TSRando_IsBossDead_Sandman", false);
                level.GameSave.SetValue("TSRando_IsBossDead_Nightmare", false);
            }));
            RoomTriggers.Add(new RoomTrigger(16, 26, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Nightmare
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Nightmare);
            }));

            RoomTriggers.Add(new RoomTrigger(5, 5, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Golden Idol
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.GoldenIdol);

                if (!itemLocation.IsPickedUp &&
                    level.GameSave.GetSaveBool("TSRando_IsBossDead_Demon") &&
                    level.GameSave.HasRelic(EInventoryRelicType.DoubleJump))
                {
                    SpawnItemDropPickup(level, itemLocation.ItemInfo, 200, 200);
                }
            }));
            RoomTriggers.Add(new RoomTrigger(11, 21, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }
                CreateBossWarp(level, (int)EBossID.Genza);

                if (!itemLocation.IsPickedUp &&
                    level.GameSave.GetSaveBool("TSRando_IsBossDead_Shapeshift") &&
                    level.GameSave.HasRelic(EInventoryRelicType.ScienceKeycardA))
                {
                    SpawnItemDropPickup(level, itemLocation.ItemInfo, 200, 200);
                }

                if (!seedOptions.Inverted && level.GameSave.HasCutsceneBeenTriggered("Alt3_Teleport"))
                {
                    CreateSimpleOneWayWarp(level, 16, 12);
                }
            }));
            RoomTriggers.Add(new RoomTrigger(7, 5, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                SpawnBoss(level, seedOptions, TargetBossId);
                if (level.GameSave.GetSaveBool("IsFightingBoss"))
                {
                    return;
                }

                // Set Cantoran quest active when fighting Pink Bird
                if (!level.GameSave.GetSaveBool("TSRando_IsPinkBirdDead"))
                {
                    level.GameSave.SetValue("TSRando_IsPinkBirdDead", true);
                    BestiaryManager.RefreshBossSaveFlags(level);
                    return;
                }

                if (!seedOptions.Cantoran)
                {
                    return;
                }

                CreateBossWarp(level, (int)EBossID.Cantoran);

                if (!itemLocation.IsPickedUp &&
                    level.GameSave.GetSaveBool("TSRando_IsBossDead_Cantoran") &&
                    level.AsDynamic()._newObjects.Count == 0)                        // Orb Pedestal event
                {
                    SpawnItemDropPickup(level, itemLocation.ItemInfo, 170, 194);
                }
            }));

            RoomTriggers.Add(new RoomTrigger(11, 1, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (itemLocation.IsPickedUp || !level.GameSave.HasRelic(EInventoryRelicType.Dash))
                {
                    return;
                }

                SpawnItemDropPickup(level, itemLocation.ItemInfo, 280, 191);
            }));
            RoomTriggers.Add(new RoomTrigger(11, 39, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (itemLocation.IsPickedUp ||
                    !level.GameSave.HasOrb(EInventoryOrbType.Eye) ||
                    !level.GameSave.GetSaveBool("11_LabPower"))
                {
                    return;
                }

                SpawnItemDropPickup(level, itemLocation.ItemInfo, 200, 176);
            }));
            RoomTriggers.Add(new RoomTrigger(11, 26, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (itemLocation.IsPickedUp ||
                    !level.GameSave.HasRelic(EInventoryRelicType.TimespinnerGear1))
                {
                    return;
                }

                SpawnTreasureChest(level, true, 136, 192);
            }));
            RoomTriggers.Add(new RoomTrigger(2, 52, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (itemLocation.IsPickedUp ||
                    !level.GameSave.HasRelic(EInventoryRelicType.TimespinnerGear2))
                {
                    return;
                }

                SpawnTreasureChest(level, true, 104, 192);
            }));
            RoomTriggers.Add(new RoomTrigger(9, 13, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (itemLocation.IsPickedUp ||
                    !level.GameSave.HasRelic(EInventoryRelicType.TimespinnerGear3))
                {
                    return;
                }

                SpawnTreasureChest(level, false, 296, 176);
            }));
            RoomTriggers.Add(new RoomTrigger(3, 6, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (seedOptions.Inverted || level.GameSave.HasRelic(EInventoryRelicType.PyramidsKey))
                {
                    return;
                }

                CreateSimpleOneWayWarp(level, 2, 54);
            }));
            RoomTriggers.Add(new RoomTrigger(2, 54, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (seedOptions.Inverted ||
                    level.GameSave.HasRelic(EInventoryRelicType.PyramidsKey) ||
                    !level.GameSave.DataKeyBools.ContainsKey("HasUsedCityTS"))
                {
                    return;
                }

                CreateSimpleOneWayWarp(level, 3, 6);
            }));
            RoomTriggers.Add(new RoomTrigger(7, 30, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (!level.GameSave.HasRelic(EInventoryRelicType.PyramidsKey))
                {
                    return;
                }

                SpawnTreasureChest(level, false, 296, 176);
            }));
            RoomTriggers.Add(new RoomTrigger(3, 0, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (itemLocation.IsPickedUp ||
                    level.GameSave.DataKeyBools.ContainsKey("HasUsedCityTS") ||
                    !level.GameSave.HasCutsceneBeenTriggered("Forest3_Haristel") ||
                    ((Dictionary <int, NPCBase>)level.AsDynamic()._npcs).Values.Any(npc => npc.GetType() == NelisteNpcType))
                {
                    return;
                }

                SpawnNeliste(level);
            }));
            // Spawn Gyre portals when applicable
            RoomTriggers.Add(new RoomTrigger(11, 4, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (!seedOptions.GyreArchives || !level.GameSave.HasFamiliar(EInventoryFamiliarType.MerchantCrow))
                {
                    return;
                }

                SpawnGyreWarp(level, 200, 200);                 // Historical Documents room to Ravenlord
            }));
            RoomTriggers.Add(new RoomTrigger(14, 8, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Reset boss save flags cleared by Gyre portal
                BestiaryManager.RefreshBossSaveFlags(level);
            }));
            RoomTriggers.Add(new RoomTrigger(14, 24, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (!seedOptions.GyreArchives)
                {
                    return;
                }

                level.JukeBox.StopSong();

                level.RequestChangeLevel(new LevelChangeRequest
                {
                    LevelID             = 11,
                    RoomID              = 4,
                    IsUsingWarp         = true,
                    IsUsingWhiteFadeOut = true,
                    FadeInTime          = 0.5f,
                    FadeOutTime         = 0.25f
                });                 // Ravenlord to Historical Documents room

                level.JukeBox.PlaySong(Timespinner.GameAbstractions.EBGM.Level11);
            }));
            RoomTriggers.Add(new RoomTrigger(2, 51, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (!seedOptions.GyreArchives)
                {
                    return;
                }
                if (level.GameSave.HasFamiliar(EInventoryFamiliarType.Kobo))
                {
                    SpawnGyreWarp(level, 200, 200);                     // Portrait room to Ifrit
                    return;
                }
                ;

                if (((Dictionary <int, NPCBase>)level.AsDynamic()._npcs).Values.Any(npc => npc.GetType() == YorneNpcType))
                {
                    return;
                }
                SpawnYorne(level);                 // Dialog for needing Kobo
            }));
            RoomTriggers.Add(new RoomTrigger(14, 6, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Reset boss save flags cleared by Gyre portal
                BestiaryManager.RefreshBossSaveFlags(level);
            }));
            RoomTriggers.Add(new RoomTrigger(14, 25, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (!seedOptions.GyreArchives)
                {
                    return;
                }
                level.JukeBox.StopSong();
                level.RequestChangeLevel(new LevelChangeRequest
                {
                    LevelID             = 2,
                    RoomID              = 51,
                    IsUsingWarp         = true,
                    IsUsingWhiteFadeOut = true,
                    FadeInTime          = 0.5f,
                    FadeOutTime         = 0.25f
                });                 // Ifrit to Portrait room
                level.JukeBox.PlaySong(Timespinner.GameAbstractions.EBGM.Library);
            }));
            RoomTriggers.Add(new RoomTrigger(10, 0, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Spawn warp after ship crashes
                if (!seedOptions.GyreArchives || !level.GameSave.GetSaveBool("IsPastCleared"))
                {
                    return;
                }
                SpawnGyreWarp(level, 340, 180);                 // Military Hangar crash site to Gyre
            }));
            RoomTriggers.Add(new RoomTrigger(14, 11, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Play Gyre music in gyre
                level.JukeBox.PlaySong(Timespinner.GameAbstractions.EBGM.Level14);
                level.AsDynamic().SetLevelSaveInt("GyreDungeonSeed", (int)level.GameSave.GetSeed().Value.Id); // Set Gyre enemies
                BestiaryManager.RefreshBossSaveFlags(level);                                                  // Reset boss save flags cleared by Gyre portal
            }));
            RoomTriggers.Add(new RoomTrigger(14, 23, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                level.JukeBox.StopSong();
                level.RequestChangeLevel(new LevelChangeRequest
                {
                    LevelID             = 10,
                    RoomID              = 0,
                    IsUsingWarp         = true,
                    IsUsingWhiteFadeOut = true,
                    FadeInTime          = 0.5f,
                    FadeOutTime         = 0.25f
                });                 // Military Hangar crash site
                level.JukeBox.PlaySong(Timespinner.GameAbstractions.EBGM.Level10);
            }));
            RoomTriggers.Add(new RoomTrigger(12, 11, (level, itemLocation, seedOptions, gameSettings, screenManager) =>             // Remove Daddy's pedestal if you havent killed him yet
            {
                if (level.GameSave.GetSaveBool("TSRando_IsBossDead_Emperor"))
                {
                    return;
                }

                ((Dictionary <int, GameEvent>)level.AsDynamic()._levelEvents).Values
                .FirstOrDefault(obj => obj.GetType() == PedestalType)
                ?.SilentKill();
            }));
            RoomTriggers.Add(new RoomTrigger(8, 6, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (!seedOptions.GasMaw)
                {
                    return;
                }

                FillRoomWithGas(level);
            }));
            RoomTriggers.Add(new RoomTrigger(8, 13, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (seedOptions.GasMaw)
                {
                    FillRoomWithGas(level);
                }
                if (!level.GameSave.GetSaveBool("TSRando_IsBossDead_Maw"))
                {
                    return;
                }
                level.GameSave.SetValue("TSRando_IsVileteSaved", true);
                if (gameSettings.BossRando.Value &&
                    !level.GameSave.GetSaveBool("IsVileteSaved"))
                {
                    var enumValue = CutsceneEnumType.GetEnumValue("CavesPast6_MawBoom");
                    CreateAndCallCutsceneMethod.InvokeStatic(enumValue, level, new Point(200, 200));
                }
                BestiaryManager.RefreshBossSaveFlags(level);
            }));
            RoomTriggers.Add(new RoomTrigger(8, 21, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (seedOptions.GasMaw)
                {
                    FillRoomWithGas(level);
                }

                var levelReflected = level.AsDynamic();
                IEnumerable <Animate> eventObjects = levelReflected._levelEvents.Values;

                if (!itemLocation.IsPickedUp &&
                    !eventObjects.Any(o => o.GetType().ToString() ==
                                      "Timespinner.GameObjects.Events.EnvironmentPrefabs.EnvPrefabCavesRadiationCrystal"))
                {
                    SpawnItemDropPickup(level, itemLocation.ItemInfo, 312, 912);
                }
            }));
            RoomTriggers.Add(new RoomTrigger(8, 33, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                if (!seedOptions.GasMaw)
                {
                    return;
                }

                FillRoomWithGas(level);
            }));
            RoomTriggers.Add(new RoomTrigger(16, 1, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Allow the post-Nightmare chest to spawn
                level.GameSave.SetValue("IsGameCleared", true);
                level.GameSave.SetValue("IsEndingCDCleared", true);
            }));
            RoomTriggers.Add(new RoomTrigger(16, 21, (level, itemLocation, seedOptions, gameSettings, screenManager) => {
                // Spawn glowing floor event to give a soft-lock exit warp
                if (((Dictionary <int, NPCBase>)level.AsDynamic()._npcs).Values.Any(npc => npc.GetType() == GlowingFloorEventType))
                {
                    return;
                }
                SpawnGlowingFloor(level);
            }));
            RoomTriggers.Add(new RoomTrigger(16, 27, (level, itemLocation, seedOptions, gameSettings, screenManager) =>
            {
                // Post-Nightmare void
                if (level.GameSave.GetSettings().BossRando.Value)
                {
                    var enumValue = CutsceneEnumType.GetEnumValue("Temple2_End");
                    CreateAndCallCutsceneMethod.InvokeStatic(enumValue, level, new Point(200, 200));
                }
                level.JukeBox.StopSong();

                if (!level.GameSave.DataKeyStrings.ContainsKey(ArchipelagoItemLocationRandomizer.GameSaveServerKey))
                {
                    return;
                }
                Client.SetStatus(ArchipelagoClientState.ClientGoal);
                AskPermissionMessage(screenManager, "collect", Client.CollectPermissions);
                AskPermissionMessage(screenManager, "forfeit", Client.ForfeitPermissions);
            }));
        }