beezany
Trixie
this is more of a worked example than a tutorial, but i hope that it will illustrate the option configuration process. the end result is a set of game Options on their own Mods tab (along with any other mod that uses the same technique).
for illustration i'll use my Resource Re-sorts mod, which has two checkbox options and just a little code.
the first script is a variant of the ModSettings script that @leonardify created and several modders have been using to save config options. it stores the data in the game's persistent localStorage which requires cooperation between modders. this version adds a bit of code to create the new Mods tab on the Options screen. this script requires no modification, just drop it into your project.
if you are already using @leonardify's technique, all you need to do is add this snippet to your code and set your mod category to
otherwise, you'll need to edit the other script to configure your options. i've linked to the version in Resource Re-sorts, which is of course tailored to that mod. you'll need to change everything with a
which turns
once you set up the two scripts and update your modinfo, you should be able to see your options on both the main menu and in-game Options screens. you can refresh the in-game options using the debug console, but you have to restart the game to refresh the main menu.
for illustration i'll use my Resource Re-sorts mod, which has two checkbox options and just a little code.
option configuration scripts
first you'll need to add two scripts to your mod:the first script is a variant of the ModSettings script that @leonardify created and several modders have been using to save config options. it stores the data in the game's persistent localStorage which requires cooperation between modders. this version adds a bit of code to create the new Mods tab on the Options screen. this script requires no modification, just drop it into your project.
if you are already using @leonardify's technique, all you need to do is add this snippet to your code and set your mod category to
CategoryType.Mods
:
JavaScript:
import { CategoryData, CategoryType } from '/core/ui/options/options-helpers.js';
CategoryType["Mods"] = "mods";
CategoryData[CategoryType.Mods] = {
title: "LOC_UI_CONTENT_MGR_SUBTITLE",
description: "LOC_UI_CONTENT_MGR_SUBTITLE_DESCRIPTION",
};
otherwise, you'll need to edit the other script to configure your options. i've linked to the version in Resource Re-sorts, which is of course tailored to that mod. you'll need to change everything with a
bz
or BZ
prefix, including the filename, because those things are specific to my mods. here's some of the specific steps:- change
MOD_ID = "bz-re-sorts"
to your ownmod-id
- rename
bzReSortsOptions
to suit your mod - model your config options in the
data
object and update the various accessors & event callbacks to match them - change
group: 'bz_mods'
to something based on your name or yourmod-id
. use underscores here, not hyphens. - check for anything still containing
bz
orBZ
because those are all specific to my mod
group: name
requires some explanation. the Option processor translates that into a locale tag "LOC_OPTIONS_GROUP_" + uppercase(group)
used as a section title for your options. easiest thing to do here is set group to your mod-id with hyphens changed to underscores:
JavaScript:
group: MOD_ID.replace(/-/g, '_');
my-mod
into LOC_OPTIONS_GROUP_MY_MOD
. my example mod uses a different value because i group all of my mods' options into a single section.other option types
the game'sOptions
API supports several kinds of options:- Checkbox and Switch for boolean options
- Slider and Stepper for numeric ranges
- Dropdown for menu options
- Editor for text
OptionType.Checkbox
so i can't provide specific guidance on the others yet.modinfo
you'll need to add these to your modinfo in two places. for in-game options, add them to the same action group as the rest of your scripts. for the main menu, you'll also need to create ashell
action group:
Code:
<ActionGroup id="MOD-ID-menu" scope="shell" criteria="always">
<Properties>
<LoadOrder>100</LoadOrder>
</Properties>
<Actions>
<UIScripts>
<Item>ui/options/MOD-ID-options.js</Item>
<Item>ui/options/mod-options-decorator.js</Item>
</UIScripts>
<UpdateText>
<Item>text/en_us/InGameText.xml</Item>
</UpdateText>
</Actions>
</ActionGroup>
once you set up the two scripts and update your modinfo, you should be able to see your options on both the main menu and in-game Options screens. you can refresh the in-game options using the debug console, but you have to restart the game to refresh the main menu.
using the options
after that, all that's left is to hook up your options in your main scripts. import your settings object and use the properties you declared in the configuration script above. for example:
JavaScript:
import bzReSortsOptions from '/bz-re-sorts/ui/options/bz-re-sorts-options.js';
const settlementSort = (a, b) => {
if (bzReSortsOptions.sortCitiesByType) {
// first sort capital, city, town
// ...
}
if (bzReSortsOptions.sortCitiesBySlots) {
// then sort by total resource slots
// ...
}
// then sort by name ...
};
ui/options/mod-options-decorator.js
for reference, here is the entiremod-options-decorator.js
script (no editing required):
JavaScript:
import { CategoryData, CategoryType } from '/core/ui/options/options-helpers.js';
CategoryType["Mods"] = "mods";
CategoryData[CategoryType.Mods] = {
title: "LOC_UI_CONTENT_MGR_SUBTITLE",
description: "LOC_UI_CONTENT_MGR_SUBTITLE_DESCRIPTION",
};
// fix Options tab spacing
const MOD_OPTIONS_STYLE = document.createElement('style');
MOD_OPTIONS_STYLE.textContent = `
.option-frame .tab-bar__items .flex-auto {
flex: 1 0 auto;
min-width: 0rem;
margin-left: 0.4444444444rem;
margin-right: 0.4444444444rem;
}`;
document.head.appendChild(MOD_OPTIONS_STYLE);
// Please, always use ModSettings to save and load settings in your mod.
// Right now if you try to use **multiple** keys in localStorage, it
// will break reading from localStorage for **every mod**. This is
// a workaround to avoid this issue, while keeping a namespace to give
// each mod its own settings.
export class ModSettingsSingleton {
save(modID, data) {
if (localStorage.length > 1) {
console.warn(`ModSettings: erasing storage (${localStorage.length} items)`);
localStorage.clear();
}
const modSettings = JSON.parse(localStorage.getItem("modSettings") || '{}');
modSettings[modID] = data;
localStorage.setItem("modSettings", JSON.stringify(modSettings));
console.warn(`SAVE ${modID}=${JSON.stringify(data)}`);
}
load(modID) {
try {
const modSettings = localStorage.getItem("modSettings");
if (!modSettings) return null;
const data = modSettings && (JSON.parse(modSettings)[modID] ?? null);
console.warn(`LOAD ${modID}=${JSON.stringify(data)}`);
return data;
}
catch (e) {
console.error(`ModSettings: error loading settings`);
console.error(`${modID}: ${e}`);
}
return null;
}
}
const ModSettings = new ModSettingsSingleton();
export { ModSettings as default };
Last edited: