public static OpTab[] BuildOpTab()
        {
            OpTab[] optab = new OpTab[Global.SIZE];

            for (int i = 0; i < Global.SIZE; i++)
            {
                optab[i]   = new OpTab(MAXBRANCHFACTOR);
                optab[i].n = 0;
                if (i >= DIM)
                {
                    optab[i].ops[optab[i].n++] = (byte)(i - DIM);
                }
                if (i % DIM > 0)
                {
                    optab[i].ops[optab[i].n++] = (byte)(i - 1);
                }
                if (i % DIM < DIM - 1)
                {
                    optab[i].ops[optab[i].n++] = (byte)(i + 1);
                }
                if (i < Global.SIZE - DIM)
                {
                    optab[i].ops[optab[i].n++] = (byte)(i + DIM);
                }
            }

            return(optab);
        }
Beispiel #2
0
        // my UI
        public override void Initialize()
        {
            base.Initialize();

            Tabs    = new OpTab[1];
            Tabs[0] = new OpTab("EFTAB");
            Tabs[0].AddItem(new OpLabel(new Vector2(100f, 550f), new Vector2(400f, 40f), "EFRW - EFLFE mod config", FLabelAlignment.Center, true));
            float y = 460f;

            // OpKeyBinder

            // general features
            AddCheckBox(ref y, nameof(SlowBackMotion), true, "Slow motion on back flip.");
            AddCheckBox(ref y, nameof(MoveAcc), true, "Smooth acceleration of running speed.");
            AddCheckBox(ref y, nameof(AirInLungsX2), true, "Second breath underwater (AirInLungs x2).");
            AddCheckBox(ref y, nameof(BrokenTeleport), true, "Broken teleportation (key C).");

            // misc
            AddCheckBox(ref y, nameof(ClearWater), false, "When under water, make it transparent.");
            AddCheckBox(ref y, nameof(MaxCycleTime), false, "Max cycle time (no random).");
            AddCheckBox(ref y, nameof(NightMode), false, "Night time mode (experimental).");
#if DEBUG
            AddCheckBox(ref y, nameof(UnlimitedRedCycles), false, "Unlimited cycles for Hunter.");
#endif
        }
Beispiel #3
0
 public UnconfiguableOI(PartialityMod mod, Exception exception) : base(mod)
 {
     Tabs           = new OpTab[1];
     Tabs[0]        = new OpTab();
     this.reason    = Reason.InitError;
     this.exception = exception.ToString();
 }
Beispiel #4
0
        public void KillTabElements()
        {
            foreach (KeyValuePair <string, OpTab> item in OptionScript.tabs)
            {
                OpTab tab = OptionScript.tabs[item.Key];

                foreach (UIelement element in tab.items)
                {
                    foreach (MenuObject obj in element.subObjects)
                    {
                        obj.RemoveSprites();
                        //this.pages[0].subObjects.Remove(obj);
                    }
                    element.myContainer.RemoveAllChildren();
                    this.pages[0].Container.RemoveChild(element.myContainer);
                    element.myContainer.RemoveFromContainer();
                    element.Unload();
                }
                tab.Unload();
            }

            //this.pages[0].subObjects.Remove(modListBound.menuObj);
            //this.pages[0].subObjects.Remove(modCanvasBound.menuObj);
            menuTab.Unload();
        }
Beispiel #5
0
        /// <summary>
        /// Adds Basic Profile on top of OpTab
        /// </summary>
        /// <param name="tab"><see cref="OpTab"/> which will contain the profile</param>
        /// <param name="mod"><see cref="RainWorldMod"/> that has basic information of the mod</param>
        public static void AddBasicProfile(OpTab tab, RainWorldMod mod)
        {
            tab.AddItems(new OpLabel(new Vector2(100f, 550f), new Vector2(400f, 50f), mod.ModID, FLabelAlignment.Center, true));
            tab.AddItems(new OpLabel(new Vector2(50f, 500f), new Vector2(100f, 20f), InternalTranslator.Translate("Version: <ModVersion>").Replace("<ModVersion>", mod.Version), FLabelAlignment.Left));

            if (mod.author != RainWorldMod.authorNull)
            {
                tab.AddItems(new OpLabel(new Vector2(350f, 500f), new Vector2(200f, 20f), InternalTranslator.Translate("Author: <ModAuthor>").Replace("<ModAuthor>", mod.author), FLabelAlignment.Right)
                {
                    autoWrap = true
                });
            }

            /*
             * if (mod.coauthor != RainWorldMod.authorNull)
             * {
             *  labelCoauthor = new OpLabel(new Vector2(100f, 420f), new Vector2(300f, 20f), string.Concat("Coautor: ", mod.coauthor));
             *  Tabs[0].AddItem(labelCoauthor);
             *  labelCoauthor.autoWrap = true;
             * }
             * if(mod.description != RainWorldMod.authorNull)
             * {
             *  labelDesc = new OpLabel(new Vector2(80f, 350f), new Vector2(340f, 20f), mod.description, FLabelAlignment.Left);
             *  Tabs[0].AddItem(labelDesc);
             *  labelDesc.autoWrap = true;
             * } */
        }
Beispiel #6
0
        public override void Initialize()
        {
            base.Initialize();
            Tabs    = new OpTab[1];
            Tabs[0] = new OpTab("Overseers");

            cModeBox     = new OpComboBox(new Vector2(200, 210), 150, "colourMode", Enum.GetNames(typeof(ColourMode)), "RandomStatic");
            cPickerLabel = new OpLabel(150, 160, "Custom colour selector");
            cPicker      = new OpColorPicker(new Vector2(200, 7), "customColour", "A369E0");

            Tabs[0].AddItems(
                new OpLabel(new Vector2(100, 550), new Vector2(400, 40), rwMod.ModID, bigText: true),
                new OpLabel(new Vector2(150, 500), new Vector2(150, 30), $"v{rwMod.Version}"),
                new OpLabel(new Vector2(300, 500), new Vector2(150, 30), $"by {rwMod.author}"),

                new OpLabel(150, 400, "Minimum overseer count per region"),
                new OpSlider(new Vector2(200, 360), "min", new IntVector2(5, 100), 200, false, defaultMin),

                new OpLabel(150, 320, "Maximum overseer count per region"),
                new OpSlider(new Vector2(200, 280), "max", new IntVector2(5, 100), 200, false, defaultMax),

                new OpLabel(150, 240, "Colour mode"),
                cModeBox,

                cPickerLabel, cPicker
                );
        }
Beispiel #7
0
        public static void ChangeSelectedTab()
        {
            currentTab.Hide();

            currentTab = OptionScript.tabs[string.Concat(selectedModIndex.ToString("D3") + "_" + selectedTabIndex.ToString("D2"))];

            currentTab.Show();
        }
Beispiel #8
0
        public override void Initialize()
        {
            // hopefully all of the 'magic numbers' can be forgiven
            songKeyBindings = new KeyCode[4];

            base.Initialize();
            Tabs    = new OpTab[1];
            Tabs[0] = new OpTab("FMTTM");

            // metadata start
            string modName = FMTTMMod.Instance.Info.Metadata.Name;
            string modVrsn = FMTTMMod.Instance.Info.Metadata.Version.ToString();
            string modAuth = FMTTMMod.Instance.Info.Metadata.GUID.Split('.')[0];

            Tabs[0].AddItems(new UIelement[]
            {
                new OpLabel(new Vector2(50, 550), new Vector2(150, 40), modName, FLabelAlignment.Left, true),
                new OpLabel(new Vector2(228, 552), new Vector2(100, 30), $"by {modAuth}", FLabelAlignment.Left),
                new OpLabel(new Vector2(58, 535), new Vector2(100, 15), $"v{modVrsn}", FLabelAlignment.Left),
                new OpLabel(new Vector2(40, 500), new Vector2(250, 15), "Configure song hotkey for each player below!", FLabelAlignment.Left)
            });
            // metadata end

            // player control config start
            Vector2 rectSize = new Vector2(245, 59);

            int[,] controlConfigBoxCoords = new int[, ]
            {
                { 50, 400 }, { 305, 400 },
                { 50, 330 }, { 305, 330 }
            };

            for (int i = 0; i < controlConfigBoxCoords.GetLength(0); i++)
            {
                // rect's position coords (bottom-left corner)
                Vector2 bl = new Vector2(controlConfigBoxCoords[i, 0], controlConfigBoxCoords[i, 1]);

                OpRect  rect  = new OpRect(bl, rectSize);
                OpLabel label = new OpLabel(
                    new Vector2(bl.x + 5, bl.y + 20),
                    new Vector2(100, 15), $"Player {i + 1}");

                string      keyCodeString = (i == 0) ? KeyCode.C.ToString() : KeyCode.None.ToString();
                OpKeyBinder keyBinder     = new OpKeyBinder(
                    new Vector2(bl.x + 98, bl.y + 7),
                    new Vector2(140, 45), modID: FMTTMMod.Instance.Info.Metadata.GUID, $"player{i + 1}_key",
                    keyCodeString, false, OpKeyBinder.BindController.AnyController);

                Tabs[0].AddItems(new UIelement[] { rect, label, keyBinder });
            }
            // player control config end
        }
Beispiel #9
0
        private void PopUp(bool error)
        {
            OpTab tab = CompletelyOptional.ConfigMenu.currentInterface.Tabs.First(x => x.name.Equals("Browse RainDB"));

            if (OptionInterface.IsConfigScreen && (tab != null) && !tab.isHidden)
            {
                string labelText   = "N/A";
                string buttonText  = "ERROR";
                string buttonText2 = null;
                CustomWorldOption.OptionSignal signal = CustomWorldOption.OptionSignal.Empty;
                if (!error)
                {
                    labelText  = $"[{this.packName}] requires additional mods to function:\n\n";
                    labelText += $"The required files [{string.Join(", ", dependenciesName.ToArray())}] have been downloaded";
                    if (CustomWorldMod.usingBepinex)
                    {
                        labelText += $" to BepInEx's plugins folder. \nPlease restart the game to apply the changes.";
                    }
                    else
                    {
                        labelText += $"to Partiality's Mods folder. \nPlease close the game and apply them using the Partiality Launcher.";
                    }
                    buttonText  = "Exit game";
                    signal      = CustomWorldOption.OptionSignal.CloseGame;
                    buttonText2 = "Later";
                }
                else
                {
                    labelText = $"Error while downloading [{this.packName}]\n\n";
                    if (File.Exists(CustomWorldMod.exeDownloaderLocation))
                    {
                        if (!this.errorLogged.Equals(string.Empty))
                        {
                            labelText += $"{this.errorLogged}\n";
                        }
                        labelText += "Please try again.\n";
                    }
                    else
                    {
                        labelText += "Missing executable.\n";
                    }
                    buttonText = "Close";
                    signal     = CustomWorldOption.OptionSignal.CloseWindow;
                }
                CustomWorldOption.CreateWindowPopUp(tab, labelText, signal, buttonText, error, buttonText2: buttonText2);
            }
        }
Beispiel #10
0
 public override void ShutDownProcess()
 {
     //foreach (UIelement element in menuTab.items)
     //{
     //foreach (MenuObject obj in element.subObjects)
     //{
     //this.pages[0].subObjects.Remove(obj);
     //}
     //this.pages[0].Container.RemoveChild(element.myContainer);
     //element.myContainer.RemoveFromContainer();
     //}
     KillTabElements();
     OptionScript.KillTabs();
     base.ShutDownProcess();
     this.darkSprite.RemoveFromContainer();
     currentTab = null;
 }
Beispiel #11
0
 public override void ShutDownProcess()
 {
     //foreach (UIelement element in menuTab.items)
     //{
     //foreach (MenuObject obj in element.subObjects)
     //{
     //this.pages[0].subObjects.Remove(obj);
     //}
     //this.pages[0].Container.RemoveChild(element.myContainer);
     //element.myContainer.RemoveFromContainer();
     //}
     KillTabElements();
     OptionScript.KillTabs();
     base.ShutDownProcess();
     this.darkSprite.RemoveFromContainer();
     currentTab = null;
     FTexture.GarbageCollect(false); // Already going to be called by vanilla
 }
Beispiel #12
0
        public override void Initialize()
        {
            base.Initialize();
            Tabs    = new OpTab[1];
            Tabs[0] = new OpTab("RichPresence");

            string modName = RegionCastPlugin.Instance.Info.Metadata.Name;
            string modVrsn = RegionCastPlugin.Instance.Info.Metadata.Version.ToString();
            string modAuth = RegionCastPlugin.Instance.Info.Metadata.GUID.Split('.')[0];

            Tabs[0].AddItems(new UIelement[]
            {
                new OpLabel(new Vector2(100f, 550f), new Vector2(400f, 40f), modName, bigText: true),
                new OpLabel(new Vector2(150f, 500f), new Vector2(150f, 30f), $"v{modVrsn}"),
                new OpLabel(new Vector2(300f, 500f), new Vector2(150f, 30f), $"by {modAuth}")
            });

            OpRadioButtonGroup buttonGroup = new OpRadioButtonGroup("toAppend", 0);

            Tabs[0].AddItems(new UIelement[] { buttonGroup });
            buttonGroup.SetButtons(new OpRadioButton[]
            {
                new OpRadioButton(40f, 400f)
                {
                    description = "No data is appended to your game mode"
                },
                new OpRadioButton(240f, 400f)
                {
                    description = "Cycle count is appended to your game mode"
                },
                new OpRadioButton(440f, 400f)
                {
                    description = "Player count (if greater than 1) is appended to your game mode"
                }
            });

            Tabs[0].AddItems(new UIelement[]
            {
                new OpLabel(new Vector2(100f, 430f), new Vector2(400f, 40f), "Data to append to game mode:"),
                new OpLabel(new Vector2(80f, 400f), new Vector2(150f, 30f), "None", FLabelAlignment.Left),
                new OpLabel(new Vector2(280f, 400f), new Vector2(150f, 30f), "Cycle count", FLabelAlignment.Left),
                new OpLabel(new Vector2(480f, 400f), new Vector2(150f, 30f), "Player count", FLabelAlignment.Left)
            });
        }
        public override void Initialize()
        {
            base.Initialize();
            updateAvailableTabWarning = false;
            errorTabWarning           = false;

            Tabs    = new OpTab[4];
            Tabs[0] = new OpTab("Main Tab");
            MainTabRedux(0);

            Tabs[1] = new OpTab("Analyzer");
            AnalyserSaveTab(1);

            Tabs[2] = new OpTab("Browse RainDB");
            PackBrowser(2);

            Tabs[3] = new OpTab("News");
            NewsTab(3);
        }
        public override void Update(float dt)
        {
            base.Update(dt);
            counter += 8f * dt;

            try
            {
                if (errorTabWarning)
                {
                    OpTab errorTab = Tabs.First(x => x.name.Equals("Analyzer"));
                    errorTab.color = Color.Lerp(Color.white, Color.red, 0.5f * (0.65f - Mathf.Sin(counter + Mathf.PI)));
                }

                OpTab raindbTab = Tabs.First(x => x.name.Equals("Browse RainDB"));
                if (updateAvailableTabWarning)
                {
                    //OpTab raindbTab = Tabs.First(x => x.name.Equals("Browse RainDB"));
                    raindbTab.color = Color.Lerp(Color.white, Color.green, 0.5f * (0.65f - Mathf.Sin(counter + Mathf.PI)));
                }
                if (!raindbTab.isHidden && CustomWorldMod.scripts != null)
                {
                    PackDownloader script = CustomWorldMod.scripts.Find(x => x is PackDownloader) as PackDownloader;
                    if (script != null)
                    {
                        if (script.downloadButton == null)
                        {
                            OpSimpleButton downloadButton = (Tabs.First(x => x.name.Equals("Browse RainDB")).items.Find(x => x is OpSimpleButton button && button.signal.Contains(script.packName)) as OpSimpleButton);
                            script.downloadButton = downloadButton;
                        }
                    }
                }

                if (updatedNews)
                {
                    OpTab news = Tabs.First(x => x.name.ToLower().Contains("news"));
                    news.color = Color.Lerp(Color.white, Color.blue, 0.5f * (0.65f - Mathf.Sin(counter + Mathf.PI)));
                }
            }
            catch (Exception e) { CustomWorldMod.Log("Error getting downloadButton " + e, true); }
        }
Beispiel #15
0
#pragma warning restore IDE0060
#pragma warning restore CA1822

        public override void Initialize()
        {
            if (this.reason == Reason.TooManyMod)
            {
                ListMods();
                return;
            }

            Tabs    = new OpTab[1];
            Tabs[0] = new OpTab();

            if (this.reason == Reason.NoMod)
            {
                TutoInit();
                return;
            }

            GeneratedOI.AddBasicProfile(Tabs[0], rwMod);

            switch (this.reason)
            {
            case Reason.NoInterface:
                if (rwMod.description != RainWorldMod.authorNull)
                {
                    Tabs[0].AddItems(new OpLabelLong(new Vector2(50f, 200f), new Vector2(500f, 250f), rwMod.description, alignment: FLabelAlignment.Center));
                    labelSluggo0 = new OpLabel(new Vector2(100f, 150f), new Vector2(400f, 20f),
                                               InternalTranslator.Translate(rwMod.type == RainWorldMod.Type.PartialityMod ? "This Partiality Mod has no Option Interface." : "This BepInEx Plugin has no Option Interface."));
                }
                else
                {
                    labelSluggo0 = new OpLabel(new Vector2(100f, 350f), new Vector2(400f, 20f),
                                               InternalTranslator.Translate(rwMod.type == RainWorldMod.Type.PartialityMod ? "This Partiality Mod has no Option Interface." : "This BepInEx Plugin has no Option Interface."));
                }

                Tabs[0].AddItems(labelSluggo0);

                break;

            case Reason.InitError:
                blue = new OpRect(new Vector2(30f, 20f), new Vector2(540f, 420f))
                {
                    alpha = 0.7f, colorFill = new Color(0.121568627f, 0.40392156862f, 0.69411764705f, 1f)
                };

                Color white = Menu.Menu.MenuRGB(Menu.Menu.MenuColors.White);
                oof = new OpLabel(new Vector2(100f, 380f), new Vector2(30f, 40f), ":(", FLabelAlignment.Left, true)
                {
                    color = white
                };
                labelSluggo0 = new OpLabel(new Vector2(150f, 390f), new Vector2(300f, 20f), InternalTranslator.Translate("There was an issue initializing OptionInterface."))
                {
                    color = white
                };
                labelSluggo1 = new OpLabelLong(new Vector2(50f, 40f), new Vector2(500f, 320f), exception)
                {
                    color = white, allowOverflow = false
                };
                labelVersion = new OpLabel(new Vector2(50f, 480f), new Vector2(100f, 20f), string.Concat(Environment.NewLine, "Config Machine ", MenuTab.GetCMVersion()), FLabelAlignment.Left);

                Tabs[0].AddItems(blue, oof, labelSluggo0, labelSluggo1, labelVersion);

                break;
            }
        }
Beispiel #16
0
        public override void Initialize()
        {
            base.Initialize();

            if (mode == GenMode.BepInExConfig)
            {
                ICollection <ConfigDefinition> keys = bepConfig.Keys;
                List <string> sections = new List <string>();
                foreach (ConfigDefinition k in keys)
                {
                    // Debug.Log($"{rwMod.ModID}) {k.Section}: {k.Key}");
                    if (!sections.Contains(k.Section))
                    {
                        sections.Add(k.Section);
                    }
                }
                sections.Sort();

                bool        hasUnsupported = false, hasFirstScroll = false;
                OpScrollBox firstScroll = null;
                Tabs = new OpTab[Mathf.Min(20, sections.Count)];
                for (int t = 0; t < Tabs.Length; t++)
                {
                    Tabs[t] = new OpTab(sections[t]);
                    float h = t != 0 ? 50f : 150f;
                    List <ConfigDefinition> cds = new List <ConfigDefinition>();
                    foreach (ConfigDefinition k in keys)
                    {
                        if (k.Section == sections[t])
                        {
                            cds.Add(k);
                        }
                    }
                    cds.Sort(CompareCDkey);
                    List <UIelement> elms = new List <UIelement>();
                    for (int e = 0; e < cds.Count; e++)
                    {
                        if (TryGetBase(bepConfig, cds[e], out ConfigEntryBase entryBase))
                        {
                            string desc = entryBase.Description.Description; // LoremIpsum.Generate(3, 4);
                            switch (entryBase.SettingType.Name.ToLower())
                            {
                            case "bool":     // OpCheckBox
                            case "boolean":
                                if (bepConfig.TryGetEntry(cds[e], out ConfigEntry <bool> eBool))
                                {
                                    elms.Add(new OpCheckBox(new Vector2(30f, 600f - h - 40f), GenerateKey(cds[e]), (bool)eBool.DefaultValue)
                                    {
                                        description = GetFirstSentence(desc)
                                    });
                                    elms.Add(new OpLabel(new Vector2(20f, 600f - h - 15f), new Vector2(70f, 15f), cds[e].Key)
                                    {
                                        alignment = FLabelAlignment.Left, description = GetFirstSentence(desc), bumpBehav = (elms[elms.Count - 1] as UIconfig).bumpBehav
                                    });
                                    if (!string.IsNullOrEmpty(desc))
                                    {
                                        elms.Add(new OpLabelLong(new Vector2(80f, 600f - h - 80f), new Vector2(500f, 45f), desc));
                                    }
                                    h += 60f;
                                }
                                else
                                {
                                    continue;
                                }
                                break;

                            case "byte":     //OpSliderSubtle
                                if (bepConfig.TryGetEntry(cds[e], out ConfigEntry <byte> eByte))
                                {
                                    elms.Add(new OpSliderSubtle(new Vector2(30f, 600f - h - 45f), GenerateKey(cds[e]), new IntVector2(0, 20), 240, false, Mathf.Clamp((byte)eByte.DefaultValue, 0, 20))
                                    {
                                        description = GetFirstSentence(desc)
                                    });
                                    elms.Add(new OpLabel(new Vector2(20f, 600f - h - 15f), new Vector2(120f, 15f), cds[e].Key)
                                    {
                                        alignment = FLabelAlignment.Left, description = GetFirstSentence(desc), bumpBehav = (elms[elms.Count - 1] as UIconfig).bumpBehav
                                    });
                                    if (!string.IsNullOrEmpty(desc))
                                    {
                                        elms.Add(new OpLabelLong(new Vector2(80f, 600f - h - 90f), new Vector2(500f, 45f), desc));
                                    }
                                    h += 90f;
                                }
                                else
                                {
                                    continue;
                                }
                                break;

                            case "uint":     //OpSlider
                            case "uint32":
                                if (bepConfig.TryGetEntry(cds[e], out ConfigEntry <uint> eUint))
                                {
                                    elms.Add(new OpSlider(new Vector2(30f, 600f - h - 45f), GenerateKey(cds[e]), new IntVector2(0, 100), 400, false, Mathf.Clamp(Convert.ToInt32((uint)eUint.DefaultValue), 0, 100))
                                    {
                                        description = GetFirstSentence(desc)
                                    });
                                    elms.Add(new OpLabel(new Vector2(20f, 600f - h - 15f), new Vector2(120f, 15f), cds[e].Key)
                                    {
                                        alignment = FLabelAlignment.Left, description = GetFirstSentence(desc), bumpBehav = (elms[elms.Count - 1] as UIconfig).bumpBehav
                                    });
                                    if (!string.IsNullOrEmpty(desc))
                                    {
                                        elms.Add(new OpLabelLong(new Vector2(80f, 600f - h - 90f), new Vector2(500f, 45f), desc));
                                    }
                                    h += 90f;
                                }
                                else
                                {
                                    continue;
                                }
                                break;

                            case "int":     //OpUpdown
                            case "int32":
                                if (bepConfig.TryGetEntry(cds[e], out ConfigEntry <int> eInt))
                                {
                                    elms.Add(new OpUpdown(new Vector2(30f, 600f - h - 45f), 110f, GenerateKey(cds[e]), (int)eInt.DefaultValue)
                                    {
                                        description = GetFirstSentence(desc), allowSpace = true
                                    });
                                    elms.Add(new OpLabel(new Vector2(20f, 600f - h - 15f), new Vector2(120f, 15f), cds[e].Key)
                                    {
                                        alignment = FLabelAlignment.Left, description = GetFirstSentence(desc), bumpBehav = (elms[elms.Count - 1] as UIconfig).bumpBehav
                                    });
                                    if (!string.IsNullOrEmpty(desc))
                                    {
                                        elms.Add(new OpLabelLong(new Vector2(160f, 600f - h - 60f), new Vector2(420f, 45f), desc));
                                    }
                                    h += 60f;
                                }
                                else
                                {
                                    continue;
                                }
                                break;

                            case "float":     //OpUpdown
                            case "single":
                                if (bepConfig.TryGetEntry(cds[e], out ConfigEntry <float> eFloat))
                                {
                                    elms.Add(new OpUpdown(new Vector2(30f, 600f - h - 45f), 110f, GenerateKey(cds[e]), (float)eFloat.DefaultValue, 2)
                                    {
                                        description = GetFirstSentence(desc), allowSpace = true
                                    });
                                    elms.Add(new OpLabel(new Vector2(20f, 600f - h - 15f), new Vector2(120f, 15f), cds[e].Key)
                                    {
                                        alignment = FLabelAlignment.Left, description = GetFirstSentence(desc), bumpBehav = (elms[elms.Count - 1] as UIconfig).bumpBehav
                                    });
                                    if (!string.IsNullOrEmpty(desc))
                                    {
                                        elms.Add(new OpLabelLong(new Vector2(160f, 600f - h - 60f), new Vector2(420f, 45f), desc));
                                    }
                                    h += 60f;
                                }
                                else
                                {
                                    continue;
                                }
                                break;

                            case "string":     //OpTextBox or OpColorPicker
                                if (bepConfig.TryGetEntry(cds[e], out ConfigEntry <string> eString))
                                {
                                    string defaultString = (string)eString.DefaultValue;
                                    if (OpColorPicker.IsStringHexColor(defaultString))
                                    {     //OpColorPicker
                                        elms.Add(new OpColorPicker(new Vector2(30f, 600f - h - 170f), GenerateKey(cds[e]), defaultString));
                                        elms.Add(new OpLabel(new Vector2(20f, 600f - h - 15f), new Vector2(120f, 15f), cds[e].Key)
                                        {
                                            alignment = FLabelAlignment.Left, description = GetFirstSentence(desc), bumpBehav = (elms[elms.Count - 1] as UIconfig).bumpBehav
                                        });
                                        if (!string.IsNullOrEmpty(desc))
                                        {
                                            elms.Add(new OpLabelLong(new Vector2(200f, 600f - h - 170f), new Vector2(380f, 135f), desc));
                                        }
                                        h += 170f;
                                    }
                                    else
                                    {
                                        elms.Add(new OpTextBox(new Vector2(30f, 600f - h - 45f), 110f, GenerateKey(cds[e]), defaultString, OpTextBox.Accept.StringASCII)
                                        {
                                            description = GetFirstSentence(desc)
                                        });
                                        elms.Add(new OpLabel(new Vector2(20f, 600f - h - 15f), new Vector2(120f, 15f), cds[e].Key)
                                        {
                                            alignment = FLabelAlignment.Left, description = GetFirstSentence(desc), bumpBehav = (elms[elms.Count - 1] as UIconfig).bumpBehav
                                        });
                                        if (!string.IsNullOrEmpty(desc))
                                        {
                                            elms.Add(new OpLabelLong(new Vector2(160f, 600f - h - 60f), new Vector2(420f, 45f), desc));
                                        }
                                        h += 60f;
                                    }
                                }
                                else
                                {
                                    continue;
                                }
                                break;

                            case "keycode":     //OpKeyBinder
                                if (bepConfig.TryGetEntry(cds[e], out ConfigEntry <KeyCode> eKeyCode))
                                {
                                    elms.Add(new OpKeyBinder(new Vector2(30f, 600f - h - 50f), new Vector2(150f, 30f), rwMod.ModID, GenerateKey(cds[e]), ((KeyCode)eKeyCode.DefaultValue).ToString(), false));
                                    elms.Add(new OpLabel(new Vector2(20f, 600f - h - 15f), new Vector2(120f, 15f), cds[e].Key)
                                    {
                                        alignment = FLabelAlignment.Left, description = GetFirstSentence(desc), bumpBehav = (elms[elms.Count - 1] as UIconfig).bumpBehav
                                    });
                                    if (!string.IsNullOrEmpty(desc))
                                    {
                                        elms.Add(new OpLabelLong(new Vector2(200f, 600f - h - 90f), new Vector2(380f, 75f), desc));
                                    }
                                    h += 100f;
                                }
                                else
                                {
                                    continue;
                                }
                                break;

                            default:
                                // if type is enum => OpComboBox
                                if (entryBase.SettingType.IsEnum)
                                {
                                    elms.Add(new OpResourceSelector(new Vector2(30f, 600f - h - 45f), 120f, GenerateKey(cds[e]), entryBase.SettingType, entryBase.DefaultValue.ToString()));
                                    elms.Add(new OpLabel(new Vector2(20f, 600f - h - 15f), new Vector2(120f, 15f), cds[e].Key)
                                    {
                                        alignment = FLabelAlignment.Left, description = GetFirstSentence(desc), bumpBehav = (elms[elms.Count - 1] as UIconfig).bumpBehav
                                    });
                                    if (!string.IsNullOrEmpty(desc))
                                    {
                                        elms.Add(new OpLabelLong(new Vector2(160f, 600f - h - 60f), new Vector2(420f, 45f), desc));
                                    }
                                    h += 60f;
                                    break;
                                }

                                if (TryAcceptableValueList(entryBase.Description.AcceptableValues,
                                                           out var valueType, out var values))
                                {
                                    var items = new List <ListItem>();
                                    for (var i = 0; i < values.Length; i++)
                                    {
                                        var value = values[i];
                                        var name  = TomlTypeConverter.ConvertToString(value, valueType);
                                        var item  = new ListItem(name, i)
                                        {
                                            displayName = value.ToString()
                                        };
                                        items.Add(item);
                                    }

                                    elms.Add(new OpComboBox(new Vector2(30f, 600f - h - 45f), 120f, GenerateKey(cds[e]), items, TomlTypeConverter.ConvertToString(entryBase.DefaultValue, valueType)));
                                    elms.Add(new OpLabel(new Vector2(20f, 600f - h - 15f), new Vector2(120f, 15f), cds[e].Key)
                                    {
                                        alignment = FLabelAlignment.Left, description = GetFirstSentence(desc), bumpBehav = (elms[elms.Count - 1] as UIconfig).bumpBehav
                                    });
                                    if (!string.IsNullOrEmpty(desc))
                                    {
                                        elms.Add(new OpLabelLong(new Vector2(160f, 600f - h - 60f), new Vector2(420f, 45f), desc));
                                    }
                                    h += 60f;
                                    break;
                                }

                                Debug.Log($"{rwMod.ModID} has unsupported ConfigEntry: {cds[e].Key}({entryBase.SettingType.Name})");
                                hasUnsupported = true; continue; // Not supported
                            }
                            h += 20f;                            // between gap
                        }
                    }
                    if (h <= 600f)
                    {
                        if (t == 0)
                        {
                            AddBasicProfile(Tabs[0], rwMod); hasFirstScroll = false;
                        }
                        Tabs[t].AddItems(elms.ToArray());
                    }
                    else
                    {
                        OpScrollBox box = new OpScrollBox(Tabs[t], h);
                        if (t == 0)
                        {
                            AddBasicProfile(box, rwMod); hasFirstScroll = true; firstScroll = box;
                        }
                        foreach (UIelement elm in elms)
                        {
                            elm.pos = new Vector2(elm.GetPos().x, elm.GetPos().y - 600f + h);
                        }
                        box.AddItems(elms.ToArray());
                    }
                }
                if (hasUnsupported)
                {
                    string warn = InternalTranslator.Translate("This Plugin contains types of settings that are not supported by Config Machine:") + Environment.NewLine
                                  + InternalTranslator.Translate("Go to [BepInEx]-[config] folder and use Notepad to edit those settings.");
                    if (hasFirstScroll)
                    {
                        firstScroll.AddItems(new OpLabel(new Vector2(50f, firstScroll.GetContentSize() - 600f + 525f), new Vector2(500f, 30f), warn));
                    }
                    else
                    {
                        Tabs[0].AddItems(new OpLabel(new Vector2(50f, 525f), new Vector2(500f, 20f), warn));
                    }
                }
            }
            else
            {
                Tabs    = new OpTab[1];
                Tabs[0] = new OpTab();
                AddBasicProfile(Tabs[0], rwMod);
                if (!string.IsNullOrEmpty(modDescription))
                {
                    Tabs[0].AddItems(new OpLabelLong(new Vector2(50f, 200f), new Vector2(500f, 250f), modDescription, alignment: FLabelAlignment.Center));
                }
            }
        }
Beispiel #17
0
        public void ResetCurrentConfig()
        {
            if (!currentInterface.Configuable())
            {
                return;
            }

            foreach (OpTab tab in currentInterface.Tabs)
            {
                foreach (UIelement element in tab.items)
                {
                    foreach (MenuObject obj in element.subObjects)
                    {
                        obj.RemoveSprites();
                        this.pages[0].subObjects.Remove(obj);
                    }
                    this.pages[0].Container.RemoveChild(element.myContainer);
                    element.myContainer.RemoveFromContainer();
                }
                tab.Unload();
            }
            int i = 0;

            do
            {
                string key = string.Concat(selectedModIndex.ToString("D3") + "_" + i.ToString("D2"));
                if (OptionScript.tabs.ContainsKey(key))
                {
                    OptionScript.tabs.Remove(key);
                }
                else
                {
                    break;
                }
                i++;
            } while (i < 100);

            currentInterface.Initialize();
            for (i = 0; i < currentInterface.Tabs.Length; i++)
            {
                string key = string.Concat(selectedModIndex.ToString("D3") + "_" + i.ToString("D2"));
                OptionScript.tabs.Add(key, currentInterface.Tabs[i]);
                foreach (UIelement element in currentInterface.Tabs[i].items)
                {
                    foreach (RectangularMenuObject obj in element.subObjects)
                    {
                        this.pages[0].subObjects.Add(obj);
                    }
                    this.pages[0].Container.AddChild(element.myContainer);
                }
                currentInterface.Tabs[i].Hide();
            }

            selectedTabIndex = 0;
            currentTab       = currentInterface.Tabs[0];
            currentTab.Show();
            currentInterface.SaveConfig(currentInterface.GrabConfig());
            currentInterface.ConfigOnChange();

            //OptionScript.configChanged = false;
        }
Beispiel #18
0
        public override void Initialize()
        {
            Tabs    = new OpTab[1];
            Tabs[0] = new OpTab();

            if (this.reason == Reason.NoMod)
            {
                TutoInit();
                return;
            }

            //Futile.atlasManager.LogAllElementNames();

            labelID      = new OpLabel(new Vector2(100f, 500f), new Vector2(400f, 50f), mod.ModID, FLabelAlignment.Center, true);
            labelVersion = new OpLabel(new Vector2(100f, 450f), new Vector2(100f, 20f), string.Concat("Version: ", mod.Version), FLabelAlignment.Left);
            Tabs[0].AddItems(labelID, labelVersion);
            if (mod.author != "NULL")
            {
                labelAuthor = new OpLabel(new Vector2(350f, 450f), new Vector2(200f, 20f), string.Concat("Author: ", mod.author), FLabelAlignment.Right);
                Tabs[0].AddItems(labelAuthor);
                labelAuthor.autoWrap = true;
            }

            /*
             * if (mod.coauthor != "NULL")
             * {
             *  labelCoauthor = new OpLabel(new Vector2(100f, 420f), new Vector2(300f, 20f), string.Concat("Coautor: ", mod.coauthor));
             *  Tabs[0].AddItem(labelCoauthor);
             *  labelCoauthor.autoWrap = true;
             * }
             * if(mod.description != "NULL")
             * {
             *  labelDesc = new OpLabel(new Vector2(80f, 350f), new Vector2(340f, 20f), mod.description, FLabelAlignment.Left);
             *  Tabs[0].AddItem(labelDesc);
             *  labelDesc.autoWrap = true;
             * }*/


            switch (this.reason)
            {
            case Reason.NoInterface:
                labelSluggo0 = new OpLabel(new Vector2(100f, 200f), new Vector2(400f, 20f), "This Partiality Mod/Patch cannot be configured.");
                Tabs[0].AddItems(labelSluggo0);

                break;

            case Reason.InitError:
                blue = new OpRect(new Vector2(40f, 40f), new Vector2(520f, 340f))
                {
                    alpha = 0.7f
                };
                if (OptionScript.init)
                {
                    for (int j = 0; j < 9; j++)
                    {
                        blue.rect.sprites[j].color = new Color(0.121568627f, 0.40392156862f, 0.69411764705f, 1f);
                    }
                }
                Color white = Menu.Menu.MenuRGB(Menu.Menu.MenuColors.White);
                oof = new OpLabel(new Vector2(100f, 320f), new Vector2(30f, 40f), ":(", FLabelAlignment.Left, true)
                {
                    color = white
                };
                labelSluggo0 = new OpLabel(new Vector2(100f, 320f), new Vector2(400f, 20f), "There was an issue initializing OptionInterface.")
                {
                    color = white
                };
                labelSluggo1 = new OpLabel(new Vector2(100f, 80f), new Vector2(400f, 240f), exception, FLabelAlignment.Left)
                {
                    autoWrap = true,
                    color    = white
                };
                labelSluggo1.OnChange();

                Tabs[0].AddItems(blue, oof, labelSluggo0, labelSluggo1);

                break;
            }
        }
        public override void Signal(UItrigger trigger, string signal)
        {
            base.Signal(trigger, signal);
            if (signal != null)
            {
                CustomWorldMod.Log($"Received menu signal [{signal}]");

                // Refresh config menu list
                if (signal.Equals("refresh"))
                {
                    ConfigMenu.ResetCurrentConfig();
                }
                // Reload pack list
                else if (signal.Equals("reloadRegions"))
                {
                    CustomWorldMod.LoadCustomWorldResources();
                }
                // Downnload a pack X
                else if (signal.Contains("download") || signal.Contains("update"))
                {
                    if (CustomWorldMod.scripts.FindAll(x => x is PackDownloader).Count == 0)
                    {
                        // Process ID of Rain World
                        string ID = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
                        // Divider used
                        string divider = "<div>";
                        // Name of the pack to download
                        string packName = signal.Substring(signal.IndexOf("_") + 1);
                        string url      = "";

                        CustomWorldMod.Log($"Download / update signal from [{packName}]");

                        if (CustomWorldMod.rainDbPacks.TryGetValue(packName, out RegionPack toDownload))
                        {
                            url = toDownload.packUrl;
                        }

                        if (url != null && url != string.Empty)
                        {
                            string arguments = $"{url}{divider}\"{packName}\"{divider}{ID}{divider}" + @"\" + CustomWorldMod.resourcePath + (signal.Contains("update") ? $"{divider}update" : "");
                            CustomWorldMod.Log($"Creating pack downloader for [{arguments}]");

                            CustomWorldMod.scripts.Add(new PackDownloader(arguments, packName));
                            CRExtras.TryPlayMenuSound(SoundID.MENU_Player_Join_Game);
                        }
                        else
                        {
                            CustomWorldMod.Log($"Error loading pack [{packName}] from raindb pack list", true);
                        }
                    }
                    else
                    {
                        CustomWorldMod.Log("Pack downloader in process");
                        CRExtras.TryPlayMenuSound(SoundID.MENU_Player_Unjoin_Game);
                    }
                }
                // Close the game
                else if (signal.Equals("close_game"))
                {
                    CustomWorldMod.Log("Exiting game...");
                    Application.Quit();
                }
                // Close(hide) pop-up window
                else if (signal.Equals("close_window"))
                {
                    if (currentWindowPopUp != null)
                    {
                        OpTab tab = ConfigMenu.currentInterface.Tabs.First(x => x.name.Equals("Browse RainDB"));
                        if (tab != null)
                        {
                            foreach (UIelement item in currentWindowPopUp)
                            {
                                try
                                {
                                    item.Hide();
                                }
                                catch (Exception e) { CustomWorldMod.Log("option " + e, true); }
                            }
                        }
                    }
                }
                else
                {
                    CustomWorldMod.Log($"Unknown signal [{signal}]", true);
                }
            }
        }
Beispiel #20
0
        public override void Initialize()
        {
            base.Initialize();
            Tabs = new OpTab[] { new OpTab("Config") };

            // Title
            Tabs[0].AddItems(new OpLabel(new Vector2(32f, 536f), new Vector2(256f, 32f), "Input Display Options", FLabelAlignment.Left, true));

            const float boolOffset = 150f;

            // Interpolation
            string lerpDesc = "Enable interpolation between frames (True by default)";

            Tabs[0].AddItems(new OpCheckBox(new Vector2(8f, 504f), "rwid_interpolation", true)
            {
                description = lerpDesc
            });
            Tabs[0].AddItems(new OpLabel(new Vector2(34f, 504f - 3f), new Vector2(boolOffset - 32f, 32f), "Interpolation", FLabelAlignment.Left)
            {
                description = lerpDesc
            });

            // RT indicators
            string rtiDesc = "Show real-time input indicators at the bottom left of each button (True by default)";

            Tabs[0].AddItems(new OpCheckBox(new Vector2(8f + boolOffset, 504f), "rwid_rt_indicators", true)
            {
                description = rtiDesc
            });
            Tabs[0].AddItems(new OpLabel(new Vector2(34f + boolOffset, 504f - 3f), new Vector2(boolOffset - 32f, 32f), "Show Realtime Input", FLabelAlignment.Left)
            {
                description = rtiDesc
            });

            // Use outline for label colors
            string oclDesc = "Set button labels as the outline color instead of the opposite on or off color (False by default)";

            Tabs[0].AddItems(new OpCheckBox(new Vector2(8f + boolOffset * 2f, 504f), "rwid_outline_labels", false)
            {
                description = oclDesc
            });
            Tabs[0].AddItems(new OpLabel(new Vector2(34f + boolOffset * 2f, 504f - 3f), new Vector2(boolOffset - 32f, 32f), "Outline Color Labels", FLabelAlignment.Left)
            {
                description = oclDesc
            });

            // Show the time stacker
            string stsDesc = "A bar below the input display indicates the current timeStacker (False by default)";

            Tabs[0].AddItems(new OpCheckBox(new Vector2(8f + boolOffset * 3f, 504f), "rwid_show_timestacker", false)
            {
                description = stsDesc
            });
            Tabs[0].AddItems(new OpLabel(new Vector2(34f + boolOffset * 3f, 504f - 3f), new Vector2(boolOffset - 32f, 32f), "Show timeStacker", FLabelAlignment.Left)
            {
                description = stsDesc
            });

            // Color pickers
            _backCol = new OpColorPicker(new Vector2(32f, 314f), "rwid_color_back", "FFFFFF");
            Tabs[0].AddItems(_backCol, new OpLabel(new Vector2(32f, 472f), new Vector2(150f, 16f), "Outline Color"));
            _offCol = new OpColorPicker(new Vector2(225f, 314f), "rwid_color_off", "000000");
            Tabs[0].AddItems(_offCol, new OpLabel(new Vector2(225f, 472f), new Vector2(150f, 16f), "Off Color"));
            _onCol = new OpColorPicker(new Vector2(418f, 314f), "rwid_color_on", "BFBFBF");
            Tabs[0].AddItems(_onCol, new OpLabel(new Vector2(418f, 472f), new Vector2(150f, 16f), "On Color"));

            // Alpha slider
            string aDesc = "How opaque the display is (75 by default)";

            Tabs[0].AddItems(new OpLabel(new Vector2(8f, 280f), new Vector2(40f, 24f), "Alpha", FLabelAlignment.Right)
            {
                description = aDesc
            });
            Tabs[0].AddItems(new OpSlider(new Vector2(8f + 48f, 280f - 3f), "rwid_alpha", new IntVector2(0, 100), length: 200, defaultValue: 75)
            {
                description = aDesc
            });

            // Scale slider
            string sclDesc = "The scale factor of the display (10 by default)";

            Tabs[0].AddItems(new OpLabel(new Vector2(8f, 250f), new Vector2(40f, 24f), "Scale", FLabelAlignment.Right)
            {
                description = sclDesc
            });
            Tabs[0].AddItems(new OpSlider(new Vector2(8f + 48f, 250f - 3f), "rwid_scale", new IntVector2(5, 20), length: 200, defaultValue: 10)
            {
                description = sclDesc
            });
        }
Beispiel #21
0
        private void ListMods()
        {
            const int modInPage = 20;
            int       cListNum  = Mathf.CeilToInt(configuableMods.Length / (float)modInPage);
            int       iListNum  = Mathf.CeilToInt(ignoredMods.Length / (float)modInPage);

            string modNumDecimal = "D" + (configuableMods.Length + ignoredMods.Length).ToString().Length.ToString();

            Tabs = new OpTab[cListNum + iListNum];
            for (int t = 0; t < cListNum; t++)
            {
                string name = InternalTranslator.Translate("Mods") + " " + ((t * modInPage) + 1).ToString(modNumDecimal) + " ~ "
                              + (Math.Min((t + 1) * modInPage, configuableMods.Length)).ToString(modNumDecimal);
                Tabs[t] = new OpTab(name);
                Tabs[t].AddItems(new OpLabel(new Vector2(100f, 500f), new Vector2(400f, 50f), InternalTranslator.Translate("Configurable Mod List"), FLabelAlignment.Center, true));
            }
            for (int t = cListNum; t < cListNum + iListNum; t++)
            {
                string name = InternalTranslator.Translate("Mods") + " " + (1 + configuableMods.Length + ((t - cListNum) * modInPage)).ToString(modNumDecimal) + " ~ "
                              + (configuableMods.Length + Math.Min((t - cListNum + 1) * modInPage, ignoredMods.Length)).ToString(modNumDecimal);
                Tabs[t] = new OpTab(name);
                Tabs[t].AddItems(new OpLabel(new Vector2(100f, 500f), new Vector2(400f, 50f), InternalTranslator.Translate("Other Mod List"), FLabelAlignment.Center, true));
            }

            for (int i = 0; i < configuableMods.Length; i++)
            {
                string name = configuableMods[i].ModID + " (" + configuableMods[i].Version + ")";
                string ath  = "";
                if (!string.IsNullOrEmpty(configuableMods[i].author) && configuableMods[i].author != RainWorldMod.authorNull)
                {
                    ath = configuableMods[i].author;
                }
                Vector2 pos = default;
                pos.x = i % 2 == 0 ? 40f : 320f;
                pos.y = 405f - Mathf.FloorToInt((i % modInPage) / 2f) * 40f;
                string desc = string.IsNullOrEmpty(ath) ? InternalTranslator.Translate("Configure <ModID>")
                    : InternalTranslator.Translate("Configure <ModID> by <ModAuthor>").Replace("<ModAuthor>", ath);
                Tabs[Mathf.FloorToInt(i / (float)modInPage)].AddItems(new OpSimpleButton(pos, new Vector2(240f, 30f), configuableMods[i].ModID, name)
                {
                    description = desc.Replace("<ModID>", configuableMods[i].ModID)
                });
            }

            for (int i = 0; i < ignoredMods.Length; i++)
            {
                string name = ignoredMods[i].ModID + " (" + ignoredMods[i].Version + ")";
                string desc = " ";
                if (!string.IsNullOrEmpty(ignoredMods[i].author) && ignoredMods[i].author != RainWorldMod.authorNull)
                {
                    desc = InternalTranslator.Translate("<ModID> by <ModAuthor>").Replace("<ModAuthor>", ignoredMods[i].author).Replace("<ModID>", ignoredMods[i].ModID);
                }
                Vector2 pos = default;
                pos.x = i % 2 == 0 ? 50f : 330f;
                pos.y = 410f - Mathf.FloorToInt((i % modInPage) / 2f) * 40f;
                Tabs[cListNum + Mathf.FloorToInt(i / (float)modInPage)].AddItems(new OpRect(new Vector2(pos.x - 10f, pos.y - 5f), new Vector2(240f, 30f))
                {
                    description = desc, doesBump = true
                },
                                                                                 new OpLabel(pos, new Vector2(220f, 20f), name));
            }
        }
Beispiel #22
0
        public override void Initialize()
        {
            base.Initialize();

            Tabs = new OpTab[] { new OpTab("Config") };

            const string desc =
                "Mod behavior\n" +
                "\n+ When bit by a lizard, instead of randomly killing the player, the player takes damage." +
                "\n+ Too much damage equals death." +
                "\n+ Some time after being released, or after the start of a cycle, damage is reset.";
            const string vanillaDesc =
                "Vanilla behavior\n" +
                "\n+ When not killed by a bite, slugcat is only grabbed, so you can still escape with your life if your captor drops you before reaching a den." +
                "\n+ The creature will drop you if it is stunned." +
                "\n+ After a moment, it will paralyze slugcat, so hit it with a rock or spear quickly!";

            var labelAuthor  = new OpLabel(20, 600 - 30, "by Dual", true);
            var labelVersion = new OpLabel(20, 600 - 30 - 40, "github.com/Dual-Iron/");
            var labelNote    = new OpLabel(200, 600 - 30 - 20, "Testing the waters with this mod. It's been pleasant so far.");

            var size            = new Vector2(300 - 20, 150);
            var pos             = new Vector2(10, 200 - size.y / 2);
            var rectDescription = new OpRect(pos, size)
            {
                description = "Mod mechanics"
            };
            var labelDescription = new OpLabelLong(pos + new Vector2(10, 0), rectDescription.size - Vector2.one * 20, desc, true, FLabelAlignment.Left);

            pos.x = 310;
            var rectVanillaDescription = new OpRect(pos, size)
            {
                description = "Tips on creatures grabbing slugcat"
            };
            var labelVanillaDescription = new OpLabelLong(pos + new Vector2(10, 0), rectDescription.size - Vector2.one * 20, vanillaDesc, true, FLabelAlignment.Left);

            var top           = 200;
            var labelDmgMul   = new OpLabel(20, 600 - top, "Lizard damage multiplier");
            var labelDecimal  = new OpLabel(326, 600 - top + 2, "x 0.1");
            var draggerDmgMul = new OpDragger(new Vector2(300, 600 - top), "D1", 10)
            {
                description = "Makes you take more/less damage per lizard bite. By default (x1.0), a 1/n chance for lizards to kill makes them kill in n bites.",
                min         = 0,
                max         = 50,
                colorEdge   = Color.clear,
                colorText   = new Color(122, 216, 255)
            };

            var labelDmgRegen   = new OpLabel(20, 600 - top - 30, "Lizard damage reset cooldown");
            var labelSeconds    = new OpLabel(326, 600 - top - 30 + 2, "seconds");
            var draggerDmgRegen = new OpDragger(new Vector2(300, 600 - top - 30), "D2", -1)
            {
                description = "The time it takes to reset damage after being released from a grab. Value -1 means damage is only reset at the start of a cycle.",
                min         = -1,
                max         = 60,
                colorEdge   = Color.clear,
                colorText   = new Color(122, 216, 255)
            };

            Tabs[0].AddItems(
                rectVanillaDescription,
                labelVanillaDescription,
                rectDescription,
                labelDescription,
                labelAuthor,
                labelVersion,
                labelNote,
                labelDmgMul,
                labelDecimal,
                draggerDmgMul,
                labelDmgRegen,
                labelSeconds,
                draggerDmgRegen
                );
        }
        private void CreateRegionPackList(OpTab tab, Dictionary <string, RegionPack> packs, Dictionary <string, byte[]> thumbnails, bool raindb)
        {
            //How Many Options
            int numberOfOptions = packs.Count;

            if (numberOfOptions < 1)
            {
                OpLabel label2 = new OpLabel(new Vector2(100f, 450), new Vector2(400f, 20f), "No regions available.", FLabelAlignment.Center, false);
                if (raindb && CustomWorldMod.OfflineMode)
                {
                    label2.text = "Browsing RainDB is not available in offline mode";
                }
                tab.AddItems(label2);
                return;
            }

            int spacing = 25;

            // SIZES AND POSITIONS OF ALL ELEMENTS //
            Vector2     rectSize           = new Vector2(475, 175);
            Vector2     thumbSize          = new Vector2(225, 156);
            Vector2     buttonDownloadSize = new Vector2(80, 30);
            Vector2     labelSize          = new Vector2(rectSize.x - thumbSize.x - 1.5f * spacing, 25);
            Vector2     descripSize        = new Vector2(rectSize.x - thumbSize.x - 1.5f * spacing, rectSize.y - labelSize.y - buttonDownloadSize.y);
            OpScrollBox mainScroll         = new OpScrollBox(new Vector2(25, 25), new Vector2(550, 500), (int)(spacing + ((rectSize.y + spacing) * numberOfOptions)));
            Vector2     rectPos            = new Vector2(spacing, mainScroll.contentSize - rectSize.y - spacing);

            // ---------------------------------- //

            tab.AddItems(mainScroll);

            for (int i = 0; i < numberOfOptions; i++)
            {
                RegionPack pack      = packs.ElementAt(i).Value;
                bool       activated = pack.activated;
                bool       update    = false;
                try
                {
                    update = raindb && !activated && pack.checksum != null && pack.checksum != string.Empty && !pack.checksum.Equals(CustomWorldMod.installedPacks[pack.name].checksum);
                }
                catch { CustomWorldMod.Log("Error checking the checksum for updates"); }
                Color colorEdge    = activated ? Color.white : new Color((108f / 255f), 0.001f, 0.001f);
                Color colorInverse = Color.white;

                /*
                 * if (raindb)
                 * {
                 *  colorEdge = Color.white;
                 *  try
                 *  {
                 *      // Online checksum is different from local, needs to be updated.
                 *      if (!activated && pack.checksum != null && pack.checksum != string.Empty)
                 *      {
                 *          update = !pack.checksum.Equals(CustomWorldMod.installedPacks[pack.name].checksum);
                 *      }
                 *  }
                 *  catch { CustomWorldMod.Log("Error checking the checksum for updates"); }
                 * }
                 */

                // RECTANGLE
                OpRect rectOption = new OpRect(rectPos, rectSize, 0.2f)
                {
                    doesBump = activated && !pack.packUrl.Equals(string.Empty)
                };
                mainScroll.AddItems(rectOption);
                // ---------------------------------- //


                // REGION NAME LABEL
                string nameText = pack.name;
                if (!pack.author.Equals(string.Empty))
                {
                    nameText += " [by " + pack.author.ToUpper() + "]";
                }
                OpLabel labelRegionName = new OpLabel(rectPos + new Vector2(thumbSize.x + spacing, 140), labelSize, "", FLabelAlignment.Left)
                {
                    description = nameText
                };

                // Add load order number if local pack
                if (!raindb)
                {
                    nameText = (i + 1).ToString() + "] " + nameText;
                }
                // Trim in case of overflow
                CRExtras.TrimString(ref nameText, labelSize.x, "...");
                labelRegionName.text = nameText;
                mainScroll.AddItems(labelRegionName);
                // ---------------------------------- //


                // DESCRIPTION LABEL
                OpLabelLong labelDesc = new OpLabelLong(rectPos + new Vector2(spacing + thumbSize.x, (rectSize.y - descripSize.y - labelSize.y - 0.5f * spacing)), descripSize, "", true, FLabelAlignment.Left)
                {
                    text = pack.description,
                    verticalAlignment = OpLabel.LabelVAlignment.Top,
                    allowOverflow     = false
                };
                mainScroll.AddItems(labelDesc);
                // ---------------------------------- //

                if (thumbnails.TryGetValue(pack.name, out byte[] fileData) && fileData.Length > 0)