POG Config
In-game MOD SETTINGS panel for Pit of Goblin mods. Provides toggles, sliders with numeric input, options lists, and keybind entries. Dependency for other POG mods.
| Last updated | 3 days ago |
| Total downloads | 1289 |
| Total rating | 2 |
| Categories | Mods Tools Libraries |
| Dependency string | Largo-POG_Config-1.1.1 |
| Dependants | 4 other packages depend on this package |
This mod requires the following mods to function
LavaGang-MelonLoader
The World's First Universal Mod Loader for Unity Games compatible with both Il2Cpp and Mono
Preferred version: 0.7.2README
POG Config
One shared MOD SETTINGS panel for Pit of Goblin mods, plus an editor for the game's own key binds.
Mods that support POG Config add their settings to this panel, so you get one place to change everything instead of editing config files.
Install: Thunderstore Mod Manager / r2modman, or put POGConfig.dll into the game's Mods folder (MelonLoader required).
Source and developer Wiki: github.com/largoz/POGConfig (Wiki) · Thunderstore Wiki
For players
- A MODS button in the main menu and in the pause menu, styled like the game's own buttons, with mouse, keyboard and gamepad navigation.
- A sidebar with every mod that registered settings, with a search box.
- VANILLA BINDS tab: the game's own controls, editable. Each action has two keyboard slots and one mouse slot, exactly like the game's Controls screen. Changes go straight into the game's settings.
- RESTORE DEFAULTS on every page, including the vanilla binds.
- Settings are saved automatically.
Esccancels what you are doing (typing a value, waiting for a key, an open list) and otherwise closes the panel.- Settings with many choices open a list with search and filter buttons. Type to search; arrows, Enter and Esc work too.
For mod authors
Click to expand
Reference
<Reference Include="POGConfig">
<HintPath>..\..\Mods\POGConfig.dll</HintPath>
<Private>false</Private>
</Reference>
Add using POGMods.Config; and declare a dependency on Largo-POG_Config in your Thunderstore manifest.
Registering
Register once, usually from OnInitializeMelon(). Load order does not matter: Register only stores your entries, and the panel is built the first time it opens.
Wrapping the call in a NoInlining helper keeps POG Config optional: your mod still loads if POG Config is not installed.
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using POGMods.Config;
public override void OnInitializeMelon()
{
try { TryRegisterConfig(); } catch { }
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void TryRegisterConfig()
{
POGConfig.Register("My Mod", new List<ConfigEntry>
{
new HeaderEntry("General"),
new ToggleEntry("Enable Feature", () => _enabled, v => _enabled = v, "Enabled"),
new SliderEntry("Speed", () => _speed, v => _speed = v, 0f, 10f, v => $"{v:F1}", "Speed"),
new HeaderEntry("Input"),
new KeyEntry("Hotkey", () => _key, v => _key = v, "Hotkey"),
}, new ModInfo("1.0.0", "Short description", "You"));
}
- The mod name is the sidebar label and the
MelonPreferencescategory (spaces become_). Keep it stable across releases. - The values your fields hold when you call
Registerare the defaults that RESTORE DEFAULTS goes back to. Set them first. - Calling
Registeragain with the same name replaces your earlier page instead of adding a second one.
Entry types
| Type | What it shows |
|---|---|
HeaderEntry(label) |
A section heading. No value. |
ToggleEntry(label, get, set[, prefKey]) |
A checkbox. |
SliderEntry(label, get, set, min, max[, fmt, prefKey, originValue, showFill, wholeNumbers, stepPointsCount]) |
A slider with a value box you can type into. |
OptionsSliderEntry(label, get, set, options[, prefKey]) |
A slider that picks one of several named options. |
ChoiceRow(label, get, set, options…) |
A choice from a list that opens over the page, with search and filters. New in 1.1.0. |
KeyEntry(label, get, set[, prefKey]) |
One key bind slot. |
KeyEntry(label, get(slot), set(slot, key), prefKey, slotCount) |
Up to 3 key bind slots. |
ButtonEntry(label, buttonText, onClick) |
A button that runs an action. New in 1.0.12. |
get is polled while the panel is open, so the row follows changes your mod makes on its own. set is called when the player changes the value.
SliderEntry
new SliderEntry(
string label, Func<float> get, Action<float> set,
float min, float max,
Func<float, string> fmt = null, // display text; default v => v.ToString("F1")
string prefKey = null,
float originValue = 0f, // the fill bar grows from here, in both directions
bool showFill = true,
bool wholeNumbers = false, // snap to integers
int stepPointsCount = 0) // 2 or more draws evenly spaced dots on the track
- Click the value box to type a number.
Enteror a click elsewhere applies it,Esccancels. A suffix from your formatter (43s,80%) is ignored when parsing. Values are clamped to[min, max]. - Column widths default to 35 % label, 15 % value box, the rest slider. Override with
{ LabelFraction = 0.45f, ValueFraction = 0.10f }.
new SliderEntry("Volume", () => vol, v => vol = v, 0f, 1f, v => $"{v * 100:F0}%", "Volume")
new SliderEntry("Points", () => pts, v => pts = v, 0f, 8f, v => $"{v:F0}",
"Points", 0f, false, true, 9) // whole numbers, 9 dots, no fill
OptionsSliderEntry
new OptionsSliderEntry("Difficulty", () => _difficulty, v => _difficulty = v,
new[] { "Easy", "Normal", "Hard" }, "Difficulty")
The value is the option index. Saved as an int.
KeyEntry
// One slot
new KeyEntry("Toggle Key", () => _toggleKey, v => _toggleKey = v, "ToggleKey")
// Up to three slots
private static readonly KeyCode[] _fire = { KeyCode.Mouse0, KeyCode.None, KeyCode.None };
new KeyEntry("Fire", slot => _fire[slot], (slot, v) => _fire[slot] = v, "Fire", 3)
- Click a slot, then press a key or a mouse button.
Esccancels. The small x unbinds the slot (KeyCode.None). - Every slot accepts keyboard keys and mouse buttons. Set
{ AllowMouseButtons = false }for a keyboard-only entry. - Slot 1 is saved under
prefKey, slots 2 and 3 underprefKey_2andprefKey_3. - Treat
KeyCode.Noneas "no hotkey":if (_toggleKey != KeyCode.None && Input.GetKeyDown(_toggleKey)).
ChoiceRow
A setting picked from a list. The row shows the current item; a click opens the list over the page.
new ChoiceRow("Difficulty", () => _diff, v => _diff = v, "Easy", "Normal", "Hard")
.Saved("Difficulty")
new ChoiceRow("Font", () => _font, v => _font = v, new List<Option>
{
new Option("goblin", "Goblin Menu", "Cyrillic letters in the menu style", "Font mods"),
new Option("roboto", "Roboto", "The game's plain font", "Game fonts"),
})
.Searchable() // search field (shown by itself from 10 items on)
.Filters("Font mods", "Game fonts") // filter buttons, matched against Option tags
.Description("Font for the main menu")
- The value is the item's key (
string), so adding, removing or reordering items never turns a saved choice into another one. - For a list that changes while the game runs, pass
() => CurrentOptions()instead of a fixed list. .Saved(key)keeps the choice inMelonPreferences.cfg;.Description(text)adds a line under the label that wraps if it is long.- Only the visible items are drawn, so long lists stay fast.
ButtonEntry
new ButtonEntry("Statistics", "RESET", () => _stats.Clear())
Runs onClick when pressed. It has no value, is not saved, and RESTORE DEFAULTS leaves it alone. An exception thrown by onClick is logged, not rethrown.
Panel state and events
public static bool PanelOpen { get; }
public static event Action PanelOpened;
public static event Action PanelClosed;
Check PanelOpen before handling your hotkeys, so keys pressed inside the panel don't trigger game actions:
if (!POGConfig.PanelOpen && Input.GetKeyDown(_toggleKey)) Toggle();
PanelClosed fires after any value still being typed has been applied. Use it for settings that are expensive to apply one change at a time:
POGConfig.PanelClosed += RebuildOverlay;
Saving
Entries with a prefKey load their saved value during Register and save on change.
| Entry | Saved as |
|---|---|
ToggleEntry |
bool |
SliderEntry |
float |
OptionsSliderEntry |
int (option index) |
KeyEntry |
string (key name) |
Changes are written to UserData/MelonPreferences.cfg half a second after the last change, when the panel closes, and when the game quits. Dragging a slider no longer writes the file every frame.
Only changes made through the panel are saved. If your mod changes a value itself (for example through a hotkey), the panel shows the new value but your mod is responsible for saving it.
Custom entry types
ConfigEntry's build and update hooks are internal, so other assemblies cannot add new entry types. If you need one, open an issue on GitHub.