public void CreateEnabledEntry(TextMenu menu, bool inGame)
        {
            TextMenu.OnOff button = new TextMenu.OnOff(DialogIds.Enabled.DialogClean(), Enabled)
            {
                OnValueChange = value => {
                    Enabled = value;

                    bool mineItem       = false;
                    int  mineItemsCount = 2;
                    foreach (TextMenu.Item item in menu.Items)
                    {
                        if (item == menu.Current && !mineItem)
                        {
                            mineItem = true;
                            continue;
                        }

                        if (!mineItem || mineItemsCount <= 0)
                        {
                            continue;
                        }

                        mineItemsCount--;
                        item.Visible = value;
                    }
                }
            };

            menu.Add(button);
        }
Beispiel #2
0
        public static void CreateMenu(EverestModule everestModule, TextMenu menu, bool inGame)
        {
            TextMenu.Item enabledItem = new TextMenu.OnOff("Enabled".ToDialogText(), Settings.Enabled).Change((value) => {
                Settings.Enabled = value;
                foreach (TextMenu.Item item in options)
                {
                    item.Visible = value;
                }
            });
            menu.Add(enabledItem);
            CreateOptions(everestModule, menu, inGame);
            foreach (TextMenu.Item item in options)
            {
                menu.Add(item);
                item.Visible = Settings.Enabled;
            }

            foreach (string text in Split(InputController.TasFilePath, 60).Reverse())
            {
                enabledItem.AddDescription(menu, text);
            }

            enabledItem.AddDescription(menu, "Working TAS File Path:");

            HitboxTweak.AddSubMenuDescription(menu, inGame);
            InfoHud.AddSubMenuDescription(menu);
            keyConfigButton.AddDescription(menu, "Key Config Description".ToDialogText());
        }
 public void CreateLogToIngameConsoleEntry(TextMenu textMenu, bool inGame)
 {
     TextMenu.Item item = new TextMenu.OnOff("Log to ingame console [DEBUG]", LogToIngameConsole)
                          .Change(value => {
         LogToIngameConsole = value;
     });
     textMenu.Add(item);
 }
 public void CreateBackupAsZipFileEntry(TextMenu textMenu, bool inGame)
 {
     TextMenu.Item item = new TextMenu.OnOff(DialogId.Options.BackupAsZipFile.DialogClean(), BackupAsZipFile)
                          .Change(value => {
         BackupAsZipFile = value;
     });
     textMenu.Add(item);
     menuItems.Add(DialogId.Options.BackupAsZipFile, item);
 }
 public void CreateAutoDeleteOldBackupsEntry(TextMenu textMenu, bool inGame)
 {
     TextMenu.Item item = new TextMenu.OnOff(DialogId.Options.AutoDeleteOldBackups.DialogClean(), AutoDeleteOldBackups)
                          .Change(value => {
         AutoDeleteOldBackups = value;
         RefreshItemsStates();
     });
     textMenu.Add(item);
     menuItems.Add(DialogId.Options.AutoDeleteOldBackups, item);
 }
        public static void CreateMenu(EverestModule everestModule, TextMenu menu, bool inGame)
        {
            List <TextMenuExt.EaseInSubHeaderExt> enabledDescriptions = new();

            TextMenuExt.EaseInSubHeaderExt AddEnabledDescription(TextMenu.Item enabledItem, TextMenu containingMenu, string description)
            {
                TextMenuExt.EaseInSubHeaderExt descriptionText = new(description, false, containingMenu) {
                    TextColor   = Color.Gray,
                    HeightExtra = 0f
                };

                List <TextMenu.Item> items = containingMenu.GetItems();

                if (items.Contains(enabledItem))
                {
                    containingMenu.Insert(items.IndexOf(enabledItem) + 1, descriptionText);
                }

                enabledItem.OnEnter += () => descriptionText.FadeVisible = Settings.Enabled;
                enabledItem.OnLeave += () => descriptionText.FadeVisible = false;

                return(descriptionText);
            }

            TextMenu.Item enabledItem = new TextMenu.OnOff("Enabled".ToDialogText(), Settings.Enabled).Change((value) => {
                Settings.Enabled = value;
                foreach (EaseInSubMenu easeInSubMenu in options)
                {
                    easeInSubMenu.FadeVisible = value;
                }

                foreach (TextMenuExt.EaseInSubHeaderExt easeInSubHeader in enabledDescriptions)
                {
                    easeInSubHeader.FadeVisible = value;
                }
            });
            menu.Add(enabledItem);
            CreateOptions(everestModule, menu, inGame);
            foreach (EaseInSubMenu easeInSubMenu in options)
            {
                menu.Add(easeInSubMenu);
            }

            foreach (string text in Split(InputController.TasFilePath, 60).Reverse())
            {
                enabledDescriptions.Add(AddEnabledDescription(enabledItem, menu, text));
            }

            enabledDescriptions.Add(AddEnabledDescription(enabledItem, menu, "Enabled Description".ToDialogText()));

            HitboxMenu.AddSubMenuDescription(menu, inGame);
            InfoHud.AddSubMenuDescription(menu);
            hotkeysSubMenu.AddDescription(menu, "Hotkeys Description".ToDialogText());
        }
 public void CreateConnectionEntry(TextMenu menu, bool inGame)
 {
     if (Celeste.PlayMode == Celeste.PlayModes.Debug)
     {
         menu.Add(new TextMenu.SubHeader("modoptions_ghostnetmodule_debugwarn".DialogCleanOrNull() ?? "WARNING: DEBUG MODE DETECTED!"));
     }
     menu.Add(
         (EnabledEntry = new TextMenu.OnOff("modoptions_ghostnetmodule_connected".DialogCleanOrNull() ?? "Connected", Connection))
         .Change(v => Connection = v)
         );
 }
 public void CreateEnabledEntry(TextMenu textMenu, bool inGame)
 {
     TextMenu.Item item = new TextMenu.OnOff(DialogId.Options.Enabled.DialogClean(), Enabled)
                          .Change(value => {
         Enabled = value;
         if (Enabled)
         {
             InfiniteBackupsModule.Instance.Load();
         }
         else
         {
             InfiniteBackupsModule.Instance.Unload();
         }
         RefreshItemsStates();
     });
     textMenu.Add(item);
     menuItems.Add(DialogId.Options.Enabled, item);
 }
        public void CreateMasterSwitchEntry(TextMenu menu, bool inGame)
        {
            if (inGame)
            {
                return;
            }

            var toggle = new TextMenu.OnOff(Dialog.Clean("modoptions_bingoclient_masterswitch"), this.MasterSwitch);

            toggle.OnValueChange = v => {
                this.MasterSwitch = v;
                if (v)
                {
                    BingoClient.Instance.HookStuff();
                }
                else
                {
                    BingoClient.Instance.UnhookStuff();
                }
            };
            menu.Add(toggle);
        }
Beispiel #10
0
        private void ReloadMenu()
        {
            menu = new DisablableTextMenu {
                new TextMenu.Header(Dialog.Clean("MODOPTIONS_RANDOMIZER_HEADER"))
            };

            var hashtext = new TextMenuExt.EaseInSubHeaderExt("{hash}", true, menu)
            {
                HeightExtra = -10f,
                Offset      = new Vector2(30, -5),
            };

            void updateHashText()
            {
                hashtext.Title = "v" + RandoModule.Instance.Metadata.VersionString;
                if (Settings.SeedType == SeedType.Custom)
                {
                    hashtext.Title += " #" + Settings.Hash.ToString();
                }
            }

            updateHashText();

            var errortext = new TextMenuExt.EaseInSubHeaderExt("{error}", false, menu)
            {
                HeightExtra = -10f,
                Offset      = new Vector2(30, -5),
            };

            var seedbutton = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_SEED") + ": " + Settings.Seed);

            seedbutton.Pressed(() => {
                Audio.Play(SFX.ui_main_savefile_rename_start);
                menu.SceneAs <Overworld>().Goto <UI.OuiTextEntry>().Init <OuiRandoSettings>(
                    Settings.Seed,
                    (v) => Settings.Seed = v,
                    RandoModule.MAX_SEED_CHARS
                    );
            });
            seedbutton.Visible = Settings.SeedType == SeedType.Custom;

            var seedtypetoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_SEEDTYPE"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_SEEDTYPE_" + Enum.GetNames(typeof(SeedType))[i].ToUpperInvariant()));
            }, 0, (int)SeedType.Last - 1, (int)Settings.SeedType).Change((i) => {
                Settings.SeedType  = (SeedType)i;
                seedbutton.Visible = Settings.SeedType == SeedType.Custom;
                // just in case...
                seedbutton.Label = Dialog.Clean("MODOPTIONS_RANDOMIZER_SEED") + ": " + Settings.Seed;
                updateHashText();
            });

            var mapbutton = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER")).Pressed(() => {
                Audio.Play(SFX.ui_main_button_select);
                menu.SceneAs <Overworld>().Goto <OuiMapPicker>();
            });

            var mapcountlbl = new TextMenuExt.SubHeaderExt(Settings.LevelCount.ToString() + " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_LEVELS"))
            {
                HeightExtra = -10f,
                Offset      = new Vector2(30, -5),
            };

            var logictoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_LOGIC"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_LOGIC_" + Enum.GetNames(typeof(LogicType))[i].ToUpperInvariant()));
            }, 0, (int)LogicType.Last - 1, (int)Settings.Algorithm).Change((i) => {
                Settings.Algorithm = (LogicType)i;
                updateHashText();
            });

            var lengthtoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_LENGTH"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_LENGTH_" + Enum.GetNames(typeof(MapLength))[i].ToUpperInvariant()));
            }, 0, (int)MapLength.Last - 1, (int)Settings.Length).Change((i) => {
                Settings.Length = (MapLength)i;
                updateHashText();
            });

            var numdashestoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_NUMDASHES"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_NUMDASHES_" + Enum.GetNames(typeof(NumDashes))[i].ToUpperInvariant()));
            }, 0, (int)NumDashes.Last - 1, (int)Settings.Dashes).Change((i) => {
                Settings.Dashes = (NumDashes)i;
                updateHashText();
            });

            var difficultytoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_DIFFICULTY"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_DIFFICULTY_" + Enum.GetNames(typeof(Difficulty))[i].ToUpperInvariant()));
            }, 0, (int)Difficulty.Last - 1, (int)Settings.Difficulty).Change((i) => {
                Settings.Difficulty = (Difficulty)i;
                updateHashText();
            });

            var repeatroomstoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_REPEATROOMS"), Settings.RepeatRooms).Change((val) => {
                Settings.RepeatRooms = val;
                updateHashText();
            });

            var enterunknowntext = new TextMenuExt.EaseInSubHeaderExt(Dialog.Clean("MODOPTIONS_RANDOMIZER_ENTERUNKNOWN_EXPLAIN"), false, menu)
            {
                HeightExtra = 17f,
                Offset      = new Vector2(30, -5),
            };

            var enterunknowntoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_ENTERUNKNOWN"), Settings.EnterUnknown).Change((val) => {
                Settings.EnterUnknown = val;
                updateHashText();
            });

            enterunknowntoggle.OnEnter += () => { enterunknowntext.FadeVisible = true; };
            enterunknowntoggle.OnLeave += () => { enterunknowntext.FadeVisible = false; };

            var shinetoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_SHINE"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_SHINE_" + Enum.GetNames(typeof(ShineLights))[i].ToUpperInvariant()));
            }, 0, (int)ShineLights.Last - 1, (int)Settings.Lights).Change((i) => {
                Settings.Lights = (ShineLights)i;
                updateHashText();
            });

            var darktoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_DARK"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_DARK_" + Enum.GetNames(typeof(Darkness))[i].ToUpperInvariant()));
            }, 0, (int)Darkness.Last - 1, (int)Settings.Darkness).Change((i) => {
                Settings.Darkness = (Darkness)i;
                updateHashText();
            });

            var goldentoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_GOLDENBERRY"), Settings.SpawnGolden).Change((val) => {
                Settings.SpawnGolden = val;
            });

            var moreoptions = false;

            repeatroomstoggle.Visible  = false;
            enterunknowntoggle.Visible = false;
            goldentoggle.Visible       = false;
            shinetoggle.Visible        = false;
            darktoggle.Visible         = false;

            var moreoptionsbtn = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_MOREOPTIONS"));

            moreoptionsbtn.Pressed(() => {
                moreoptions          = !moreoptions;
                moreoptionsbtn.Label = moreoptions ? Dialog.Clean("MODOPTIONS_RANDOMIZER_FEWEROPTIONS") : Dialog.Clean("MODOPTIONS_RANDOMIZER_MOREOPTIONS");

                repeatroomstoggle.Visible  = moreoptions;
                enterunknowntoggle.Visible = moreoptions;
                goldentoggle.Visible       = moreoptions;
                shinetoggle.Visible        = moreoptions;
                darktoggle.Visible         = moreoptions;
            });

            void syncModel()
            {
                repeatroomstoggle.Index  = Settings.RepeatRooms ? 1 : 0;
                enterunknowntoggle.Index = Settings.EnterUnknown ? 1 : 0;
                logictoggle.Index        = (int)Settings.Algorithm;
                lengthtoggle.Index       = (int)Settings.Length;
                numdashestoggle.Index    = (int)Settings.Dashes;
                difficultytoggle.Index   = (int)Settings.Difficulty;
                shinetoggle.Index        = (int)Settings.Lights;
                darktoggle.Index         = (int)Settings.Darkness;
                mapcountlbl.Title        = Settings.LevelCount.ToString() + " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_LEVELS");

                var locked = Settings.Rules != Ruleset.Custom;

                mapbutton.Disabled          = locked;
                repeatroomstoggle.Disabled  = locked;
                enterunknowntoggle.Disabled = locked;
                logictoggle.Disabled        = locked;
                lengthtoggle.Disabled       = locked;
                numdashestoggle.Disabled    = locked;
                difficultytoggle.Disabled   = locked;
                shinetoggle.Disabled        = locked;
                darktoggle.Disabled         = locked;
            }

            syncModel();

            var rulestoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_RULES"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_RULES_" + Enum.GetNames(typeof(Ruleset))[i].ToUpperInvariant()));
            }, 0, (int)Ruleset.Last - 1, (int)Settings.Rules).Change((i) => {
                Settings.Rules = (Ruleset)i;
                Settings.Enforce();
                syncModel();
                updateHashText();
            });

            var startbutton = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_START"));

            startbutton.Pressed(() => {
                if (this.entering)
                {
                    return;
                }

                void reenableMenu()
                {
                    this.builderThread = null;

                    startbutton.Label = Dialog.Clean("MODOPTIONS_RANDOMIZER_START");
                    updateHashText();
                    menu.DisableMovement = false;
                }

                if (this.builderThread == null)
                {
                    errortext.FadeVisible = false;
                    startbutton.Label     = Dialog.Clean("MODOPTIONS_RANDOMIZER_CANCEL");
                    hashtext.Title       += " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_GENERATING");
                    menu.DisableMovement  = true;

                    this.builderThread = new Thread(() => {
                        Settings.Enforce();
                        AreaKey newArea;
                        try {
                            newArea = RandoLogic.GenerateMap(Settings);
                        } catch (ThreadAbortException) {
                            return;
                        } catch (Exception e) {
                            if (e.Message == "Could not generate map")
                            {
                                errortext.Title = e.Message;
                            }
                            else
                            {
                                errortext.Title = "Encountered an error - Check log.txt for details";
                                Logger.LogDetailed(e, "randomizer");
                            }
                            errortext.FadeVisible = true;
                            reenableMenu();
                            return;
                        }
                        this.entering = true;

                        Audio.SetMusic((string)null, true, true);
                        Audio.SetAmbience((string)null, true);
                        Audio.Play("event:/ui/main/savefile_begin");

                        // use the debug file
                        SaveData.InitializeDebugMode();
                        // turn on variants mode
                        SaveData.Instance.VariantMode = true;
                        SaveData.Instance.AssistMode  = false;
                        // clear summit gems, just in case!
                        SaveData.Instance.SummitGems = new bool[6];
                        // mark as completed to spawn golden berry
                        SaveData.Instance.Areas[newArea.ID].Modes[0].Completed = true;

                        var fade = new FadeWipe(this.Scene, false, () => {   // assign to variable to suppress compiler warning
                            var session = new Session(newArea, null, null);
                            //session.FirstLevel = false;   // setting this value here prevents the wakeup animation. set it in a hook.
                            LevelEnter.Go(session, true);
                            this.builderThread = null;
                            this.entering      = false;
                        });

                        /*foreach (AreaData area in AreaData.Areas) {
                         *  Logger.Log("randomizer", $"Skeleton for {area.GetSID()}");
                         *  RandoConfigFile.YamlSkeleton(area);
                         *
                         * }*/
                    });
                    this.builderThread.Start();
                }
                else
                {
                    this.builderThread.Abort();
                    reenableMenu();
                }
            });

            menu.Add(seedtypetoggle);
            menu.Add(seedbutton);
            menu.Add(rulestoggle);
            menu.Add(mapbutton);
            menu.Add(mapcountlbl);
            menu.Add(logictoggle);
            menu.Add(lengthtoggle);
            menu.Add(numdashestoggle);
            menu.Add(difficultytoggle);
            menu.Add(moreoptionsbtn);
            menu.Add(repeatroomstoggle);
            menu.Add(enterunknowntoggle);
            menu.Add(enterunknowntext);
            menu.Add(shinetoggle);
            menu.Add(darktoggle);
            menu.Add(goldentoggle);
            menu.Add(startbutton);
            menu.Add(hashtext);
            menu.Add(errortext);

            Scene.Add(menu);
        }
Beispiel #11
0
        /// <summary>
        /// Create the mod menu subsection including the section header in the given menu.
        /// The default implementation uses reflection to attempt creating a menu.
        /// </summary>
        /// <param name="menu">Menu to add the section to.</param>
        /// <param name="inGame">Whether we're in-game (paused) or in the main menu.</param>
        /// <param name="snapshot">The Level.PauseSnapshot</param>
        public virtual void CreateModMenuSection(TextMenu menu, bool inGame, EventInstance snapshot)
        {
            Type type = SettingsType;
            EverestModuleSettings settings = _Settings;

            if (type == null || settings == null)
            {
                return;
            }

            // The default name prefix.
            string typeName = type.Name.ToLowerInvariant();

            if (typeName.EndsWith("settings"))
            {
                typeName = typeName.Substring(0, typeName.Length - 8);
            }
            string nameDefaultPrefix = $"modoptions_{typeName}_";

            // Any attributes we may want to get and read from later.
            SettingInGameAttribute attribInGame;
            SettingRangeAttribute  attribRange;

            // If the settings type has got the InGame attrib, only show it in the matching situation.
            if ((attribInGame = type.GetCustomAttribute <SettingInGameAttribute>()) != null &&
                attribInGame.InGame != inGame)
            {
                return;
            }

            // The settings subheader.
            string name; // We lazily reuse this field for the props later on.

            name = type.GetCustomAttribute <SettingNameAttribute>()?.Name ?? $"{nameDefaultPrefix}title";
            name = name.DialogCleanOrNull() ?? Metadata.Name.SpacedPascalCase();

            menu.Add(new TextMenu.SubHeader(name + " | v." + Metadata.VersionString));

            PropertyInfo[] props;
            if (type == _PrevSettingsType)
            {
                props = _PrevSettingsProps;
            }
            else
            {
                _PrevSettingsProps = props = type.GetProperties();
                _PrevSettingsType  = type;
            }

            foreach (PropertyInfo prop in props)
            {
                MethodInfo creator = type.GetMethod(
                    $"Create{prop.Name}Entry",
                    BindingFlags.Public | BindingFlags.Instance,
                    null,
                    new Type[] { typeof(TextMenu), typeof(bool) },
                    new ParameterModifier[0]
                    );

                if (creator != null)
                {
                    creator.GetFastDelegate()(settings, menu, inGame);
                    continue;
                }

                if ((attribInGame = prop.GetCustomAttribute <SettingInGameAttribute>()) != null &&
                    attribInGame.InGame != inGame)
                {
                    continue;
                }

                if (prop.GetCustomAttribute <SettingIgnoreAttribute>() != null)
                {
                    continue;
                }

                if (!prop.CanRead || !prop.CanWrite)
                {
                    continue;
                }

                name = prop.GetCustomAttribute <SettingNameAttribute>()?.Name ?? $"{nameDefaultPrefix}{prop.Name.ToLowerInvariant()}";
                name = name.DialogCleanOrNull() ?? prop.Name.SpacedPascalCase();

                bool needsRelaunch = prop.GetCustomAttribute <SettingNeedsRelaunchAttribute>() != null;

                TextMenu.Item item     = null;
                Type          propType = prop.PropertyType;
                object        value    = prop.GetValue(settings);

                // Create the matching item based off of the type and attributes.

                if (propType == typeof(bool))
                {
                    item =
                        new TextMenu.OnOff(name, (bool)value)
                        .Change(v => prop.SetValue(settings, v))
                    ;
                }
                else if (
                    propType == typeof(int) &&
                    (attribRange = prop.GetCustomAttribute <SettingRangeAttribute>()) != null
                    )
                {
                    item =
                        new TextMenu.Slider(name, i => i.ToString(), attribRange.Min, attribRange.Max, (int)value)
                        .Change(v => prop.SetValue(settings, v))
                    ;
                }
                else if (propType.IsEnum)
                {
                    Array enumValues = Enum.GetValues(propType);
                    Array.Sort((int[])enumValues);
                    string enumNamePrefix = $"{nameDefaultPrefix}{prop.Name.ToLowerInvariant()}_";
                    item =
                        new TextMenu.Slider(name, (i) => {
                        string enumName = enumValues.GetValue(i).ToString();
                        string fullName = $"{enumNamePrefix}{enumName.ToLowerInvariant()}";
                        return(fullName.DialogCleanOrNull() ?? enumName);
                    }, 0, enumValues.Length - 1, (int)value)
                        .Change(v => prop.SetValue(settings, v))
                    ;
                }
                else if (!inGame && propType == typeof(string))
                {
                    item =
                        new TextMenu.Button(name + ": " + value)
                        .Pressed(() => {
                        Audio.Play(Sfxs.ui_main_savefile_rename_start);
                        menu.SceneAs <Overworld>().Goto <OuiModOptionString>().Init <OuiModOptions>(
                            (string)value,
                            v => prop.SetValue(settings, v)
                            );
                    })
                    ;
                }

                if (item == null)
                {
                    continue;
                }

                if (needsRelaunch)
                {
                    item = item.NeedsRelaunch();
                }

                menu.Add(item);
            }
        }
        private void ReloadMenu()
        {
            menu = new TextMenu {
                new TextMenu.Header(Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_HEADER")),
                new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_TOGGLEALL")).Pressed(() => {
                    var items = menu.GetItems();
                    TextMenu.OnOff firstToggle = null;
                    foreach (var item in items)
                    {
                        if (item is TextMenu.OnOff)
                        {
                            firstToggle = item as TextMenu.OnOff;
                            break;
                        }
                    }
                    if (firstToggle == null)
                    {
                        // ???
                        return;
                    }

                    var newValue = 1 - firstToggle.Index;
                    for (int i = 0; i < items.Count; i++)
                    {
                        if (items[i] is TextMenu.OnOff toggle)
                        {
                            toggle.Index = newValue;
                            toggle.OnValueChange(toggle.Values[newValue].Item2);
                        }
                    }
                }),
            };

            var lvlCount = new Dictionary <RandoSettings.AreaKeyNotStupid, int>();

            foreach (var room in RandoLogic.AllRooms)
            {
                var notstupid = new RandoSettings.AreaKeyNotStupid(room.Area);
                if (lvlCount.TryGetValue(notstupid, out int c))
                {
                    lvlCount[notstupid] = c + 1;
                }
                else
                {
                    lvlCount[notstupid] = 1;
                }
            }
            string currentSet = null;

            foreach (var key in RandoLogic.AvailableAreas)
            {
                var area = AreaData.Get(key);
                var mode = AreaData.GetMode(key);

                if (currentSet != area.GetLevelSet())
                {
                    currentSet = area.GetLevelSet();
                    menu.Add(new TextMenu.SubHeader(DialogExt.CleanLevelSet(currentSet)));
                }

                var on   = Settings.MapIncluded(key);
                var name = area.Name;
                name = name.DialogCleanOrNull() ?? name.SpacedPascalCase();
                if (key.Mode != AreaMode.Normal || (area.Mode.Length != 1 && area.Mode[1] != null))
                {
                    name += " " + Char.ToString((char)('A' + (int)key.Mode));
                }

                menu.Add(new TextMenu.OnOff(name, on).Change(this.MakeChangeFunc(key)));
                menu.Add(new TextMenuExt.SubHeaderExt(lvlCount[new RandoSettings.AreaKeyNotStupid(key)].ToString() + " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_LEVELS"))
                {
                    HeightExtra = -10f,
                    Offset      = new Vector2(30, -5),
                });
            }

            if (currentSet != "Celeste")
            {
                menu.Insert(2, new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_RESET")).Pressed(() => {
                    Settings.SetNormalMaps();
                    // this is a stupid way to do this
                    int levelsetIdx = -1;
                    foreach (var item in menu.GetItems())
                    {
                        if (item is TextMenu.SubHeader && !(item is TextMenuExt.SubHeaderExt))
                        {
                            levelsetIdx++;
                        }
                        else if (item is TextMenu.OnOff toggle)
                        {
                            toggle.Index = levelsetIdx == 0 ? 1 : 0;
                        }
                    }
                }));
            }

            Scene.Add(menu);
        }
Beispiel #13
0
        protected override void addOptionsToMenu(TextMenu menu, bool inGame, object[] parameters)
        {
            OptionItems items = new OptionItems();

            // Add the general settings
            menu.Add(new TextMenu.SubHeader(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_GENERALSETTINGS")));
            menu.Add(new TextMenu.Slider(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_CHANGEVARIANTSINTERVAL"),
                                         i => {
                if (i == 0)
                {
                    return(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_ONSCREENTRANSITION"));
                }
                return($"{Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_EVERY")} {changeVariantsIntervalScale[i]}s");
            }, 0, changeVariantsIntervalScale.Length - 1, indexFromChangeVariantsInterval(ExtendedVariantsModule.Settings.ChangeVariantsInterval))
                     .Change(i => {
                ExtendedVariantsModule.Settings.ChangeVariantsInterval = changeVariantsIntervalScale[i];
                refreshOptionMenuEnabledStatus(items);
                ExtendedVariantsModule.Instance.Randomizer.UpdateCountersFromSettings();
            }));

            menu.Add(new TextMenu.Slider(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_VARIANTSET"),
                                         i => Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_" + new string[] { "OFF", "VANILLA", "EXTENDED", "BOTH" }[i]), 1, 3, ExtendedVariantsModule.Settings.VariantSet)
                     .Change(i => {
                ExtendedVariantsModule.Settings.VariantSet = i;
                refreshOptionMenuEnabledStatus(items);
            }));

            TextMenu.Option <int> maxEnabledVariants = new TextMenu.Slider(
                Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_MAXENABLEDVARIANTS" + (ExtendedVariantsModule.Settings.RerollMode ? "_REROLL" : "")),
                i => i.ToString(), 0, ExtendedVariantsModule.Instance.VariantHandlers.Count + 13, ExtendedVariantsModule.Settings.MaxEnabledVariants)
                                                       .Change(newValue => ExtendedVariantsModule.Settings.MaxEnabledVariants = newValue);

            menu.Add(new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_REROLLMODE"), ExtendedVariantsModule.Settings.RerollMode)
                     .Change(newValue => {
                ExtendedVariantsModule.Settings.RerollMode = newValue;
                maxEnabledVariants.Label = Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_MAXENABLEDVARIANTS" + (newValue ? "_REROLL" : ""));
            }));

            menu.Add(maxEnabledVariants);

            menu.Add(items.VanillafyOption = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_VANILLAFY"), i => {
                if (i == 0)
                {
                    return(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_DISABLED"));
                }
                i = vanillafyScale[i];
                if (i < 60)
                {
                    return($"{i.ToString()}s");
                }
                return($"{(i / 60).ToString()} min");
            }, 0, vanillafyScale.Length - 1, indexFromVanillafyScale(ExtendedVariantsModule.Settings.Vanillafy))
                                             .Change(newValue => {
                ExtendedVariantsModule.Settings.Vanillafy = vanillafyScale[newValue];
                ExtendedVariantsModule.Instance.Randomizer.UpdateCountersFromSettings();
            }));

            menu.Add(new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_DISPLAYONSCREEN"), ExtendedVariantsModule.Settings.DisplayEnabledVariantsToScreen)
                     .Change(newValue => ExtendedVariantsModule.Settings.DisplayEnabledVariantsToScreen = newValue));

            if (!inGame)
            {
                TextMenu.Button seedButton = new TextMenu.Button(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_SEEDINPUT") + " " + ExtendedVariantsModule.Settings.RandoSetSeed);
                seedButton.Pressed(() => {
                    returnIndex = menu.Selection;
                    Audio.Play(SFX.ui_main_savefile_rename_start);
                    menu.SceneAs <Overworld>().Goto <OuiModOptionString>().Init <OuiRandomizerOptions>(
                        ExtendedVariantsModule.Settings.RandoSetSeed,
                        v => ExtendedVariantsModule.Settings.RandoSetSeed = v,
                        25
                        );
                });

                TextMenu.Option <bool> toggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_SETSEED"), ExtendedVariantsModule.Settings.RandoSetSeed != null)
                                                .Change(newValue => {
                    ExtendedVariantsModule.Settings.RandoSetSeed = (newValue ? "seed" : null);

                    seedButton.Visible = newValue;
                    seedButton.Label   = Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_SEEDINPUT") + " seed";
                });

                seedButton.Visible = ExtendedVariantsModule.Settings.RandoSetSeed != null;

                menu.Add(toggle);
                toggle.AddDescription(menu, Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_SEEDDESCRIPTION2"));
                toggle.AddDescription(menu, Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_SEEDDESCRIPTION1"));
                menu.Add(seedButton);
            }


            // build the toggles to individually enable or disable all vanilla variants
            menu.Add(new TextMenu.SubHeader(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_ENABLED_VANILLA")));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.GameSpeed));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.MirrorMode));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.ThreeSixtyDashing));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.InvisibleMotion));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.NoGrabbing));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.LowFriction));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.SuperDashing));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.Hiccups));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.PlayAsBadeline));

            menu.Add(new TextMenu.SubHeader(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_ENABLED_VANILLA_ASSISTS")));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.InfiniteStamina));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.DashMode));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.Invincible));
            items.VanillaVariantOptions.Add(addToggleOptionToMenu(menu, VanillaVariant.DashAssist));

            // and do the same with extended ones
            menu.Add(new TextMenu.SubHeader(Dialog.Clean("MODOPTIONS_EXTENDEDVARIANTS_RANDOMIZER_ENABLED_EXTENDED")));
            foreach (ExtendedVariantsModule.Variant variant in ExtendedVariantsModule.Instance.VariantHandlers.Keys)
            {
                items.ExtendedVariantOptions.Add(addToggleOptionToMenu(menu, variant));
            }

            refreshOptionMenuEnabledStatus(items);

            if (returnIndex >= 0)
            {
                menu.Selection = returnIndex;
                returnIndex    = -1;
            }
        }
        private Tuple <List <TextMenu.Item>, Action> MakeMapPicker(Action syncOutward)
        {
            var menu      = new List <TextMenu.Item>();
            var toggleAll = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_TOGGLEALL")).Pressed(() => {
                TextMenu.OnOff firstToggle = null;
                foreach (var item in menu)
                {
                    if (item is TextMenu.OnOff)
                    {
                        firstToggle = item as TextMenu.OnOff;
                        break;
                    }
                }

                if (firstToggle == null)
                {
                    // ???
                    return;
                }

                var newValue = 1 - firstToggle.Index;
                foreach (var item in menu)
                {
                    if (item is TextMenu.OnOff toggle)
                    {
                        toggle.Index = newValue;
                        toggle.OnValueChange(toggle.Values[newValue].Item2);
                    }
                }
            });

            menu.Add(toggleAll);

            var mapcountlbl = new TextMenuExt.SubHeaderExt(Settings.LevelCount.ToString() + " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_LEVELS"))
            {
                HeightExtra = -10f,
                Offset      = new Vector2(30, -5),
            };

            menu.Add(mapcountlbl);

            void syncTotal()
            {
                mapcountlbl.Title = Settings.LevelCount.ToString() + " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_LEVELS");
            }

            void syncInner()
            {
                syncOutward();
                syncTotal();
            }

            Action AddAreaToggle(string name, AreaKey key)
            {
                var    toggle   = new TextMenu.OnOff(name, false);
                Action syncFunc = () => {
                    var on = Settings.MapIncluded(key);
                    toggle.Index = on ? 1 : 0;
                };
                var numLevels = RandoLogic.LevelCount[new RandoSettings.AreaKeyNotStupid(key)];

                menu.Add(toggle.Change(this.MakeChangeFunc(key, syncInner)));
                menu.Add(new TextMenuExt.SubHeaderExt(numLevels.ToString() + " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_LEVELS"))
                {
                    HeightExtra = -10f,
                    Offset      = new Vector2(30, -5),
                });
                syncFunc();
                return(syncFunc);
            }

            Action AddLevelSetToggle(string name, List <AreaKey> keys)
            {
                var    toggle   = new TextMenu.OnOff(name, false);
                Action syncFunc = () => {
                    var on = Settings.MapIncluded(keys[0]);
                    toggle.Index = on ? 1 : 0;
                };
                var numLevels = 0;

                foreach (AreaKey key in keys)
                {
                    numLevels += RandoLogic.LevelCount[new RandoSettings.AreaKeyNotStupid(key)];
                }
                menu.Add(toggle.Change(this.MakeChangeFunc(keys, syncInner)));
                menu.Add(new TextMenuExt.SubHeaderExt(numLevels.ToString() + " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_LEVELS"))
                {
                    HeightExtra = -10f,
                    Offset      = new Vector2(30, -5),
                });
                syncFunc();
                return(syncFunc);
            }

            Action AddLevelSetMenu(string levelSetID)
            {
                List <AreaKey> keys      = RandoLogic.LevelSets[levelSetID];
                var            syncFuncs = new List <Action>();

                menu.Add(new TextMenu.SubHeader(DialogExt.CleanLevelSet(keys[0].GetLevelSet())));
                foreach (var key in keys)
                {
                    var area = AreaData.Get(key);
                    var name = area.Name;
                    name = name.DialogCleanOrNull() ?? name.SpacedPascalCase();
                    if (key.Mode != AreaMode.Normal || (area.Mode.Length != 1 && area.Mode[1] != null))
                    {
                        name += " " + Char.ToString((char)('A' + (int)key.Mode));
                    }

                    syncFuncs.Add(AddAreaToggle(name, key));
                }

                return(() => {
                    foreach (var a in syncFuncs)
                    {
                        a();
                    }
                    syncTotal();
                });
            }

            var allSyncs = new List <Action>();

            // Create submenu for Celeste, campaigns, then other levelsets
            allSyncs.Add(AddLevelSetMenu("Celeste"));
            List <string> completedLevelSets = new List <string> {
                "Celeste"
            };

            var campaigns = RandoModule.Instance.MetaConfig.Campaigns;

            foreach (RandoMetadataCampaign campaign in campaigns)
            {
                menu.Add(new TextMenu.SubHeader(DialogExt.CleanLevelSet(campaign.Name)));
                foreach (RandoMetadataLevelSet levelSet in campaign.LevelSets)
                {
                    var name = levelSet.Name;
                    if (RandoLogic.LevelSets.TryGetValue(levelSet.ID, out var keys))
                    {
                        allSyncs.Add(AddLevelSetToggle(name, keys));
                        completedLevelSets.Add(levelSet.ID);
                    }
                }
            }

            foreach (string levelSet in RandoLogic.LevelSets.Keys)
            {
                if (!completedLevelSets.Contains(levelSet))
                {
                    allSyncs.Add(AddLevelSetMenu(levelSet));
                }
            }

            // If Celeste is not the only levelset, Reset should turn all other levelsets off
            if (RandoLogic.LevelSets.Count > 1)
            {
                menu.Insert(2, new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_RESET")).Pressed(() => {
                    Settings.SetNormalMaps();
                    // this is a stupid way to do this
                    int levelsetIdx = -1;
                    foreach (var item in menu)
                    {
                        if (item is TextMenu.SubHeader && !(item is TextMenuExt.SubHeaderExt))
                        {
                            levelsetIdx++;
                        }
                        else if (item is TextMenu.OnOff toggle)
                        {
                            toggle.Index = levelsetIdx == 0 ? 1 : 0;
                        }
                    }
                }));
            }

            Action finalSync = () => {
                foreach (var aa in allSyncs)
                {
                    aa();
                }
            };

            return(Tuple.Create(menu, finalSync));
        }
Beispiel #15
0
        /// <summary>
        /// Create the mod menu subsection including the section header in the given menu.
        /// The default implementation uses reflection to attempt creating a menu.
        /// </summary>
        /// <param name="menu">Menu to add the section to.</param>
        /// <param name="inGame">Whether we're in-game (paused) or in the main menu.</param>
        /// <param name="snapshot">The Level.PauseSnapshot</param>
        public virtual void CreateModMenuSection(TextMenu menu, bool inGame, EventInstance snapshot)
        {
            Type type = SettingsType;
            EverestModuleSettings settings = _Settings;

            if (type == null || settings == null)
            {
                return;
            }

            // The default name prefix.
            string nameDefaultPrefix = $"modoptions_{type.Name.ToLowerInvariant()}_";

            if (nameDefaultPrefix.EndsWith("Settings"))
            {
                nameDefaultPrefix = nameDefaultPrefix.Substring(0, nameDefaultPrefix.Length - 8);
            }

            // Any attributes we may want to get and read from later.
            SettingInGameAttribute attribInGame;
            SettingRangeAttribute  attribRange;

            // If the settings type has got the InGame attrib, only show it in the matching situation.
            if ((attribInGame = type.GetCustomAttribute <SettingInGameAttribute>()) != null &&
                attribInGame.InGame != inGame)
            {
                return;
            }

            // The settings subheader.
            string name; // We lazily reuse this field for the props later on.

            name = type.GetCustomAttribute <SettingNameAttribute>()?.Name ?? $"{nameDefaultPrefix}title";
            name = name.DialogCleanOrNull() ?? Metadata.Name.SpacedPascalCase();

            menu.Add(new TextMenu.SubHeader(name));

            PropertyInfo[] props;
            if (type == _PrevSettingsType)
            {
                props = _PrevSettingsProps;
            }
            else
            {
                _PrevSettingsProps = props = type.GetProperties();
                _PrevSettingsType  = type;
            }

            foreach (PropertyInfo prop in props)
            {
                if ((attribInGame = prop.GetCustomAttribute <SettingInGameAttribute>()) != null &&
                    attribInGame.InGame != inGame)
                {
                    continue;
                }

                if (prop.GetCustomAttribute <SettingIgnoreAttribute>() != null)
                {
                    continue;
                }

                if (!prop.CanRead || !prop.CanWrite)
                {
                    continue;
                }

                name = prop.GetCustomAttribute <SettingNameAttribute>()?.Name ?? $"{nameDefaultPrefix}{prop.Name.ToLowerInvariant()}";
                name = name.DialogCleanOrNull() ?? prop.Name.SpacedPascalCase();

                bool needsRelaunch = prop.GetCustomAttribute <SettingNeedsRelaunchAttribute>() != null;

                TextMenu.Item item     = null;
                Type          propType = prop.PropertyType;
                object        value    = prop.GetValue(settings);

                // Create the matching item based off of the type and attributes.

                if (propType == typeof(bool))
                {
                    item =
                        new TextMenu.OnOff(name, (bool)value)
                        .Change(v => prop.SetValue(settings, v))
                        .NeedsRelaunch(needsRelaunch)
                    ;
                }
                else if (
                    propType == typeof(int) &&
                    (attribRange = prop.GetCustomAttribute <SettingRangeAttribute>()) != null
                    )
                {
                    item =
                        new TextMenu.Slider(name, i => i.ToString(), attribRange.Min, attribRange.Max, (int)value)
                        .Change(v => prop.SetValue(settings, v))
                        .NeedsRelaunch(needsRelaunch)
                    ;
                }

                if (item == null)
                {
                    continue;
                }
                menu.Add(item);
            }
        }
        protected override Entity ReloadMenu()
        {
            var menu = new DisablableTextMenu {
                new TextMenu.Header(Dialog.Clean("MODOPTIONS_RANDOMIZER_HEADER"))
            };

            var currentPage = OptionsPages.Basic;
            var pages       = new[] { new List <TextMenu.Item>(), new List <TextMenu.Item>(), new List <TextMenu.Item>(), new List <TextMenu.Item>(), new List <TextMenu.Item>() };

            var hashtext = new TextMenuExt.EaseInSubHeaderExt("{hash}", true, menu)
            {
                HeightExtra = -10f,
                Offset      = new Vector2(30, -5),
            };

            void updateHashText()
            {
                hashtext.Title = "v" + RandoModule.Instance.VersionString;
                if (Settings.SeedType == SeedType.Custom)
                {
                    hashtext.Title += " #" + Settings.Hash.ToString();
                }
            }

            updateHashText();

            var errortext = new TextMenuExt.EaseInSubHeaderExt("{error}", false, menu)
            {
                HeightExtra = -10f,
                Offset      = new Vector2(30, -5),
            };

            var seedbutton = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_SEED") + ": " + Settings.Seed);

            seedbutton.Pressed(() => {
                Audio.Play(SFX.ui_main_savefile_rename_start);
                menu.SceneAs <Overworld>().Goto <UI.OuiTextEntry>().Init <OuiRandoSettings>(
                    Settings.Seed,
                    (v) => Settings.Seed = v,
                    RandoModule.MAX_SEED_CHARS
                    );
            });
            pages[1].Add(seedbutton);

            var seedtypetoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_SEEDTYPE"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_SEEDTYPE_" + Enum.GetNames(typeof(SeedType))[i].ToUpperInvariant()));
            }, 0, (int)SeedType.Last - 1, (int)Settings.SeedType).Change((i) => {
                Settings.SeedType  = (SeedType)i;
                seedbutton.Visible = Settings.SeedType == SeedType.Custom;
                // just in case...
                seedbutton.Label = Dialog.Clean("MODOPTIONS_RANDOMIZER_SEED") + ": " + Settings.Seed;
                updateHashText();
            });

            pages[1].Add(seedtypetoggle);

            var lengthtoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_LENGTH"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_LENGTH_" + Enum.GetNames(typeof(MapLength))[i].ToUpperInvariant()));
            }, 0, (int)MapLength.Last - 1, (int)Settings.Length).Change((i) => {
                Settings.Length = (MapLength)i;
                updateHashText();
            });

            pages[1].Add(lengthtoggle);

            var numdashestoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_NUMDASHES"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_NUMDASHES_" + Enum.GetNames(typeof(NumDashes))[i].ToUpperInvariant()));
            }, 0, (int)NumDashes.Last - 1, (int)Settings.Dashes).Change((i) => {
                Settings.Dashes = (NumDashes)i;
                updateHashText();
            });

            pages[1].Add(numdashestoggle);

            var endlesslivespicker = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_LIVES"), i => {
                return(i == 0 ? Dialog.Clean("MODOPTIONS_RANDOMIZER_LIVES_INFINITE") : i.ToString());
            }, 0, 50, Settings.EndlessLives);

            endlesslivespicker.OnValueChange = i => {
                Settings.EndlessLives = i;
            };
            endlesslivespicker.Visible = Settings.Algorithm == LogicType.Endless;

            var logictoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_LOGIC"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_LOGIC_" + Enum.GetNames(typeof(LogicType))[i].ToUpperInvariant()));
            }, 0, (int)LogicType.Last - 1, (int)Settings.Algorithm).Change((i) => {
                Settings.Algorithm         = (LogicType)i;
                endlesslivespicker.Visible = Settings.Algorithm == LogicType.Endless;
                updateHashText();
            });

            pages[1].Add(logictoggle);
            pages[1].Add(endlesslivespicker);

            var difficultytoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_DIFFICULTY"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_DIFFICULTY_" + Enum.GetNames(typeof(Difficulty))[i].ToUpperInvariant()));
            }, 0, (int)Difficulty.Last - 1, (int)Settings.Difficulty).Change((i) => {
                Settings.Difficulty = (Difficulty)i;
                updateHashText();
            });

            pages[1].Add(difficultytoggle);

            var mapinfo = this.MakeMapPicker(updateHashText);

            pages[2].AddRange(mapinfo.Item1);

            var strawberriestoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_STRAWBERRIES"), i => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_STRAWBERRIES_" + Enum.GetNames(typeof(StrawberryDensity))[i].ToUpperInvariant()));
            }, 0, (int)StrawberryDensity.Last - 1, (int)Settings.Strawberries).Change(i => {
                Settings.Strawberries = (StrawberryDensity)i;
                updateHashText();
            });

            pages[3].Add(strawberriestoggle);

            var difficultycurvetoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_DIFFICULTYCURVE"), i => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_DIFFICULTYCURVE_" + Enum.GetNames(typeof(DifficultyEagerness))[i].ToUpperInvariant()));
            }, 0, (int)DifficultyEagerness.Last - 1, (int)Settings.DifficultyEagerness).Change(i => {
                Settings.DifficultyEagerness = (DifficultyEagerness)i;
                updateHashText();
            });

            pages[3].Add(difficultycurvetoggle);

            var repeatroomstoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_REPEATROOMS"), Settings.RepeatRooms).Change((val) => {
                Settings.RepeatRooms = val;
                updateHashText();
            });

            pages[3].Add(repeatroomstoggle);

            var enterunknowntoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_ENTERUNKNOWN"), Settings.EnterUnknown).Change((val) => {
                Settings.EnterUnknown = val;
                updateHashText();
            });

            pages[3].Add(enterunknowntoggle);

            var goldentoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_GOLDENBERRY"), Settings.SpawnGolden).Change((val) => {
                Settings.SpawnGolden = val;
            });

            pages[3].Add(goldentoggle);

            var variantstoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_VARIANTS"), Settings.Variants).Change((val) => {
                Settings.Variants = val;
            });

            pages[3].Add(variantstoggle);

            var shinetoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_SHINE"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_SHINE_" + Enum.GetNames(typeof(ShineLights))[i].ToUpperInvariant()));
            }, 0, (int)ShineLights.Last - 1, (int)Settings.Lights).Change((i) => {
                Settings.Lights = (ShineLights)i;
                updateHashText();
            });

            pages[4].Add(shinetoggle);

            var darktoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_DARK"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_DARK_" + Enum.GetNames(typeof(Darkness))[i].ToUpperInvariant()));
            }, 0, (int)Darkness.Last - 1, (int)Settings.Darkness).Change((i) => {
                Settings.Darkness = (Darkness)i;
                updateHashText();
            });

            pages[4].Add(darktoggle);

            var decorationstoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_DECORATIONS"), Settings.RandomDecorations).Change((val) => {
                Settings.RandomDecorations = val;
            });

            pages[4].Add(decorationstoggle);

            var colorstoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_COLORS"), Settings.RandomColors).Change((val) => {
                Settings.RandomColors = val;
            });

            pages[4].Add(colorstoggle);

            var bgstoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_BACKGROUNDS"), Settings.RandomBackgrounds).Change((val) => {
                Settings.RandomBackgrounds = val;
            });

            pages[4].Add(bgstoggle);

            var rulestoggles = new Dictionary <String, TextMenuExt.ButtonExt>();

            void syncModel()
            {
                repeatroomstoggle.Index     = Settings.RepeatRooms ? 1 : 0;
                enterunknowntoggle.Index    = Settings.EnterUnknown ? 1 : 0;
                variantstoggle.Index        = Settings.Variants ? 1 : 0;
                logictoggle.Index           = (int)Settings.Algorithm;
                lengthtoggle.Index          = (int)Settings.Length;
                numdashestoggle.Index       = (int)Settings.Dashes;
                difficultytoggle.Index      = (int)Settings.Difficulty;
                difficultycurvetoggle.Index = (int)Settings.DifficultyEagerness;
                shinetoggle.Index           = (int)Settings.Lights;
                darktoggle.Index            = (int)Settings.Darkness;
                endlesslivespicker.Index    = Settings.EndlessLives;
                strawberriestoggle.Index    = (int)Settings.Strawberries;

                var locked = !String.IsNullOrEmpty(Settings.Rules);

                foreach (var item in pages[2])
                {
                    item.Disabled = locked;
                }
                repeatroomstoggle.Disabled     = locked;
                enterunknowntoggle.Disabled    = locked;
                logictoggle.Disabled           = locked;
                lengthtoggle.Disabled          = locked;
                numdashestoggle.Disabled       = locked;
                difficultytoggle.Disabled      = locked;
                difficultycurvetoggle.Disabled = locked;
                shinetoggle.Disabled           = locked;
                darktoggle.Disabled            = locked;
                variantstoggle.Disabled        = locked;
                endlesslivespicker.Disabled    = locked;
                strawberriestoggle.Disabled    = locked;

                var i = (OptionsPages)0;

                foreach (var page in pages)
                {
                    var visible = i == currentPage;
                    foreach (var widget in page)
                    {
                        widget.Visible = visible;
                    }
                    i++;
                }
                endlesslivespicker.Visible &= Settings.Algorithm == LogicType.Endless;
                seedbutton.Visible         &= Settings.SeedType == SeedType.Custom;

                foreach (var kv in rulestoggles)
                {
                    //kv.Value.Visible &= kv.Key == "" || RandoModule.Instance.MetaConfig.RulesetsDict[kv.Key].Algorithm == this.Settings.Algorithm;
                    kv.Value.Icon = kv.Key == this.Settings.Rules ? "menu/poemarrow" : "";
                }

                mapinfo.Item2();
            }

            var pageToggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_OPTIONS"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_OPTIONS_" + Enum.GetNames(typeof(OptionsPages))[i].ToUpperInvariant()));
            }, 0, (int)OptionsPages.Last - 1, (int)currentPage).Change((i) => {
                currentPage = (OptionsPages)i;
                syncModel();
                menu.RecalculateSize();
                menu.Position.Y = menu.ScrollTargetY;
            });

            void syncRuleset()
            {
                Settings.Enforce();
                syncModel();
                updateHashText();
            }

            var nullToggle = new TextMenuExt.ButtonExt(Dialog.Clean("MODOPTIONS_RANDOMIZER_RULES_CUSTOM"));

            nullToggle.Pressed(this.MakeRulesetToggler("", syncRuleset));
            rulestoggles.Add("", nullToggle);
            pages[0].Add(nullToggle);

            var sortedrules = new List <RandoMetadataRuleset>(RandoModule.Instance.MetaConfig.Rulesets);

            sortedrules.Sort((a, b) => a.Name.CompareTo(b.Name));
            foreach (var ruleset in sortedrules)
            {
                var toggle = new TextMenuExt.ButtonExt(ruleset.LongName);
                toggle.Pressed(this.MakeRulesetToggler(ruleset.Name, syncRuleset));
                rulestoggles.Add(ruleset.Name, toggle);
                pages[0].Add(toggle);
            }

            var startbutton = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_START"));

            startbutton.Pressed(() => {
                if (this.Entering)
                {
                    return;
                }

                void reenableMenu()
                {
                    this.BuilderThread = null;

                    startbutton.Label = Dialog.Clean("MODOPTIONS_RANDOMIZER_START");
                    updateHashText();
                    menu.DisableMovement = false;
                }

                if (this.BuilderThread == null)
                {
                    errortext.FadeVisible = false;
                    startbutton.Label     = Dialog.Clean("MODOPTIONS_RANDOMIZER_CANCEL");
                    hashtext.Title       += " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_GENERATING");
                    menu.DisableMovement  = true;

                    this.BuilderThread = new Thread(() => {
                        Settings.Enforce();
                        AreaKey newArea;
                        try {
                            newArea = RandoLogic.GenerateMap(Settings);
                        } catch (ThreadAbortException) {
                            return;
                        } catch (GenerationError e) {
                            errortext.Title       = e.Message;
                            errortext.FadeVisible = true;
                            reenableMenu();
                            return;
                        } catch (Exception e) {
                            errortext.Title = "Encountered an error - Check log.txt for details";
                            Logger.LogDetailed(e, "randomizer");
                            errortext.FadeVisible = true;
                            reenableMenu();
                            return;
                        }
                        // save settings
                        RandoModule.Instance.SavedData.SavedSettings = Settings.Copy();
                        RandoModule.Instance.SaveSettings();

                        this.Entering       = true;
                        RandoModule.StartMe = newArea;
                        while (RandoModule.StartMe != null)
                        {
                            Thread.Sleep(10);
                        }
                        this.BuilderThread = null;
                        this.Entering      = false;
                    });
                    this.BuilderThread.Start();
                }
                else
                {
                    this.BuilderThread.Abort();
                    reenableMenu();
                }
            });

            menu.Add(startbutton);
            menu.Add(hashtext);
            menu.Add(errortext);
            menu.Add(pageToggle);
            foreach (var page in pages)
            {
                foreach (var item in page)
                {
                    menu.Add(item);
                }
            }

            Scene.Add(menu);
            syncModel();

            menu.OnCancel = () => {
                if (this.Entering || this.BuilderThread != null)
                {
                    return;
                }

                // save settings
                RandoModule.Instance.SavedData.SavedSettings = Settings.Copy();
                RandoModule.Instance.SaveSettings();

                Audio.Play(SFX.ui_main_button_back);
                Overworld.Goto <OuiMainMenu>();
            };

            menu.OnPause = () => {
                if (this.Entering || this.BuilderThread != null)
                {
                    return;
                }

                Audio.Play(SFX.ui_main_button_select);
                menu.Selection = 1;
                menu.Current.OnPressed();
            };

            menu.Selection = 1;
            return(menu);
        }
Beispiel #17
0
        protected override void addOptionsToMenu(TextMenu menu)
        {
            // for now, display a "loading" message.
            TextMenu.Button loading = new TextMenu.Button(Dialog.Clean("MODOPTIONS_MODTOGGLE_LOADING"))
            {
                Disabled = true
            };
            menu.Add(loading);

            modLoadingTask = new Task(() => {
                // load all the mod yamls (that can take some time), update the progress every 500ms so that the text doesn't go crazy since it is centered.
                Stopwatch updateTimer = Stopwatch.StartNew();
                modYamls = LoadAllModYamls(progress => {
                    if (updateTimer.ElapsedMilliseconds > 500)
                    {
                        updateTimer.Restart();
                        loading.Label = $"{Dialog.Clean("MODOPTIONS_MODTOGGLE_LOADING")} ({(int) (progress * 100)}%)";
                    }
                });
                updateTimer.Stop();

                MainThreadHelper.Do(() => {
                    modToggles = new Dictionary <string, TextMenu.OnOff>();

                    // remove the "loading..." message
                    menu.Remove(loading);

                    // if there is a whitelist, warn the user that it will break those settings.
                    if (Everest.Loader.Whitelist != null)
                    {
                        menu.Add(restartMessage1 = new TextMenuExt.SubHeaderExt(Dialog.Clean("MODOPTIONS_MODTOGGLE_WHITELISTWARN"))
                        {
                            TextColor = Color.OrangeRed
                        });
                    }

                    // display the warning about blacklist.txt + restarting
                    menu.Add(restartMessage1 = new TextMenuExt.SubHeaderExt(Dialog.Clean("MODOPTIONS_MODTOGGLE_MESSAGE_1")));
                    menu.Add(restartMessage2 = new TextMenuExt.SubHeaderExt(Dialog.Clean("MODOPTIONS_MODTOGGLE_MESSAGE_2"))
                    {
                        HeightExtra = 0f
                    });
                    menu.Add(new TextMenuExt.SubHeaderExt(Dialog.Clean("MODOPTIONS_MODTOGGLE_MESSAGE_3"))
                    {
                        HeightExtra = 20f, TextColor = Color.Goldenrod
                    });

                    // reduce spacing between the whitelist warning and the blacklist overwrite warning
                    if (Everest.Loader.Whitelist != null)
                    {
                        restartMessage1.HeightExtra = 30f;
                    }

                    // "enable all" and "disable all" buttons
                    menu.Add(new TextMenu.Button(Dialog.Clean("MODOPTIONS_MODTOGGLE_ENABLEALL")).Pressed(() => {
                        foreach (TextMenu.OnOff toggle in modToggles.Values)
                        {
                            toggle.Index = 1;
                        }
                        blacklistedMods.Clear();
                        updateHighlightedMods();
                    }));
                    menu.Add(new TextMenu.Button(Dialog.Clean("MODOPTIONS_MODTOGGLE_DISABLEALL")).Pressed(() => {
                        blacklistedMods.Clear();
                        foreach (KeyValuePair <string, TextMenu.OnOff> toggle in modToggles)
                        {
                            toggle.Value.Index = 0;
                            blacklistedMods.Add(toggle.Key);
                        }
                        updateHighlightedMods();
                    }));

                    // "toggle dependencies automatically" button
                    TextMenu.Item toggleDependenciesButton;
                    menu.Add(toggleDependenciesButton = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_MODTOGGLE_TOGGLEDEPS"), true)
                                                        .Change(value => toggleDependencies = value));

                    toggleDependenciesButton.AddDescription(menu, Dialog.Clean("MODOPTIONS_MODTOGGLE_TOGGLEDEPS_MESSAGE2"));
                    toggleDependenciesButton.AddDescription(menu, Dialog.Clean("MODOPTIONS_MODTOGGLE_TOGGLEDEPS_MESSAGE1"));

                    // "cancel" button to leave the screen without saving
                    menu.Add(new TextMenu.Button(Dialog.Clean("MODOPTIONS_MODTOGGLE_CANCEL")).Pressed(() => {
                        blacklistedMods = blacklistedModsOriginal;
                        onBackPressed(Overworld);
                    }));

                    // reset the mods list
                    allMods         = new List <string>();
                    blacklistedMods = new HashSet <string>();

                    string[] files;
                    bool headerInserted;

                    // crawl directories
                    files = Directory.GetDirectories(Everest.Loader.PathMods);
                    Array.Sort(files, (a, b) => a.ToLowerInvariant().CompareTo(b.ToLowerInvariant()));
                    headerInserted = false;
                    for (int i = 0; i < files.Length; i++)
                    {
                        string file = Path.GetFileName(files[i]);
                        if (file != "Cache")
                        {
                            if (!headerInserted)
                            {
                                menu.Add(new patch_TextMenu.patch_SubHeader(Dialog.Clean("MODOPTIONS_MODTOGGLE_DIRECTORIES")));
                                headerInserted = true;
                            }
                            addFileToMenu(menu, file);
                        }
                    }

                    // crawl zips
                    files = Directory.GetFiles(Everest.Loader.PathMods);
                    Array.Sort(files, (a, b) => a.ToLowerInvariant().CompareTo(b.ToLowerInvariant()));
                    headerInserted = false;
                    for (int i = 0; i < files.Length; i++)
                    {
                        string file = Path.GetFileName(files[i]);
                        if (file.EndsWith(".zip"))
                        {
                            if (!headerInserted)
                            {
                                menu.Add(new patch_TextMenu.patch_SubHeader(Dialog.Clean("MODOPTIONS_MODTOGGLE_ZIPS")));
                                headerInserted = true;
                            }
                            addFileToMenu(menu, file);
                        }
                    }

                    // crawl map bins
                    files = Directory.GetFiles(Everest.Loader.PathMods);
                    Array.Sort(files, (a, b) => a.ToLowerInvariant().CompareTo(b.ToLowerInvariant()));
                    headerInserted = false;
                    for (int i = 0; i < files.Length; i++)
                    {
                        string file = Path.GetFileName(files[i]);
                        if (file.EndsWith(".bin"))
                        {
                            if (!headerInserted)
                            {
                                menu.Add(new patch_TextMenu.patch_SubHeader(Dialog.Clean("MODOPTIONS_MODTOGGLE_BINS")));
                                headerInserted = true;
                            }
                            addFileToMenu(menu, file);
                        }
                    }

                    // sort the mods list alphabetically, for output in the blacklist.txt file later.
                    allMods.Sort((a, b) => a.ToLowerInvariant().CompareTo(b.ToLowerInvariant()));

                    // adjust the mods' color if they are required dependencies for other mods
                    foreach (KeyValuePair <string, TextMenu.OnOff> toggle in modToggles)
                    {
                        if (modHasDependencies(toggle.Key))
                        {
                            ((patch_TextMenu.patch_Option <bool>)(object) toggle.Value).UnselectedColor = Color.Goldenrod;
                        }
                    }

                    // snap the menu so that it doesn't show a scroll up.
                    menu.Y = menu.ScrollTargetY;

                    // clone the list to be able to check if the list changed when leaving the menu.
                    blacklistedModsOriginal = new HashSet <string>(blacklistedMods);

                    // loading is done!
                    modLoadingTask = null;
                });
            });
            modLoadingTask.Start();
        }
Beispiel #18
0
        private void ReloadMenu()
        {
            menu = new DisablableTextMenu {
                new TextMenu.Header(Dialog.Clean("MODOPTIONS_RANDOMIZER_HEADER"))
            };

            var hashtext = new TextMenuExt.EaseInSubHeaderExt("{hash}", true, menu)
            {
                HeightExtra = -10f,
                Offset      = new Vector2(30, -5),
            };

            void updateHashText()
            {
                hashtext.Title = "v" + RandoModule.Instance.Metadata.VersionString;
                if (Settings.SeedType == SeedType.Custom)
                {
                    hashtext.Title += " #" + Settings.Hash.ToString();
                }
            }

            updateHashText();

            var errortext = new TextMenuExt.EaseInSubHeaderExt("{error}", false, menu)
            {
                HeightExtra = -10f,
                Offset      = new Vector2(30, -5),
            };

            var seedbutton = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_SEED") + ": " + Settings.Seed);

            seedbutton.Pressed(() => {
                Audio.Play(SFX.ui_main_savefile_rename_start);
                menu.SceneAs <Overworld>().Goto <UI.OuiTextEntry>().Init <OuiRandoSettings>(
                    Settings.Seed,
                    (v) => Settings.Seed = v,
                    RandoModule.MAX_SEED_CHARS
                    );
            });
            seedbutton.Visible = Settings.SeedType == SeedType.Custom;

            var seedtypetoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_SEEDTYPE"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_SEEDTYPE_" + Enum.GetNames(typeof(SeedType))[i].ToUpperInvariant()));
            }, 0, (int)SeedType.Last - 1, (int)Settings.SeedType).Change((i) => {
                Settings.SeedType  = (SeedType)i;
                seedbutton.Visible = Settings.SeedType == SeedType.Custom;
                // just in case...
                seedbutton.Label = Dialog.Clean("MODOPTIONS_RANDOMIZER_SEED") + ": " + Settings.Seed;
                updateHashText();
            });

            var mapbutton = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER")).Pressed(() => {
                Audio.Play(SFX.ui_main_button_select);
                menu.SceneAs <Overworld>().Goto <OuiMapPicker>();
            });

            var mapcountlbl = new TextMenuExt.SubHeaderExt(Settings.LevelCount.ToString() + " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_LEVELS"))
            {
                HeightExtra = -10f,
                Offset      = new Vector2(30, -5),
            };

            var logictoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_LOGIC"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_LOGIC_" + Enum.GetNames(typeof(LogicType))[i].ToUpperInvariant()));
            }, 0, (int)LogicType.Last - 1, (int)Settings.Algorithm).Change((i) => {
                Settings.Algorithm = (LogicType)i;
                updateHashText();
            });

            var lengthtoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_LENGTH"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_LENGTH_" + Enum.GetNames(typeof(MapLength))[i].ToUpperInvariant()));
            }, 0, (int)MapLength.Last - 1, (int)Settings.Length).Change((i) => {
                Settings.Length = (MapLength)i;
                updateHashText();
            });

            var numdashestoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_NUMDASHES"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_NUMDASHES_" + Enum.GetNames(typeof(NumDashes))[i].ToUpperInvariant()));
            }, 0, (int)NumDashes.Last - 1, (int)Settings.Dashes).Change((i) => {
                Settings.Dashes = (NumDashes)i;
                updateHashText();
            });

            var difficultytoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_DIFFICULTY"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_DIFFICULTY_" + Enum.GetNames(typeof(Difficulty))[i].ToUpperInvariant()));
            }, 0, (int)Difficulty.Last - 1, (int)Settings.Difficulty).Change((i) => {
                Settings.Difficulty = (Difficulty)i;
                updateHashText();
            });

            var repeatroomstoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_REPEATROOMS"), Settings.RepeatRooms).Change((val) => {
                Settings.RepeatRooms = val;
                updateHashText();
            });

            var enterunknowntext = new TextMenuExt.EaseInSubHeaderExt(Dialog.Clean("MODOPTIONS_RANDOMIZER_ENTERUNKNOWN_EXPLAIN"), false, menu)
            {
                HeightExtra = 17f,
                Offset      = new Vector2(30, -5),
            };

            var enterunknowntoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_ENTERUNKNOWN"), Settings.EnterUnknown).Change((val) => {
                Settings.EnterUnknown = val;
                updateHashText();
            });

            enterunknowntoggle.OnEnter += () => { enterunknowntext.FadeVisible = true; };
            enterunknowntoggle.OnLeave += () => { enterunknowntext.FadeVisible = false; };

            var shinetoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_SHINE"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_SHINE_" + Enum.GetNames(typeof(ShineLights))[i].ToUpperInvariant()));
            }, 0, (int)ShineLights.Last - 1, (int)Settings.Lights).Change((i) => {
                Settings.Lights = (ShineLights)i;
                updateHashText();
            });

            var darktoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_DARK"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_DARK_" + Enum.GetNames(typeof(Darkness))[i].ToUpperInvariant()));
            }, 0, (int)Darkness.Last - 1, (int)Settings.Darkness).Change((i) => {
                Settings.Darkness = (Darkness)i;
                updateHashText();
            });

            var goldentoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_GOLDENBERRY"), Settings.SpawnGolden).Change((val) => {
                Settings.SpawnGolden = val;
            });

            var variantstoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_VARIANTS"), Settings.Variants).Change((val) => {
                Settings.Variants = val;
            });

            var decorationstoggle = new TextMenu.OnOff(Dialog.Clean("MODOPTIONS_RANDOMIZER_DECORATIONS"), Settings.RandomDecorations).Change((val) => {
                Settings.RandomDecorations = val;
            });

            var moreoptions = false;

            repeatroomstoggle.Visible  = false;
            enterunknowntoggle.Visible = false;
            goldentoggle.Visible       = false;
            shinetoggle.Visible        = false;
            darktoggle.Visible         = false;
            variantstoggle.Visible     = false;
            decorationstoggle.Visible  = false;

            var moreoptionsbtn = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_MOREOPTIONS"));

            moreoptionsbtn.Pressed(() => {
                moreoptions          = !moreoptions;
                moreoptionsbtn.Label = moreoptions ? Dialog.Clean("MODOPTIONS_RANDOMIZER_FEWEROPTIONS") : Dialog.Clean("MODOPTIONS_RANDOMIZER_MOREOPTIONS");

                repeatroomstoggle.Visible  = moreoptions;
                enterunknowntoggle.Visible = moreoptions;
                goldentoggle.Visible       = moreoptions;
                shinetoggle.Visible        = moreoptions;
                darktoggle.Visible         = moreoptions;
                variantstoggle.Visible     = moreoptions;
                decorationstoggle.Visible  = moreoptions;
            });

            void syncModel()
            {
                repeatroomstoggle.Index  = Settings.RepeatRooms ? 1 : 0;
                enterunknowntoggle.Index = Settings.EnterUnknown ? 1 : 0;
                variantstoggle.Index     = Settings.Variants ? 1 : 0;
                logictoggle.Index        = (int)Settings.Algorithm;
                lengthtoggle.Index       = (int)Settings.Length;
                numdashestoggle.Index    = (int)Settings.Dashes;
                difficultytoggle.Index   = (int)Settings.Difficulty;
                shinetoggle.Index        = (int)Settings.Lights;
                darktoggle.Index         = (int)Settings.Darkness;
                mapcountlbl.Title        = Settings.LevelCount.ToString() + " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_LEVELS");

                var locked = Settings.Rules != Ruleset.Custom;

                mapbutton.Disabled          = locked;
                repeatroomstoggle.Disabled  = locked;
                enterunknowntoggle.Disabled = locked;
                logictoggle.Disabled        = locked;
                lengthtoggle.Disabled       = locked;
                numdashestoggle.Disabled    = locked;
                difficultytoggle.Disabled   = locked;
                shinetoggle.Disabled        = locked;
                darktoggle.Disabled         = locked;
                variantstoggle.Disabled     = locked;
            }

            syncModel();

            var rulestoggle = new TextMenu.Slider(Dialog.Clean("MODOPTIONS_RANDOMIZER_RULES"), (i) => {
                return(Dialog.Clean("MODOPTIONS_RANDOMIZER_RULES_" + Enum.GetNames(typeof(Ruleset))[i].ToUpperInvariant()));
            }, 0, (int)Ruleset.Last - 1, (int)Settings.Rules).Change((i) => {
                Settings.Rules = (Ruleset)i;
                Settings.Enforce();
                syncModel();
                updateHashText();
            });

            var startbutton = new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_START"));

            startbutton.Pressed(() => {
                if (this.entering)
                {
                    return;
                }

                void reenableMenu()
                {
                    this.builderThread = null;

                    startbutton.Label = Dialog.Clean("MODOPTIONS_RANDOMIZER_START");
                    updateHashText();
                    menu.DisableMovement = false;
                }

                if (this.builderThread == null)
                {
                    errortext.FadeVisible = false;
                    startbutton.Label     = Dialog.Clean("MODOPTIONS_RANDOMIZER_CANCEL");
                    hashtext.Title       += " " + Dialog.Clean("MODOPTIONS_RANDOMIZER_GENERATING");
                    menu.DisableMovement  = true;

                    this.builderThread = new Thread(() => {
                        Settings.Enforce();
                        AreaKey newArea;
                        try {
                            newArea = RandoLogic.GenerateMap(Settings);
                        } catch (ThreadAbortException) {
                            return;
                        } catch (GenerationError e) {
                            errortext.Title       = e.Message;
                            errortext.FadeVisible = true;
                            reenableMenu();
                            return;
                        } catch (Exception e) {
                            errortext.Title = "Encountered an error - Check log.txt for details";
                            Logger.LogDetailed(e, "randomizer");
                            errortext.FadeVisible = true;
                            reenableMenu();
                            return;
                        }
                        // save settings
                        RandoModule.Instance.SavedData.SavedSettings = Settings.Copy();
                        RandoModule.Instance.SaveSettings();

                        this.entering       = true;
                        RandoModule.StartMe = newArea;
                        while (RandoModule.StartMe != null)
                        {
                            Thread.Sleep(10);
                        }
                        this.builderThread = null;
                        this.entering      = false;
                    });
                    this.builderThread.Start();
                }
                else
                {
                    this.builderThread.Abort();
                    reenableMenu();
                }
            });

            menu.Add(seedtypetoggle);
            menu.Add(seedbutton);
            menu.Add(rulestoggle);
            menu.Add(mapbutton);
            menu.Add(mapcountlbl);
            menu.Add(logictoggle);
            menu.Add(lengthtoggle);
            menu.Add(numdashestoggle);
            menu.Add(difficultytoggle);
            menu.Add(moreoptionsbtn);
            menu.Add(repeatroomstoggle);
            menu.Add(enterunknowntoggle);
            menu.Add(enterunknowntext);
            menu.Add(shinetoggle);
            menu.Add(darktoggle);
            menu.Add(goldentoggle);
            menu.Add(variantstoggle);
            menu.Add(decorationstoggle);
            menu.Add(startbutton);
            menu.Add(hashtext);
            menu.Add(errortext);

            Scene.Add(menu);
        }
Beispiel #19
0
        /// <summary>
        /// Create the mod menu subsection including the section header in the given menu.
        /// The default implementation uses reflection to attempt creating a menu.
        /// </summary>
        /// <param name="menu">Menu to add the section to.</param>
        /// <param name="inGame">Whether we're in-game (paused) or in the main menu.</param>
        /// <param name="snapshot">The Level.PauseSnapshot</param>
        public virtual void CreateModMenuSection(TextMenu menu, bool inGame, EventInstance snapshot)
        {
            Type type = SettingsType;
            EverestModuleSettings settings = _Settings;

            if (type == null || settings == null)
            {
                return;
            }

            // The default name prefix.
            string typeName = type.Name.ToLowerInvariant();

            if (typeName.EndsWith("settings"))
            {
                typeName = typeName.Substring(0, typeName.Length - 8);
            }
            string nameDefaultPrefix = $"modoptions_{typeName}_";

            // Any attributes we may want to get and read from later.
            SettingInGameAttribute      attribInGame;
            SettingRangeAttribute       attribRange;
            SettingNumberInputAttribute attribNumber;

            // If the settings type has got the InGame attrib, only show it in the matching situation.
            if ((attribInGame = type.GetCustomAttribute <SettingInGameAttribute>()) != null &&
                attribInGame.InGame != inGame)
            {
                return;
            }

            bool headerCreated = false;

            if (GetType().GetMethod("CreateModMenuSection").DeclaringType != typeof(EverestModule))
            {
                CreateModMenuSectionHeader(menu, inGame, snapshot);
                headerCreated = true;
            }

            PropertyInfo[] props;
            if (type == _PrevSettingsType)
            {
                props = _PrevSettingsProps;
            }
            else
            {
                _PrevSettingsProps = props = type.GetProperties();
                _PrevSettingsType  = type;
            }

            foreach (PropertyInfo prop in props)
            {
                MethodInfo creator = type.GetMethod(
                    $"Create{prop.Name}Entry",
                    BindingFlags.Public | BindingFlags.Instance,
                    null,
                    new Type[] { typeof(TextMenu), typeof(bool) },
                    new ParameterModifier[0]
                    );

                if (creator != null)
                {
                    if (!headerCreated)
                    {
                        CreateModMenuSectionHeader(menu, inGame, snapshot);
                        headerCreated = true;
                    }

                    creator.GetFastDelegate()(settings, menu, inGame);
                    continue;
                }

                if ((attribInGame = prop.GetCustomAttribute <SettingInGameAttribute>()) != null &&
                    attribInGame.InGame != inGame)
                {
                    continue;
                }

                if (prop.GetCustomAttribute <SettingIgnoreAttribute>() != null)
                {
                    continue;
                }

                if (!prop.CanRead || !prop.CanWrite)
                {
                    continue;
                }

                string name = prop.GetCustomAttribute <SettingNameAttribute>()?.Name ?? $"{nameDefaultPrefix}{prop.Name.ToLowerInvariant()}";
                name = name.DialogCleanOrNull() ?? prop.Name.SpacedPascalCase();

                bool needsRelaunch = prop.GetCustomAttribute <SettingNeedsRelaunchAttribute>() != null;

                string description = prop.GetCustomAttribute <SettingSubTextAttribute>()?.Description;

                TextMenu.Item item     = null;
                Type          propType = prop.PropertyType;
                object        value    = prop.GetValue(settings);

                // Create the matching item based off of the type and attributes.

                if (propType == typeof(bool))
                {
                    item =
                        new TextMenu.OnOff(name, (bool)value)
                        .Change(v => prop.SetValue(settings, v))
                    ;
                }
                else if (
                    propType == typeof(int) &&
                    (attribRange = prop.GetCustomAttribute <SettingRangeAttribute>()) != null
                    )
                {
                    if (attribRange.LargeRange)
                    {
                        item =
                            new TextMenuExt.IntSlider(name, attribRange.Min, attribRange.Max, (int)value)
                            .Change(v => prop.SetValue(settings, v))
                        ;
                    }
                    else
                    {
                        item =
                            new TextMenu.Slider(name, i => i.ToString(), attribRange.Min, attribRange.Max, (int)value)
                            .Change(v => prop.SetValue(settings, v))
                        ;
                    }
                }
                else if ((propType == typeof(int) || propType == typeof(float)) &&
                         (attribNumber = prop.GetCustomAttribute <SettingNumberInputAttribute>()) != null)
                {
                    float          currentValue;
                    Action <float> valueSetter;
                    if (propType == typeof(int))
                    {
                        currentValue = (int)value;
                        valueSetter  = v => prop.SetValue(settings, (int)v);
                    }
                    else
                    {
                        currentValue = (float)value;
                        valueSetter  = v => prop.SetValue(settings, v);
                    }
                    int  maxLength      = attribNumber.MaxLength;
                    bool allowNegatives = attribNumber.AllowNegatives;

                    item =
                        new TextMenu.Button(name + ": " + currentValue.ToString($"F{maxLength}").TrimEnd('0').TrimEnd('.'))
                        .Pressed(() => {
                        Audio.Play(SFX.ui_main_savefile_rename_start);
                        menu.SceneAs <Overworld>().Goto <OuiNumberEntry>().Init <OuiModOptions>(
                            currentValue,
                            valueSetter,
                            maxLength,
                            propType == typeof(float),
                            allowNegatives
                            );
                    })
                    ;
                }
                else if (propType.IsEnum)
                {
                    Array enumValues = Enum.GetValues(propType);
                    Array.Sort((int[])enumValues);
                    string enumNamePrefix = $"{nameDefaultPrefix}{prop.Name.ToLowerInvariant()}_";
                    item =
                        new TextMenu.Slider(name, (i) => {
                        string enumName = enumValues.GetValue(i).ToString();
                        return
                        ($"{enumNamePrefix}{enumName.ToLowerInvariant()}".DialogCleanOrNull() ??
                         $"modoptions_{propType.Name.ToLowerInvariant()}_{enumName.ToLowerInvariant()}".DialogCleanOrNull() ??
                         enumName);
                    }, 0, enumValues.Length - 1, (int)value)
                        .Change(v => prop.SetValue(settings, v))
                    ;
                }
                else if (!inGame && propType == typeof(string))
                {
                    int maxValueLength = prop.GetCustomAttribute <SettingMaxLengthAttribute>()?.Max ?? 12;
                    int minValueLength = prop.GetCustomAttribute <SettingMinLengthAttribute>()?.Min ?? 1;

                    item =
                        new TextMenu.Button(name + ": " + value)
                        .Pressed(() => {
                        Audio.Play(SFX.ui_main_savefile_rename_start);
                        menu.SceneAs <Overworld>().Goto <OuiModOptionString>().Init <OuiModOptions>(
                            (string)value,
                            v => prop.SetValue(settings, v),
                            maxValueLength,
                            minValueLength
                            );
                    })
                    ;
                }

                if (item == null)
                {
                    continue;
                }

                if (!headerCreated)
                {
                    CreateModMenuSectionHeader(menu, inGame, snapshot);
                    headerCreated = true;
                }

                menu.Add(item);

                if (needsRelaunch)
                {
                    item = item.NeedsRelaunch(menu);
                }

                if (description != null)
                {
                    item = item.AddDescription(menu, description.DialogCleanOrNull() ?? description);
                }
            }

            foreach (PropertyInfo prop in type.GetProperties())
            {
                if ((attribInGame = prop.GetCustomAttribute <SettingInGameAttribute>()) != null &&
                    attribInGame.InGame != inGame)
                {
                    continue;
                }

                if (prop.GetCustomAttribute <SettingIgnoreAttribute>() != null)
                {
                    continue;
                }

                if (!prop.CanRead || !prop.CanWrite)
                {
                    continue;
                }

                if (!typeof(ButtonBinding).IsAssignableFrom(prop.PropertyType))
                {
                    continue;
                }

                if (!headerCreated)
                {
                    CreateModMenuSectionHeader(menu, inGame, snapshot);
                    headerCreated = true;
                }

                CreateModMenuSectionKeyBindings(menu, inGame, snapshot);
                break;
            }
        }
        private void ReloadMenu()
        {
            menu = new TextMenu {
                new TextMenu.Header(Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_HEADER")),
                new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_TOGGLEALL")).Pressed(() => {
                    var items = menu.GetItems();
                    TextMenu.OnOff firstToggle = null;
                    foreach (var item in items)
                    {
                        if (item is TextMenu.OnOff)
                        {
                            firstToggle = item as TextMenu.OnOff;
                            break;
                        }
                    }
                    if (firstToggle == null)
                    {
                        // ???
                        return;
                    }

                    var newValue = 1 - firstToggle.Index;
                    for (int i = 0; i < items.Count; i++)
                    {
                        if (items[i] is TextMenu.OnOff toggle)
                        {
                            toggle.Index = newValue;
                            toggle.OnValueChange(toggle.Values[newValue].Item2);
                        }
                    }
                }),
            };

            // Create submenu for Celeste, campaigns, then other levelsets
            AddLevelSetMenu("Celeste");
            List <string> completedLevelSets = new List <string> {
                "Celeste"
            };

            var campaigns = RandoModule.Instance.MetaConfig.Campaigns;

            foreach (RandoMetadataCampaign campaign in campaigns)
            {
                menu.Add(new TextMenu.SubHeader(DialogExt.CleanLevelSet(campaign.Name)));
                foreach (RandoMetadataLevelSet levelSet in campaign.LevelSets)
                {
                    var name = levelSet.Name;
                    if (RandoLogic.LevelSets.TryGetValue(levelSet.ID, out var keys))
                    {
                        AddLevelSetToggle(name, keys);
                        completedLevelSets.Add(levelSet.ID);
                    }
                }
            }

            foreach (string levelSet in RandoLogic.LevelSets.Keys)
            {
                if (!completedLevelSets.Contains(levelSet))
                {
                    AddLevelSetMenu(levelSet);
                }
            }

            // If Celeste is not the only levelset, Reset should turn all other levelsets off
            if (RandoLogic.LevelSets.Count > 1)
            {
                menu.Insert(2, new TextMenu.Button(Dialog.Clean("MODOPTIONS_RANDOMIZER_MAPPICKER_RESET")).Pressed(() => {
                    Settings.SetNormalMaps();
                    // this is a stupid way to do this
                    int levelsetIdx = -1;
                    foreach (var item in menu.GetItems())
                    {
                        if (item is TextMenu.SubHeader && !(item is TextMenuExt.SubHeaderExt))
                        {
                            levelsetIdx++;
                        }
                        else if (item is TextMenu.OnOff toggle)
                        {
                            toggle.Index = levelsetIdx == 0 ? 1 : 0;
                        }
                    }
                }));
            }

            Scene.Add(menu);
        }