add settings menu

- automation
- handler
This commit is contained in:
Mykhailo Budiakov
2025-07-28 06:32:58 +03:00
parent 54e18be421
commit 0bfc311224
5 changed files with 187 additions and 41 deletions
+8
View File
@@ -1296,3 +1296,11 @@ body:not(.no-theme) #interface:not(.theme-light) #action-bar .slot.full:hover {
.strike {
text-decoration: line-through;
}
.settings-menu {
footer {
position: absolute;
left: 10px;
bottom: 10px;
}
}
+15 -6
View File
@@ -387,18 +387,27 @@
"DG.Settings.charactersheet.program": "The Program",
"DG.Settings.sortskills.name": "Sort Skills By Column?",
"DG.Settings.sortskills.hint": "Checked sorts by column. Unchecked sorts by row.",
"DG.Settings.sanityprivate.name": "Keep Sanity Private",
"DG.Settings.sanityprivate.hint": "Hide sanity from players on both character sheet and rolls.",
"DG.Settings.keepSanityPrivate.name": "Keep Sanity Private",
"DG.Settings.keepSanityPrivate.hint": "Hide sanity from players on both character sheet and rolls.",
"DG.Settings.improvementroll.name": "Default Skill Improvement Roll",
"DG.Settings.improvementroll.hint": " Default 1d4. There have been multiple errata on this, choose which fits best for the pace of your game.",
"DG.Settings.improvementroll.1": "Flat +1",
"DG.Settings.improvementroll.2": "+1D3%",
"DG.Settings.improvementroll.3": "+1D4%",
"DG.Settings.improvementroll.4": "+1D4-1%",
"DG.Settings.hypergeometry.name": "Always Show Hypergeometry Section for Players",
"DG.Settings.hypergeometry.hint": "Always show Hypergeometry item section for players, even if they don't have any items of that type.",
"DG.Settings.landscapes.name": "Show Impossible Landscapes Content",
"DG.Settings.landscapes.hint": "Show Impossible Landscapes-specific fields from character sheets.",
"DG.Settings.alwaysShowHypergeometrySectionForPlayers.name": "Always Show Hypergeometry Section for Players",
"DG.Settings.alwaysShowHypergeometrySectionForPlayers.hint": "Always show Hypergeometry item section for players, even if they don't have any items of that type.",
"DG.Settings.showImpossibleLandscapesContent.name": "Show Impossible Landscapes Content",
"DG.Settings.showImpossibleLandscapesContent.hint": "Show Impossible Landscapes-specific fields from character sheets.",
"DG.Settings.automateSanity.name": "Show Impossible Landscapes-specific fields from character sheets.",
"DG.Settings.skillFailure.name": "Auto set skill failure",
"DG.Settings.skillFailure.hint": "",
"DG.SettingsMenu.automation.name": "Automation Menu",
"DG.SettingsMenu.automation.label": "Automation Menu",
"DG.SettingsMenu.handler.name": "Handler Settings",
"DG.SettingsMenu.handler.label": "Handler Settings",
"DG.Messages.Skillsmark.Marked": "This skill is marked",
"DG.Messages.Skillsmark.Tooltip": "See p. 29 Agent's Handbook"
+3 -1
View File
@@ -1,5 +1,6 @@
/* eslint-disable max-classes-per-file */
import DGUtils from "../other/utility-functions.js";
import DG from "../config.js";
const { renderTemplate } = foundry.applications.handlebars;
@@ -298,7 +299,8 @@ export class DGPercentileRoll extends DGRoll {
}
const failureMark = !this.isSuccess && this.skillPath
&& !foundry.utils.getProperty(this.actor, `${this.skillPath}.failure`);
&& !foundry.utils.getProperty(this.actor, `${this.skillPath}.failure`)
&& game.settings.get(DG.ID, "skillFailure");
const { renderTemplate } = foundry.applications.handlebars;
const html = await renderTemplate(
+136 -34
View File
@@ -1,6 +1,142 @@
import DG from "./config.js";
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
const SettingForm = class extends HandlebarsApplicationMixin(ApplicationV2) {
constructor() {
super();
}
static _namespace;
static get namespace() {
return this.constructor._namespace
};
static get settings() {
return {}
}
static init() {
const settings = this.settings;
for (const setting of Object.keys(settings)) {
game.settings.register(DG.ID, setting, {
scope: "world",
config: false,
name: game.i18n.localize(`DG.Settings.${setting}.name`),
hint: game.i18n.localize(`DG.Settings.${setting}.hint`),
...settings[setting],
});
}
}
static DEFAULT_OPTIONS = {
tag: "form",
id: `${DG.ID}-setting-form`,
classes: [DG.ID, "settings-menu"],
window: {title: ``, resizable: true},
position: {width: 500, height: 400},
actions: {},
form: {
handler: this.onSubmit,
submitOnChange: false,
closeOnSubmit: false
}
};
static PARTS = {
form: { template: `systems/${DG.ID}/templates/settings.hbs` },
}
static async onSubmit(event, form, formData) {
event.preventDefault();
const data = foundry.utils.expandObject(formData.object);
for (const key in data) {
game.settings.set(DG.ID, key, data[key]);
}
}
async _prepareContext(_options) {
let context = await super._prepareContext(_options);
context.settings = Object.entries(this.constructor.settings).reduce(function (obj, [key, setting]) {
obj[key] = {
...setting,
key,
name: `DG.Settings.${key}.name`,
hint: `DG.Settings.${key}.hint`,
value: game.settings.get(DG.ID, key),
isSelect: !!setting.choices,
isNumber: setting.type === Number,
isString: setting.type === String,
isCheckbox: setting.type === Boolean,
};
return obj;
}, {});
return context;
}
}
class AutomationSettings extends SettingForm {
static _namespace = "automation";
static get settings() {
return {
skillFailure: {
default: false,
type: Boolean,
}
};
}
}
class HandlerSettings extends SettingForm {
static _namespace = "handler";
static get settings() {
return {
alwaysShowHypergeometrySectionForPlayers: {
requiresReload: true,
type: Boolean,
default: false,
},
showImpossibleLandscapesContent: {
requiresReload: true,
type: Boolean,
default: true,
},
keepSanityPrivate: {
requiresReload: true,
type: Boolean,
default: false,
}
};
}
}
export default function registerSystemSettings() {
game.settings.registerMenu(DG.ID, "automation", {
name: game.i18n.localize(`DG.SettingsMenu.automation.name`),
label: game.i18n.localize(`DG.SettingsMenu.automation.label`),
hint: "",
icon: "fa-solid fa-dice",
type: AutomationSettings,
restricted: true
});
AutomationSettings.init();
game.settings.registerMenu(DG.ID, "handler", {
name: game.i18n.localize(`DG.SettingsMenu.handler.name`),
label: game.i18n.localize(`DG.SettingsMenu.handler.label`),
hint: "",
icon: "fa-solid fa-dice",
type: HandlerSettings,
restricted: true
});
HandlerSettings.init();
game.settings.register("deltagreen", "characterSheetStyle", {
name: game.i18n.localize("DG.Settings.charactersheet.name"),
hint: game.i18n.localize("DG.Settings.charactersheet.hint"),
@@ -31,16 +167,6 @@ export default function registerSystemSettings() {
default: false,
});
game.settings.register("deltagreen", "keepSanityPrivate", {
name: game.i18n.localize("DG.Settings.sanityprivate.name"),
hint: game.i18n.localize("DG.Settings.sanityprivate.hint"),
scope: "world",
config: true,
requiresReload: true,
type: Boolean,
default: false,
});
game.settings.register("deltagreen", "skillImprovementFormula", {
name: game.i18n.localize("DG.Settings.improvementroll.name"),
hint: game.i18n.localize("DG.Settings.improvementroll.hint"),
@@ -55,30 +181,6 @@ export default function registerSystemSettings() {
},
});
game.settings.register(
"deltagreen",
"alwaysShowHypergeometrySectionForPlayers",
{
name: game.i18n.localize("DG.Settings.hypergeometry.name"),
hint: game.i18n.localize("DG.Settings.hypergeometry.hint"),
scope: "world",
config: true,
requiresReload: true,
type: Boolean,
default: false,
},
);
game.settings.register("deltagreen", "showImpossibleLandscapesContent", {
name: game.i18n.localize("DG.Settings.landscapes.name"),
hint: game.i18n.localize("DG.Settings.landscapes.hint"),
scope: "world",
config: true,
requiresReload: true,
type: Boolean,
default: true,
});
// obsolete - will be removed at some point
game.settings.register("deltagreen", "characterSheetFont", {
name: "World Font Choice",
+25
View File
@@ -0,0 +1,25 @@
<section class="window-content standard-form">
{{#each settings as |setting|}}
<div class="form-group">
<label for="{{setting.key}}">{{localize setting.name}}</label>
{{#if setting.isSelect}}
<select name="{{setting.key}}">
{{selectOptions setting.choices selected=setting.value localize=true}}
</select>
{{else if setting.isCheckbox}}
<input type="checkbox" name="{{setting.key}}" {{checked setting.value}} />
{{else if setting.isNumber}}
<input type="number" name="{{setting.key}}" value="{{setting.value}}" data-dtype="{{setting.type}}" />
{{else if setting.isString}}
<input type="text" name="{{setting.key}}" value="{{setting.value}}" data-dtype="{{setting.type}}" />
{{/if}}
{{#if setting.hint}}
<p class="hint">{{localize setting.hint}}</p>
{{/if}}
</div>
{{/each}}
<footer class="form-footer">
<button type="submit"><i class="fa-solid fa-floppy-disk" inert=""></i> {{localize "SETTINGS.Save"}}</button>
</footer>
</section>