Updated SystemSettings to V2 and organized some

This commit is contained in:
WBHarry 2025-06-15 16:52:13 +02:00
parent f80a849b73
commit 3cfa1d19c9
31 changed files with 584 additions and 460 deletions

View file

@ -106,7 +106,7 @@ Hooks.once('init', () => {
Hooks.on('ready', () => {
ui.resources = new CONFIG.ui.resources();
if (game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.DisplayFear) !== 'hide')
if (game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance).displayFear !== 'hide')
ui.resources.render({ force: true });
document.body.classList.toggle(
'theme-colorful',

View file

@ -24,10 +24,7 @@
"Automation": {
"Name": "Automation Settings",
"Label": "Configure Automation",
"Hint": "Various settings automating resource management and more",
"HopeLabel": "Hope",
"FearLabel": "Fear",
"ActionPointsLabel": "Action Points"
"Hint": "Various settings automating resource management and more"
},
"Homebrew": {
"Name": "Homebrew Settings",
@ -38,13 +35,7 @@
"Range": {
"Name": "Range Settings",
"Label": "Configure Range Handling",
"Hint": "System ruler setup for displaying ranges in Daggerheart",
"EnabledLabel": "Enabled",
"MeleeLabel": "Melee",
"VeryCloseLabel": "Very Close",
"CloseLabel": "Close",
"FarLabel": "Far",
"VeryFarLabel": "Very Far"
"Hint": "System ruler setup for displaying ranges in Daggerheart"
},
"Appearance": {
"title": "Appearance Settings",
@ -69,18 +60,36 @@
"actionTokens": "Action Tokens"
}
},
"Automation": {
"Hope": {
"Name": "Hope",
"Hint": "Automatically increase a character's hope on a hope duality roll result."
"Appearance": {
"FIELDS": {
"displayFear": { "label": "Fear Display" }
},
"FearDisplay": {
"Token": "Tokens",
"Bar": "Bar",
"Hide": "Hide"
}
},
"Automation": {
"Fear": {
"Name": "Fear",
"Hint": "Automatically increase the GM's fear pool on a fear duality roll result."
},
"ActionPoints": {
"Name": "Action Points",
"Hint": "Automatically give and take Action Points as combatants take their turns."
"FIELDS": {
"hope": {
"label": "Hope",
"hint": "Automatically increase a character's hope on a hope duality roll result."
},
"actionPoints": {
"label": "Action Points",
"hint": "Automatically give and take Action Points as combatants take their turns."
}
}
},
"Homebrew": {
"FIELDS": {
"maxFear": { "label": "Max Fear" },
"traitArray": { "label": "Initial Trait Modifiers" }
}
},
"Resources": {
@ -113,6 +122,10 @@
"hint": "Give each player action tokens to use in combat"
},
"FIELDS": {
"actionTokens": {
"enabled": { "label": "Enabled" },
"tokens": { "label": "Tokens" }
},
"useCoins": {
"label": "Use Coins",
"hint": "test"
@ -163,7 +176,9 @@
"OK": "OK",
"Cancel": "Cancel",
"Or": "Or",
"Enabled": "Enabled",
"Description": "Description",
"Modifier": "Modifier",
"Features": "Features",
"proficiency": "Proficiency",
"unarmored": "Unarmored",

View file

@ -32,7 +32,7 @@ export default class Resources extends HandlebarsApplicationMixin(ApplicationV2)
position: {
width: 222,
height: 222
// top: "200px",
// top: "200px",s
// left: "120px"
}
};
@ -50,7 +50,7 @@ export default class Resources extends HandlebarsApplicationMixin(ApplicationV2)
}
get maxFear() {
return game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.MaxFear);
return game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Homebrew).maxFear;
}
/* -------------------------------------------- */
@ -59,7 +59,7 @@ export default class Resources extends HandlebarsApplicationMixin(ApplicationV2)
/** @override */
async _prepareContext(_options) {
const display = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.DisplayFear),
const display = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance).displayFear,
current = this.currentFear,
max = this.maxFear,
percent = (current / max) * 100,

View file

@ -1,178 +1,121 @@
import { DualityRollColor } from '../config/settingsConfig.mjs';
import { defaultLevelTiers, DhLevelTiers } from '../data/levelTier.mjs';
import DhAppearance from '../data/settings/Appearance.mjs';
import DHAppearanceSettings from './settings/appearanceSettings.mjs';
import DhVariantRules from '../data/settings/VariantRules.mjs';
import DHVariantRuleSettings from './settings/variantRuleSettings.mjs';
class DhpAutomationSettings extends FormApplication {
constructor(object = {}, options = {}) {
super(object, options);
}
static get defaultOptions() {
const defaults = super.defaultOptions;
const overrides = {
height: 'auto',
width: 400,
id: 'daggerheart-automation-settings',
template: 'systems/daggerheart/templates/views/automation-settings.hbs',
closeOnSubmit: true,
submitOnChange: false,
classes: ['daggerheart', 'views', 'settings']
};
const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
return mergedOptions;
}
async getData() {
const context = super.getData();
context.settings = SYSTEM.SETTINGS.gameSettings.Automation;
context.hope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope);
context.actionPoints = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.ActionPoints);
return context;
}
activateListeners(html) {
super.activateListeners(html);
}
async _updateObject(_, formData) {
const data = foundry.utils.expandObject(formData);
const updateSettingsKeys = Object.keys(data);
for (var i = 0; i < updateSettingsKeys.length; i++) {
await game.settings.set(SYSTEM.id, updateSettingsKeys[i], data[updateSettingsKeys[i]]);
}
}
}
class DhpHomebrewSettings extends FormApplication {
constructor(object = {}, options = {}) {
super(object, options);
}
static get defaultOptions() {
const defaults = super.defaultOptions;
const overrides = {
height: 'auto',
width: 400,
id: 'daggerheart-homebrew-settings',
template: 'systems/daggerheart/templates/views/homebrew-settings.hbs',
closeOnSubmit: true,
submitOnChange: false,
classes: ['daggerheart', 'views', 'settings']
};
const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
return mergedOptions;
}
async getData() {
const context = super.getData();
context.settings = SYSTEM.SETTINGS.gameSettings.General;
context.abilityArray = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.AbilityArray);
return context;
}
activateListeners(html) {
super.activateListeners(html);
}
async _updateObject(_, formData) {
const data = foundry.utils.expandObject(formData);
const updateSettingsKeys = Object.keys(data);
for (var i = 0; i < updateSettingsKeys.length; i++) {
await game.settings.set(SYSTEM.id, updateSettingsKeys[i], data[updateSettingsKeys[i]]);
}
}
}
class DhpRangeSettings extends FormApplication {
constructor(object = {}, options = {}) {
super(object, options);
this.range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement);
}
static get defaultOptions() {
const defaults = super.defaultOptions;
const overrides = {
height: 'auto',
width: 400,
id: 'daggerheart-range-settings',
template: 'systems/daggerheart/templates/views/range-settings.hbs',
closeOnSubmit: false,
submitOnChange: true,
classes: ['daggerheart', 'views', 'settings']
};
const mergedOptions = foundry.utils.mergeObject(defaults, overrides);
return mergedOptions;
}
async getData() {
const context = super.getData();
context.settings = SYSTEM.SETTINGS.gameSettings.General;
context.range = this.range;
context.disabled =
context.range.enabled &&
[
context.range.melee,
context.range.veryClose,
context.range.close,
context.range.far,
context.range.veryFar
].some(x => x === null || x === false);
return context;
}
activateListeners(html) {
super.activateListeners(html);
html.find('.range-reset').click(this.reset.bind(this));
html.find('.save').click(this.save.bind(this));
html.find('.close').click(this.close.bind(this));
}
async _updateObject(_, formData) {
const data = foundry.utils.expandObject(formData, { disabled: true });
this.range = foundry.utils.mergeObject(this.range, data);
this.render(true);
}
reset() {
this.range = {
enabled: false,
melee: 5,
veryClose: 15,
close: 30,
far: 60,
veryFar: 120
};
this.render(true);
}
async save() {
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement, this.range);
this.close();
}
}
import {
DhAppearance,
DhAutomation,
DhHomebrew,
DhRangeMeasurement,
DhVariantRules
} from '../data/settings/_module.mjs';
import {
DhAppearanceSettings,
DhAutomationSettings,
DhHomebrewSettings,
DhRangeMeasurementSettings,
DhVariantRuleSettings
} from './settings/_module.mjs';
export const registerDHSettings = () => {
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.AbilityArray, {
name: game.i18n.localize('DAGGERHEART.Settings.General.AbilityArray.Name'),
hint: game.i18n.localize('DAGGERHEART.Settings.General.AbilityArray.Hint'),
registerMenuSettings();
registerMenus();
registerNonConfigSettings();
};
const registerMenuSettings = () => {
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.variantRules, {
scope: 'world',
config: false,
type: String,
default: '[2,1,1,0,0,-1]'
type: DhVariantRules
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation, {
scope: 'world',
config: false,
type: DhAutomation
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Homebrew, {
scope: 'world',
config: false,
type: DhHomebrew,
onChange: value => {
if (value.maxFear) {
if (ui.resources) ui.resources.render({ force: true });
}
}
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance, {
scope: 'client',
config: false,
type: DhAppearance,
onChange: value => {
if (value.displayFear) {
if (ui.resources) {
if (value.displayFear === 'hide') ui.resources.close({ allowed: true });
else ui.resources.render({ force: true });
}
}
}
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement, {
scope: 'client',
config: false,
type: DhRangeMeasurement
});
};
const registerMenus = () => {
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Automation.Name, {
name: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Name'),
label: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Label'),
hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Hint'),
icon: SYSTEM.SETTINGS.menu.Automation.Icon,
type: DhAutomationSettings,
restricted: true
});
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Homebrew.Name, {
name: game.i18n.localize('DAGGERHEART.Settings.Menu.Homebrew.Name'),
label: game.i18n.localize('DAGGERHEART.Settings.Menu.Homebrew.Label'),
hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Homebrew.Hint'),
icon: SYSTEM.SETTINGS.menu.Homebrew.Icon,
type: DhHomebrewSettings,
restricted: true
});
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Range.Name, {
name: game.i18n.localize('DAGGERHEART.Settings.Menu.Range.Name'),
label: game.i18n.localize('DAGGERHEART.Settings.Menu.Range.Label'),
hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Range.Hint'),
icon: SYSTEM.SETTINGS.menu.Range.Icon,
type: DhRangeMeasurementSettings,
restricted: true
});
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance, {
name: game.i18n.localize('DAGGERHEART.Settings.Menu.Appearance.title'),
label: game.i18n.localize('DAGGERHEART.Settings.Menu.Appearance.label'),
hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Appearance.hint'),
icon: 'fa-solid fa-palette',
type: DhAppearanceSettings,
restricted: false
});
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.VariantRules.Name, {
name: game.i18n.localize('DAGGERHEART.Settings.Menu.VariantRules.title'),
label: game.i18n.localize('DAGGERHEART.Settings.Menu.VariantRules.label'),
hint: game.i18n.localize('DAGGERHEART.Settings.Menu.VariantRules.hint'),
icon: SYSTEM.SETTINGS.menu.VariantRules.Icon,
type: DhVariantRuleSettings,
restricted: false
});
};
const registerNonConfigSettings = () => {
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.LevelTiers, {
scope: 'world',
config: false,
type: DhLevelTiers,
default: defaultLevelTiers
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear, {
@ -187,144 +130,4 @@ export const registerDHSettings = () => {
ui.combat.render({ force: true });
}
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.MaxFear, {
name: game.i18n.localize('DAGGERHEART.Settings.Resources.MaxFear.Name'),
hint: game.i18n.localize('DAGGERHEART.Settings.Resources.MaxFear.Hint'),
scope: 'world',
config: true,
type: Number,
default: 12,
onChange: () => {
if (ui.resources) ui.resources.render({ force: true });
}
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.DisplayFear, {
name: game.i18n.localize('DAGGERHEART.Settings.Resources.DisplayFear.Name'),
hint: game.i18n.localize('DAGGERHEART.Settings.Resources.DisplayFear.Hint'),
scope: 'client',
config: true,
type: String,
choices: {
token: 'Tokens',
bar: 'Bar',
hide: 'Hide'
},
default: 'token',
onChange: value => {
if (ui.resources) {
if (value === 'hide') ui.resources.close({ allowed: true });
else ui.resources.render({ force: true });
}
}
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope, {
name: game.i18n.localize('DAGGERHEART.Settings.Automation.Hope.Name'),
hint: game.i18n.localize('DAGGERHEART.Settings.Automation.Hope.Hint'),
scope: 'world',
config: false,
type: Boolean,
default: false
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.ActionPoints, {
name: game.i18n.localize('DAGGERHEART.Settings.Automation.ActionPoints.Name'),
hint: game.i18n.localize('DAGGERHEART.Settings.Automation.ActionPoints.Hint'),
scope: 'world',
config: false,
type: Boolean,
default: true
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement, {
name: game.i18n.localize('DAGGERHEART.Settings.General.RangeMeasurement.Name'),
hint: game.i18n.localize('DAGGERHEART.Settings.General.RangeMeasurement.Hint'),
scope: 'world',
config: false,
type: Object,
default: {
enabled: true,
melee: 5,
veryClose: 15,
close: 30,
far: 60,
veryFar: 120
}
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.variantRules, {
scope: 'world',
config: false,
type: DhVariantRules,
default: DhVariantRules.defaultSchema
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance, {
scope: 'client',
config: false,
type: DhAppearance,
default: DhAppearance.defaultSchema
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.DualityRollColor, {
name: game.i18n.localize('DAGGERHEART.Settings.DualityRollColor.Name'),
hint: game.i18n.localize('DAGGERHEART.Settings.DualityRollColor.Hint'),
scope: 'world',
config: false,
type: Number,
choices: Object.values(DualityRollColor),
default: DualityRollColor.colorful.value
});
game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.LevelTiers, {
scope: 'world',
config: false,
type: DhLevelTiers,
default: defaultLevelTiers
});
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Automation.Name, {
name: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Name'),
label: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Label'),
hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Hint'),
icon: SYSTEM.SETTINGS.menu.Automation.Icon,
type: DhpAutomationSettings,
restricted: true
});
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Homebrew.Name, {
name: game.i18n.localize('DAGGERHEART.Settings.Menu.Homebrew.Name'),
label: game.i18n.localize('DAGGERHEART.Settings.Menu.Homebrew.Label'),
hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Homebrew.Hint'),
icon: SYSTEM.SETTINGS.menu.Homebrew.Icon,
type: DhpHomebrewSettings,
restricted: true
});
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Range.Name, {
name: game.i18n.localize('DAGGERHEART.Settings.Menu.Range.Name'),
label: game.i18n.localize('DAGGERHEART.Settings.Menu.Range.Label'),
hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Range.Hint'),
icon: SYSTEM.SETTINGS.menu.Range.Icon,
type: DhpRangeSettings,
restricted: true
});
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance, {
name: game.i18n.localize('DAGGERHEART.Settings.Menu.Appearance.title'),
label: game.i18n.localize('DAGGERHEART.Settings.Menu.Appearance.label'),
hint: game.i18n.localize('DAGGERHEART.Settings.Menu.Appearance.hint'),
icon: 'fa-solid fa-palette',
type: DHAppearanceSettings,
restricted: false
});
game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.VariantRules.Name, {
name: game.i18n.localize('DAGGERHEART.Settings.Menu.VariantRules.title'),
label: game.i18n.localize('DAGGERHEART.Settings.Menu.VariantRules.label'),
hint: game.i18n.localize('DAGGERHEART.Settings.Menu.VariantRules.hint'),
icon: SYSTEM.SETTINGS.menu.VariantRules.Icon,
type: DHVariantRuleSettings,
restricted: false
});
};

View file

@ -0,0 +1,13 @@
import DhAppearanceSettings from './appearanceSettings.mjs';
import DhAutomationSettings from './automationSettings.mjs';
import DhHomebrewSettings from './homebrewSettings.mjs';
import DhRangeMeasurementSettings from './rangeMeasurementSettings.mjs';
import DhVariantRuleSettings from './variantRuleSettings.mjs';
export {
DhAppearanceSettings,
DhAutomationSettings,
DhHomebrewSettings,
DhRangeMeasurementSettings,
DhVariantRuleSettings
};

View file

@ -54,20 +54,11 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
static async save() {
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance, this.settings.toObject());
/* const reload = await foundry.applications.api.DialogV2.confirm({
id: 'reload-world-confirm',
modal: true,
rejectClose: false,
window: { title: 'SETTINGS.ReloadPromptTitle' },
position: { width: 400 },
content: `<p>${game.i18n.localize('SETTINGS.ReloadPromptBody')}</p>`
});
if (reload) {
await game.socket.emit('reload');
foundry.utils.debouncedReload();
} */
document.body.classList.toggle('theme-colorful', game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance).dualityColorScheme === DualityRollColor.colorful.value);
document.body.classList.toggle(
'theme-colorful',
game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance).dualityColorScheme ===
DualityRollColor.colorful.value
);
this.close();
}

View file

@ -0,0 +1,59 @@
import { DhAutomation } from '../../data/settings/_module.mjs';
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
export default class DhAutomationSettings extends HandlebarsApplicationMixin(ApplicationV2) {
constructor() {
super({});
this.settings = new DhAutomation(
game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation).toObject()
);
}
get title() {
return game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Name');
}
static DEFAULT_OPTIONS = {
tag: 'form',
id: 'daggerheart-automation-settings',
classes: ['daggerheart', 'setting', 'dh-style'],
position: { width: '600', height: 'auto' },
actions: {
reset: this.reset,
save: this.save
},
form: { handler: this.updateData, submitOnChange: true }
};
static PARTS = {
main: {
template: 'systems/daggerheart/templates/settings/automation-settings.hbs'
}
};
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
context.settingFields = this.settings;
return context;
}
static async updateData(event, element, formData) {
const updatedSettings = foundry.utils.expandObject(formData.object);
await this.settings.updateSource(updatedSettings);
this.render();
}
static async reset() {
this.settings = new DhAutomation();
this.render();
}
static async save() {
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation, this.settings.toObject());
this.close();
}
}

View file

@ -0,0 +1,60 @@
import { DhHomebrew } from '../../data/settings/_module.mjs';
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
export default class DhAutomationSettings extends HandlebarsApplicationMixin(ApplicationV2) {
constructor() {
super({});
this.settings = new DhHomebrew(game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Homebrew).toObject());
}
get title() {
return game.i18n.localize('DAGGERHEART.Settings.Menu.Homebrew.Name');
}
static DEFAULT_OPTIONS = {
tag: 'form',
id: 'daggerheart-homebrew-settings',
classes: ['daggerheart', 'setting', 'dh-style'],
position: { width: '600', height: 'auto' },
actions: {
reset: this.reset,
save: this.save
},
form: { handler: this.updateData, submitOnChange: true }
};
static PARTS = {
main: {
template: 'systems/daggerheart/templates/settings/homebrew-settings.hbs'
}
};
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
context.settingFields = this.settings;
return context;
}
static async updateData(event, element, formData) {
const updatedSettings = foundry.utils.expandObject(formData.object);
await this.settings.updateSource({
...updatedSettings,
traitArray: Object.values(updatedSettings.traitArray)
});
this.render();
}
static async reset() {
this.settings = new DhHomebrew();
this.render();
}
static async save() {
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Homebrew, this.settings.toObject());
this.close();
}
}

View file

@ -0,0 +1,59 @@
import { DhRangeMeasurement } from '../../data/settings/_module.mjs';
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
export default class DhRangeMeasurementSettings extends HandlebarsApplicationMixin(ApplicationV2) {
constructor() {
super({});
this.settings = new DhRangeMeasurement(
game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement).toObject()
);
}
get title() {
return game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Name');
}
static DEFAULT_OPTIONS = {
tag: 'form',
id: 'daggerheart-automation-settings',
classes: ['daggerheart', 'setting', 'dh-style'],
position: { width: '600', height: 'auto' },
actions: {
reset: this.reset,
save: this.save
},
form: { handler: this.updateData, submitOnChange: true }
};
static PARTS = {
main: {
template: 'systems/daggerheart/templates/settings/range-measurement-settings.hbs'
}
};
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
context.settingFields = this.settings;
return context;
}
static async updateData(event, element, formData) {
const updatedSettings = foundry.utils.expandObject(formData.object);
await this.settings.updateSource(updatedSettings);
this.render();
}
static async reset() {
this.settings = new DhRangeMeasurement();
this.render();
}
static async save() {
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement, this.settings.toObject());
this.close();
}
}

View file

@ -165,18 +165,18 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
context.config = SYSTEM;
const selectedAttributes = Object.values(this.document.system.traits).map(x => x.base);
context.abilityScoreArray = JSON.parse(
await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.AbilityArray)
).reduce((acc, x) => {
const selectedIndex = selectedAttributes.indexOf(x);
if (selectedIndex !== -1) {
selectedAttributes.splice(selectedIndex, 1);
} else {
acc.push({ name: x, value: x });
}
context.abilityScoreArray = await game.settings
.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Homebrew)
.traitArray.reduce((acc, x) => {
const selectedIndex = selectedAttributes.indexOf(x);
if (selectedIndex !== -1) {
selectedAttributes.splice(selectedIndex, 1);
} else {
acc.push({ name: x, value: x });
}
return acc;
}, []);
return acc;
}, []);
if (!context.abilityScoreArray.includes(0)) context.abilityScoreArray.push({ name: 0, value: 0 });
context.abilityScoresFinished = context.abilityScoreArray.every(x => x.value === 0);

View file

@ -337,3 +337,9 @@ export const rollTypes = {
label: 'DAGGERHEART.RollTypes.ability.name'
}
};
export const fearDisplay = {
token: { value: 'token', label: 'DAGGERHEART.Settings.Appearance.FearDisplay.Token' },
bar: { value: 'bar', label: 'DAGGERHEART.Settings.Appearance.FearDisplay.Bar' },
hide: { value: 'hide', label: 'DAGGERHEART.Settings.Appearance.FearDisplay.Hide' }
};

View file

@ -18,23 +18,15 @@ export const menu = {
};
export const gameSettings = {
Automation: {
Hope: 'AutomationHope',
ActionPoints: 'AutomationActionPoints'
},
Resources: {
Fear: 'ResourcesFear',
MaxFear: 'ResourcesMaxFear',
DisplayFear: 'DisplayFear'
},
General: {
AbilityArray: 'AbilityArray',
RangeMeasurement: 'RangeMeasurement'
},
DualityRollColor: 'DualityRollColor',
LevelTiers: 'LevelTiers',
Automation: 'Automation',
Homebrew: 'Homebrew',
RangeMeasurement: 'RangeMeasurement',
appearance: 'Appearance',
variantRules: 'VariantRules'
variantRules: 'VariantRules',
Resources: {
Fear: 'ResourcesFear'
},
LevelTiers: 'LevelTiers'
};
export const DualityRollColor = {

View file

@ -1,7 +1,15 @@
import { fearDisplay } from '../../config/generalConfig.mjs';
export default class DhAppearance extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
displayFear: new fields.StringField({
required: true,
choices: fearDisplay,
initial: fearDisplay.token.value,
label: 'DAGGERHEART.Settings.Appearance.FIELDS.displayFear.label'
}),
dualityColorScheme: new fields.StringField({
required: true,
choices: DualityRollColor,
@ -35,8 +43,6 @@ export default class DhAppearance extends foundry.abstract.DataModel {
})
};
}
static defaultSchema = {};
}
export const DualityRollColor = {

View file

@ -0,0 +1,11 @@
export default class DhAutomation extends foundry.abstract.DataModel {
static LOCALIZATION_PREFIXES = ['DAGGERHEART.Settings.Automation']; // Doesn't work for some reason
static defineSchema() {
const fields = foundry.data.fields;
return {
hope: new fields.BooleanField({ required: true, initial: false }),
actionPoints: new fields.BooleanField({ required: true, initial: false })
};
}
}

View file

@ -0,0 +1,19 @@
export default class DhHomebrew extends foundry.abstract.DataModel {
static LOCALIZATION_PREFIXES = ['DAGGERHEART.Settings.Homebrew']; // Doesn't work for some reason
static defineSchema() {
const fields = foundry.data.fields;
return {
maxFear: new fields.NumberField({
required: true,
integer: true,
min: 0,
initial: 12,
label: 'DAGGERHEART.Settings.Homebrew.FIELDS.maxFear.label'
}),
traitArray: new fields.ArrayField(new fields.NumberField({ required: true, integer: true }), {
initial: () => [2, 1, 1, 0, 0, -1]
})
};
}
}

View file

@ -0,0 +1,17 @@
export default class DhRangeMeasurement extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
enabled: new fields.BooleanField({ required: true, initial: false, label: 'DAGGERHEART.General.Enabled' }),
melee: new fields.NumberField({ required: true, initial: 5, label: 'DAGGERHEART.Range.melee.name' }),
veryClose: new fields.NumberField({
required: true,
initial: 15,
label: 'DAGGERHEART.Range.veryClose.name'
}),
close: new fields.NumberField({ required: true, initial: 30, label: 'DAGGERHEART.Range.close.name' }),
far: new fields.NumberField({ required: true, initial: 60, label: 'DAGGERHEART.Range.far.name' }),
veryFar: new fields.NumberField({ required: true, initial: 120, label: 'DAGGERHEART.Range.veryFar.name' })
};
}
}

View file

@ -5,12 +5,22 @@ export default class DhVariantRules extends foundry.abstract.DataModel {
const fields = foundry.data.fields;
return {
actionTokens: new fields.SchemaField({
enabled: new fields.BooleanField({ required: true, initial: false }),
tokens: new fields.NumberField({ required: true, integer: true, initial: 3 })
enabled: new fields.BooleanField({
required: true,
initial: false,
label: 'DAGGERHEART.Settings.VariantRules.FIELDS.actionTokens.enabled.label'
}),
tokens: new fields.NumberField({
required: true,
integer: true,
initial: 3,
label: 'DAGGERHEART.Settings.VariantRules.FIELDS.actionTokens.tokens.label'
})
}),
useCoins: new fields.BooleanField({ initial: false })
useCoins: new fields.BooleanField({
initial: false,
label: 'DAGGERHEART.Settings.VariantRules.FIELDS.useCoins.label'
})
};
}
static defaultSchema = {};
}

View file

@ -0,0 +1,7 @@
import DhAppearance from './Appearance.mjs';
import DhAutomation from './Automation.mjs';
import DhHomebrew from './Homebrew.mjs';
import DhRangeMeasurement from './RangeMeasurement.mjs';
import DhVariantRules from './VariantRules.mjs';
export { DhAppearance, DhAutomation, DhHomebrew, DhRangeMeasurement, DhVariantRules };

View file

@ -3,7 +3,7 @@ export default class DhpRuler extends foundry.canvas.interaction.Ruler {
const context = super._getWaypointLabelContext(waypoint, state);
if (!context) return;
const range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement);
const range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement);
if (range.enabled) {
const distance = this.#getRangeLabel(waypoint.measurement.distance.toNearest(0.01), range);

View file

@ -3,7 +3,7 @@ export default class DhpTokenRuler extends foundry.canvas.placeables.tokens.Toke
const context = super._getWaypointLabelContext(waypoint, state);
if (!context) return;
const range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.General.RangeMeasurement);
const range = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.RangeMeasurement);
if (range.enabled) {
const distance = this.#getRangeLabel(waypoint.measurement.distance.toNearest(0.01), range);

View file

@ -2816,6 +2816,31 @@ div.daggerheart.views.multiclass {
#resources:has(.fear-bar) {
min-width: 200px;
}
.daggerheart.dh-style.setting .settings-col {
display: flex;
flex-direction: column;
gap: 4px;
}
.daggerheart.dh-style.setting .trait-array-container {
display: flex;
justify-content: space-evenly;
gap: 8px;
margin-bottom: 16px;
}
.daggerheart.dh-style.setting .trait-array-container .trait-array-item {
position: relative;
display: flex;
justify-content: center;
}
.daggerheart.dh-style.setting .trait-array-container .trait-array-item label {
position: absolute;
top: -7px;
font-size: 12px;
font-variant: petite-caps;
}
.daggerheart.dh-style.setting .trait-array-container .trait-array-item input {
text-align: center;
}
.application.sheet.daggerheart.actor.dh-style.adversary .window-content {
overflow: auto;
}

View file

@ -11,6 +11,7 @@
@import './levelup.less';
@import '../node_modules/@yaireo/tagify/dist/tagify.css';
@import './resources.less';
@import './settings.less';
// new styles imports
@import './less/actors/character.less';

31
styles/settings.less Normal file
View file

@ -0,0 +1,31 @@
.daggerheart.dh-style.setting {
.settings-col {
display: flex;
flex-direction: column;
gap: 4px;
}
.trait-array-container {
display: flex;
justify-content: space-evenly;
gap: 8px;
margin-bottom: 16px;
.trait-array-item {
position: relative;
display: flex;
justify-content: center;
label {
position: absolute;
top: -7px;
font-size: 12px;
font-variant: petite-caps;
}
input {
text-align: center;
}
}
}
}

View file

@ -1,4 +1,6 @@
<div>
{{formGroup settingFields.schema.fields.displayFear value=settingFields._source.displayFear localize=true}}
<fieldset>
<legend>{{localize "DAGGERHEART.Settings.Menu.Appearance.duality"}}</legend>

View file

@ -0,0 +1,26 @@
<div>
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Automation.FIELDS.hope.label"}}</label>
<div class="form-fields">
{{formInput settingFields.schema.fields.hope value=settingFields._source.hope }}
</div>
</div>
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Automation.FIELDS.actionPoints.label"}}</label>
<div class="form-fields">
{{formInput settingFields.schema.fields.actionPoints value=settingFields._source.actionPoints }}
</div>
</div>
<footer class="form-footer">
<button data-action="reset">
<i class="fa-solid fa-arrow-rotate-left"></i>
<span>{{localize "Reset"}}</span>
</button>
<button data-action="save" >
<i class="fa-solid fa-floppy-disk"></i>
<span>{{localize "Save Changes"}}</span>
</button>
</footer>
</div>

View file

@ -0,0 +1,25 @@
<div>
{{formGroup settingFields.schema.fields.maxFear value=settingFields._source.maxFear localize=true}}
<h4>{{localize "DAGGERHEART.Settings.Homebrew.FIELDS.traitArray.label"}}</h4>
<div class="trait-array-container">
{{#each settingFields._source.traitArray as |trait index|}}
<div class="trait-array-item">
<label>{{localize "DAGGERHEART.General.Modifier"}} {{add index 1}}</label>
<input type="text" data-dtype="Number" name="{{concat "traitArray." index}}" value="{{this}}" />
</div>
{{/each}}
</div>
<footer class="form-footer">
<button data-action="reset">
<i class="fa-solid fa-arrow-rotate-left"></i>
<span>{{localize "Reset"}}</span>
</button>
<button data-action="save" >
<i class="fa-solid fa-floppy-disk"></i>
<span>{{localize "Save Changes"}}</span>
</button>
</footer>
</div>

View file

@ -0,0 +1,22 @@
<div>
<div class="settings-col">
{{formGroup settingFields.schema.fields.enabled value=settingFields._source.enabled localize=true}}
{{formGroup settingFields.schema.fields.melee value=settingFields._source.melee localize=true}}
{{formGroup settingFields.schema.fields.veryClose value=settingFields._source.veryClose localize=true}}
{{formGroup settingFields.schema.fields.close value=settingFields._source.close localize=true}}
{{formGroup settingFields.schema.fields.far value=settingFields._source.far localize=true}}
{{formGroup settingFields.schema.fields.veryFar value=settingFields._source.veryFar localize=true}}
</div>
<footer class="form-footer">
<button data-action="reset">
<i class="fa-solid fa-arrow-rotate-left"></i>
<span>{{localize "Reset"}}</span>
</button>
<button data-action="save" >
<i class="fa-solid fa-floppy-disk"></i>
<span>{{localize "Save Changes"}}</span>
</button>
</footer>
</div>

View file

@ -3,8 +3,8 @@
<label>{{localize "DAGGERHEART.Settings.Menu.VariantRules.actionTokens"}}</label>
<div class="form-fields">
{{formInput settingFields.schema.fields.actionTokens.fields.enabled value=settingFields._source.actionTokens.enabled}}
{{formInput settingFields.schema.fields.actionTokens.fields.tokens value=settingFields._source.actionTokens.tokens disabled=(not settingFields._source.actionTokens.enabled)}}
{{formGroup settingFields.schema.fields.actionTokens.fields.enabled value=settingFields._source.actionTokens.enabled localize=true}}
{{formGroup settingFields.schema.fields.actionTokens.fields.tokens value=settingFields._source.actionTokens.tokens disabled=(not settingFields._source.actionTokens.enabled) localize=true}}
</div>
</div>

View file

@ -1,19 +0,0 @@
<form class={{cssClass}} autocomplete="off">
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Menu.Automation.HopeLabel"}}</label>
<div class="form-fields">
<input type="checkbox" name="{{settings.Hope}}" {{checked this.hope}} />
</div>
</div>
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Menu.Automation.ActionPointsLabel"}}</label>
<div class="form-fields">
<input type="checkbox" name="{{settings.ActionPoints}}" {{checked this.actionPoints}} />
</div>
</div>
<footer class="flexrow">
<button type="submit">Save</button>
<button>Cancel</button>
</footer>
</form>

View file

@ -1,13 +0,0 @@
<form class={{cssClass}} autocomplete="off">
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Menu.Homebrew.AbilityArrayLabel"}}</label>
<div class="form-fields">
<input type="text" name="{{settings.AbilityArray}}" value="{{this.abilityArray}}" />
</div>
</div>
<footer class="flexrow">
<button type="submit">Save</button>
<button>Cancel</button>
</footer>
</form>

View file

@ -1,44 +0,0 @@
<form class={{cssClass}} autocomplete="off">
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Menu.Range.EnabledLabel"}}</label>
<div class="form-fields reset-range-container">
<input style="height: 100%;" type="checkbox" name="enabled" {{checked this.range.enabled}} />
<button class="range-reset" style="flex: 0;"><i class="fa-solid fa-clock-rotate-left"></i></button>
</div>
</div>
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Menu.Range.MeleeLabel"}}</label>
<div class="form-fields">
<input type="text" name="melee" value="{{this.range.melee}}" data-dtype="Number" {{#if (not this.range.enabled)}}disabled{{/if}} />
</div>
</div>
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Menu.Range.VeryCloseLabel"}}</label>
<div class="form-fields">
<input type="text" name="veryClose" value="{{this.range.veryClose}}" data-dtype="Number" {{#if (not this.range.enabled)}}disabled{{/if}} />
</div>
</div>
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Menu.Range.CloseLabel"}}</label>
<div class="form-fields">
<input type="text" name="close" value="{{this.range.close}}" data-dtype="Number" {{#if (not this.range.enabled)}}disabled{{/if}} />
</div>
</div>
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Menu.Range.FarLabel"}}</label>
<div class="form-fields">
<input type="text" name="far" value="{{this.range.far}}" data-dtype="Number" {{#if (not this.range.enabled)}}disabled{{/if}} />
</div>
</div>
<div class="form-group">
<label>{{localize "DAGGERHEART.Settings.Menu.Range.VeryFarLabel"}}</label>
<div class="form-fields">
<input type="text" name="veryFar" value="{{this.range.veryFar}}" data-dtype="Number" {{#if (not this.range.enabled)}}disabled{{/if}} />
</div>
</div>
<footer class="flexrow">
<button class="save" {{#if this.disabled}}disabled{{/if}}>Save</button>
<button class="close">Cancel</button>
</footer>
</form>