mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-11 19:25:21 +01:00
[Feature] Homebrew Domains (#639)
* Split into tabs * Finished homebrew settings * . * Improved domainremoval cleanup
This commit is contained in:
parent
d186c62ee5
commit
02958f9574
24 changed files with 560 additions and 49 deletions
18
lang/en.json
18
lang/en.json
|
|
@ -1854,7 +1854,9 @@
|
|||
"tier1": "Tier 1",
|
||||
"tier2": "Tier 2",
|
||||
"tier3": "Tier 3",
|
||||
"tier4": "tier 4"
|
||||
"tier4": "tier 4",
|
||||
"domains": "Domains",
|
||||
"downtime": "Downtime"
|
||||
},
|
||||
"Tiers": {
|
||||
"singular": "Tier",
|
||||
|
|
@ -1887,6 +1889,7 @@
|
|||
"damageType": "Damage Type",
|
||||
"description": "Description",
|
||||
"difficulty": "Difficulty",
|
||||
"downtime": "Downtime",
|
||||
"dropActorsHere": "Drop Actors here",
|
||||
"duality": "Duality",
|
||||
"dualityRoll": "Duality Roll",
|
||||
|
|
@ -1919,6 +1922,7 @@
|
|||
"inactiveEffects": "Inactive Effects",
|
||||
"inventory": "Inventory",
|
||||
"itemResource": "Item Resource",
|
||||
"label": "Label",
|
||||
"level": "Level",
|
||||
"levelUp": "Level Up",
|
||||
"loadout": "Loadout",
|
||||
|
|
@ -2137,6 +2141,18 @@
|
|||
"handfullName": "Handfull Name",
|
||||
"bagName": "Bag Name",
|
||||
"chestName": "Chest Name"
|
||||
},
|
||||
"domains": {
|
||||
"domainsTitle": "Base Domains",
|
||||
"homebrewDomains": "Homebrew Domains",
|
||||
"newDomain": "New Domain",
|
||||
"newDomainInputTitle": "Create Homebrew Domain",
|
||||
"newDomainInputLabel": "New Domain Name",
|
||||
"newDomainInputHint": "This cannot be altered later",
|
||||
"editDomain": "Active Domain",
|
||||
"deleteDomain": "Delete Domain",
|
||||
"deleteDomainText": "Are you sure you want to delete the {name} domain? It will be immediately removed from all Actors in this world where it's currently used. Compendiums are not cleared.",
|
||||
"duplicateDomain": "There is already a domain with this identification."
|
||||
}
|
||||
},
|
||||
"Menu": {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export default class MulticlassChoiceDialog extends HandlebarsApplicationMixin(A
|
|||
const context = await super._prepareContext(_options);
|
||||
context.multiclass = this.multiclass;
|
||||
context.domainChoices = this.multiclass.domains.map(value => {
|
||||
const domain = CONFIG.DH.DOMAIN.domains[value];
|
||||
const domain = CONFIG.DH.DOMAIN.allDomains()[value];
|
||||
return {
|
||||
value: value,
|
||||
label: game.i18n.localize(domain.label),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import LevelUpBase from './levelup.mjs';
|
||||
import { DhLevelup } from '../../data/levelup.mjs';
|
||||
import { domains } from '../../config/domainConfig.mjs';
|
||||
import { abilities, subclassFeatureLabels } from '../../config/actorConfig.mjs';
|
||||
|
||||
export default class DhCharacterLevelUp extends LevelUpBase {
|
||||
|
|
@ -113,7 +112,7 @@ export default class DhCharacterLevelUp extends LevelUpBase {
|
|||
: levelBase;
|
||||
|
||||
return game.i18n.format('DAGGERHEART.APPLICATIONS.Levelup.selections.emptyDomainCardHint', {
|
||||
domain: game.i18n.localize(domains[domain.domain].label),
|
||||
domain: game.i18n.localize(CONFIG.DH.DOMAIN.allDomains()[domain.domain].label),
|
||||
level: levelMax
|
||||
});
|
||||
}),
|
||||
|
|
@ -170,7 +169,7 @@ export default class DhCharacterLevelUp extends LevelUpBase {
|
|||
uuid: multiclass.uuid,
|
||||
domains:
|
||||
multiclass?.system?.domains.map(key => {
|
||||
const domain = domains[key];
|
||||
const domain = CONFIG.DH.DOMAIN.allDomains()[key];
|
||||
const alreadySelected = this.actor.system.class.value.system.domains.includes(key);
|
||||
|
||||
return {
|
||||
|
|
@ -315,7 +314,10 @@ export default class DhCharacterLevelUp extends LevelUpBase {
|
|||
? {
|
||||
...multiclassItem.toObject(),
|
||||
domain: checkbox.secondaryData.domain
|
||||
? game.i18n.localize(domains[checkbox.secondaryData.domain].label)
|
||||
? game.i18n.localize(
|
||||
CONFIG.DH.DOMAIN.allDomains()[checkbox.secondaryData.domain]
|
||||
.label
|
||||
)
|
||||
: null,
|
||||
subclass: subclass ? subclass.name : null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { abilities, subclassFeatureLabels } from '../../config/actorConfig.mjs';
|
||||
import { domains } from '../../config/domainConfig.mjs';
|
||||
import { getDeleteKeys, tagifyElement } from '../../helpers/utils.mjs';
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
|
@ -253,7 +252,10 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
|||
? {
|
||||
...multiclassItem.toObject(),
|
||||
domain: checkbox.secondaryData.domain
|
||||
? game.i18n.localize(domains[checkbox.secondaryData.domain].label)
|
||||
? game.i18n.localize(
|
||||
CONFIG.DH.DOMAIN.allDomains()[checkbox.secondaryData.domain]
|
||||
.label
|
||||
)
|
||||
: null,
|
||||
subclass: subclass ? subclass.name : null
|
||||
}
|
||||
|
|
@ -357,10 +359,10 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
|||
experienceIncreaseTagify,
|
||||
Object.keys(this.actor.system.experiences).reduce((acc, id) => {
|
||||
const experience = this.actor.system.experiences[id];
|
||||
acc[id] = { label: experience.name };
|
||||
acc.push({ id: id, label: experience.name });
|
||||
|
||||
return acc;
|
||||
}, {}),
|
||||
}, []),
|
||||
this.tagifyUpdate('experience').bind(this)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { DhHomebrew } from '../../data/settings/_module.mjs';
|
||||
import { slugify } from '../../helpers/utils.mjs';
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
export default class DhHomebrewSettings extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
|
|
@ -8,6 +9,10 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
this.settings = new DhHomebrew(
|
||||
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).toObject()
|
||||
);
|
||||
|
||||
this.selected = {
|
||||
domain: null
|
||||
};
|
||||
}
|
||||
|
||||
get title() {
|
||||
|
|
@ -17,7 +22,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
id: 'daggerheart-homebrew-settings',
|
||||
classes: ['daggerheart', 'dh-style', 'dialog', 'setting'],
|
||||
classes: ['daggerheart', 'dh-style', 'dialog', 'setting', 'homebrew-settings'],
|
||||
position: { width: '600', height: 'auto' },
|
||||
window: {
|
||||
icon: 'fa-solid fa-gears'
|
||||
|
|
@ -27,6 +32,9 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
editItem: this.editItem,
|
||||
removeItem: this.removeItem,
|
||||
resetMoves: this.resetMoves,
|
||||
addDomain: this.addDomain,
|
||||
toggleSelectedDomain: this.toggleSelectedDomain,
|
||||
deleteDomain: this.deleteDomain,
|
||||
save: this.save,
|
||||
reset: this.reset
|
||||
},
|
||||
|
|
@ -34,9 +42,19 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
};
|
||||
|
||||
static PARTS = {
|
||||
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||
settings: { template: 'systems/daggerheart/templates/settings/homebrew-settings/settings.hbs' },
|
||||
domains: { template: 'systems/daggerheart/templates/settings/homebrew-settings/domains.hbs' },
|
||||
downtime: { template: 'systems/daggerheart/templates/settings/homebrew-settings/downtime.hbs' },
|
||||
footer: { template: 'systems/daggerheart/templates/settings/homebrew-settings/footer.hbs' }
|
||||
};
|
||||
|
||||
/** @inheritdoc */
|
||||
static TABS = {
|
||||
main: {
|
||||
template: 'systems/daggerheart/templates/settings/homebrew-settings.hbs',
|
||||
scrollable: ['']
|
||||
tabs: [{ id: 'settings' }, { id: 'domains' }, { id: 'downtime' }],
|
||||
initial: 'settings',
|
||||
labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -47,7 +65,26 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
return context;
|
||||
}
|
||||
|
||||
static async updateData(event, element, formData) {
|
||||
async _preparePartContext(partId, context) {
|
||||
await super._preparePartContext(partId, context);
|
||||
|
||||
switch (partId) {
|
||||
case 'domains':
|
||||
const selectedDomain = this.selected.domain ? this.settings.domains[this.selected.domain] : null;
|
||||
const enrichedDescription = selectedDomain
|
||||
? await foundry.applications.ux.TextEditor.implementation.enrichHTML(selectedDomain.description)
|
||||
: null;
|
||||
|
||||
if (enrichedDescription !== null) context.selectedDomain = { ...selectedDomain, enrichedDescription };
|
||||
context.configDomains = CONFIG.DH.DOMAIN.domains;
|
||||
context.homebrewDomains = this.settings.domains;
|
||||
break;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static async updateData(_event, _element, formData) {
|
||||
const updatedSettings = foundry.utils.expandObject(formData.object);
|
||||
|
||||
await this.settings.updateSource({
|
||||
|
|
@ -163,6 +200,107 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
this.render();
|
||||
}
|
||||
|
||||
static async addDomain(event) {
|
||||
event.preventDefault();
|
||||
const content = new foundry.data.fields.StringField({
|
||||
label: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.domains.newDomainInputLabel'),
|
||||
hint: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.domains.newDomainInputHint'),
|
||||
required: true
|
||||
}).toFormGroup({}, { name: 'domainName', localize: true }).outerHTML;
|
||||
|
||||
async function callback(_, button) {
|
||||
const domainName = button.form.elements.domainName.value;
|
||||
if (!domainName) return;
|
||||
|
||||
const newSlug = slugify(domainName);
|
||||
const existingDomains = [
|
||||
...Object.values(this.settings.domains),
|
||||
...Object.values(CONFIG.DH.DOMAIN.domains)
|
||||
];
|
||||
if (existingDomains.find(x => slugify(game.i18n.localize(x.label)) === newSlug)) {
|
||||
ui.notifications.warn(game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.domains.duplicateDomain'));
|
||||
return;
|
||||
}
|
||||
|
||||
this.settings.updateSource({
|
||||
[`domains.${newSlug}`]: {
|
||||
id: newSlug,
|
||||
label: domainName,
|
||||
src: 'icons/svg/portal.svg'
|
||||
}
|
||||
});
|
||||
|
||||
this.selected.domain = newSlug;
|
||||
this.render();
|
||||
}
|
||||
|
||||
foundry.applications.api.DialogV2.prompt({
|
||||
content: content,
|
||||
rejectClose: false,
|
||||
modal: true,
|
||||
ok: { callback: callback.bind(this) },
|
||||
window: {
|
||||
title: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.domains.newDomainInputTitle')
|
||||
},
|
||||
position: { width: 400 }
|
||||
});
|
||||
}
|
||||
|
||||
static toggleSelectedDomain(_, target) {
|
||||
this.selected.domain = this.selected.domain === target.id ? null : target.id;
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async deleteDomain() {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.domains.deleteDomain')
|
||||
},
|
||||
content: game.i18n.format('DAGGERHEART.SETTINGS.Homebrew.domains.deleteDomainText', {
|
||||
name: this.settings.domains[this.selected.domain].label
|
||||
})
|
||||
});
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
await this.settings.updateSource({
|
||||
[`domains.-=${this.selected.domain}`]: null
|
||||
});
|
||||
|
||||
const currentSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew);
|
||||
if (currentSettings.domains[this.selected.domain]) {
|
||||
await currentSettings.updateSource({ [`domains.-=${this.selected.domain}`]: null });
|
||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, currentSettings);
|
||||
}
|
||||
|
||||
const updateClasses = game.items.filter(x => x.type === 'class');
|
||||
for (let actor of game.actors) {
|
||||
updateClasses.push(...actor.items.filter(x => x.type === 'class'));
|
||||
}
|
||||
|
||||
for (let c of updateClasses) {
|
||||
if (c.system.domains.includes(this.selected.domain)) {
|
||||
const newDomains =
|
||||
c.system.domains.length === 1
|
||||
? [CONFIG.DH.DOMAIN.domains.arcana.id]
|
||||
: c.system.domains.filter(x => x !== this.selected.domain);
|
||||
await c.update({ 'system.domains': newDomains });
|
||||
}
|
||||
c.sheet.render();
|
||||
}
|
||||
|
||||
const updateDomainCards = game.items.filter(
|
||||
x => x.type === 'domainCard' && x.system.domain === this.selected.domain
|
||||
);
|
||||
for (let d of updateDomainCards) {
|
||||
await d.update({ 'system.domain': CONFIG.DH.DOMAIN.domains.arcana.id });
|
||||
d.sheet.render();
|
||||
}
|
||||
|
||||
this.selected.domain = null;
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async save() {
|
||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, this.settings.toObject());
|
||||
this.close();
|
||||
|
|
@ -200,4 +338,13 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
_getTabs(tabs) {
|
||||
for (const v of Object.values(tabs)) {
|
||||
v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active;
|
||||
v.cssClass = v.active ? 'active' : '';
|
||||
}
|
||||
|
||||
return tabs;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export default class ClassSheet extends DHBaseItemSheet {
|
|||
tagifyConfigs: [
|
||||
{
|
||||
selector: '.domain-input',
|
||||
options: () => CONFIG.DH.DOMAIN.domains,
|
||||
options: () => CONFIG.DH.DOMAIN.orderedDomains(),
|
||||
callback: ClassSheet.#onDomainSelect,
|
||||
tagifyOptions: {
|
||||
maxTags: () => game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxDomains
|
||||
|
|
|
|||
|
|
@ -34,4 +34,12 @@ export default class DomainCardSheet extends DHBaseItemSheet {
|
|||
scrollable: ['.effects']
|
||||
}
|
||||
};
|
||||
|
||||
async _prepareContext(options) {
|
||||
const context = await super._prepareContext(options);
|
||||
context.domain = CONFIG.DH.DOMAIN.allDomains()[this.document.system.domain];
|
||||
context.domainChoices = CONFIG.DH.DOMAIN.orderedDomains();
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ export default class FilterMenu extends foundry.applications.ux.ContextMenu {
|
|||
}
|
||||
}));
|
||||
|
||||
const domainFilter = Object.values(CONFIG.DH.DOMAIN.domains).map(({ id, label }) => ({
|
||||
const domainFilter = Object.values(CONFIG.DH.DOMAIN.allDomains()).map(({ id, label }) => ({
|
||||
group: game.i18n.localize('DAGGERHEART.GENERAL.Domain.single'),
|
||||
name: game.i18n.localize(label),
|
||||
filter: {
|
||||
|
|
|
|||
|
|
@ -55,8 +55,17 @@ export const domains = {
|
|||
}
|
||||
};
|
||||
|
||||
export const classDomainMap = {
|
||||
rogue: [domains.midnight, domains.grace]
|
||||
export const allDomains = () => ({
|
||||
...domains,
|
||||
...game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).domains
|
||||
});
|
||||
|
||||
export const orderedDomains = () => {
|
||||
const all = {
|
||||
...domains,
|
||||
...game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).domains
|
||||
};
|
||||
return Object.values(all).sort((a, b) => game.i18n.localize(a.label).localeCompare(game.i18n.localize(b.label)));
|
||||
};
|
||||
|
||||
export const subclassMap = {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default class DHDomainCard extends BaseDataItem {
|
|||
return {
|
||||
...super.defineSchema(),
|
||||
domain: new fields.StringField({
|
||||
choices: CONFIG.DH.DOMAIN.domains,
|
||||
choices: CONFIG.DH.DOMAIN.allDomains,
|
||||
required: true,
|
||||
initial: CONFIG.DH.DOMAIN.domains.arcana.id
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ import { defaultRestOptions } from '../../config/generalConfig.mjs';
|
|||
import { ActionsField } from '../fields/actionField.mjs';
|
||||
|
||||
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 {
|
||||
|
|
@ -98,7 +96,19 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
|
|||
{ initial: defaultRestOptions.shortRest() }
|
||||
)
|
||||
})
|
||||
})
|
||||
}),
|
||||
domains: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
id: new fields.StringField({ required: true }),
|
||||
label: new fields.StringField({ required: true, initial: '', label: 'DAGGERHEART.GENERAL.label' }),
|
||||
src: new fields.FilePathField({
|
||||
categories: ['IMAGE'],
|
||||
base64: false,
|
||||
label: 'Image'
|
||||
}),
|
||||
description: new fields.HTMLField()
|
||||
})
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,15 +83,16 @@ export const chunkify = (array, chunkSize, mappingFunc) => {
|
|||
return chunkifiedArray;
|
||||
};
|
||||
|
||||
export const tagifyElement = (element, options, onChange, tagifyOptions = {}) => {
|
||||
export const tagifyElement = (element, baseOptions, onChange, tagifyOptions = {}) => {
|
||||
const { maxTags } = tagifyOptions;
|
||||
const options = typeof baseOptions === 'object' ? Object.values(baseOptions) : baseOptions;
|
||||
|
||||
const tagifyElement = new Tagify(element, {
|
||||
tagTextProp: 'name',
|
||||
enforceWhitelist: true,
|
||||
whitelist: Object.keys(options).map(key => {
|
||||
const option = options[key];
|
||||
whitelist: options.map(option => {
|
||||
return {
|
||||
value: key,
|
||||
value: option.id,
|
||||
name: game.i18n.localize(option.label),
|
||||
src: option.src,
|
||||
description: option.description
|
||||
|
|
@ -100,7 +101,7 @@ export const tagifyElement = (element, options, onChange, tagifyOptions = {}) =>
|
|||
maxTags: typeof maxTags === 'function' ? maxTags() : maxTags,
|
||||
dropdown: {
|
||||
mapValueTo: 'name',
|
||||
searchKeys: ['name'],
|
||||
searchKeys: ['value'],
|
||||
enabled: 0,
|
||||
maxItems: 100,
|
||||
closeOnSelect: true,
|
||||
|
|
@ -369,3 +370,7 @@ export async function createEmbeddedItemWithEffects(actor, baseData, update) {
|
|||
|
||||
return doc;
|
||||
}
|
||||
|
||||
export const slugify = name => {
|
||||
return name.toLowerCase().replaceAll(' ', '-').replaceAll('.', '');
|
||||
};
|
||||
|
|
|
|||
|
|
@ -619,6 +619,7 @@
|
|||
margin-left: 8px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
filter: @dark-filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -651,23 +652,25 @@
|
|||
}
|
||||
}
|
||||
|
||||
.theme-light .application {
|
||||
&.sheet.dh-style {
|
||||
button.glow {
|
||||
animation: glow-dark 0.75s infinite alternate;
|
||||
}
|
||||
}
|
||||
|
||||
.component.dh-style.card-preview-container {
|
||||
background-image: url('../assets/parchments/dh-parchment-light.png');
|
||||
|
||||
.preview-text-container {
|
||||
background-image: url(../assets/parchments/dh-parchment-dark.png);
|
||||
.theme-light {
|
||||
.application {
|
||||
&.sheet.dh-style {
|
||||
button.glow {
|
||||
animation: glow-dark 0.75s infinite alternate;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-selected-icon-container {
|
||||
background-image: url(../assets/parchments/dh-parchment-dark.png);
|
||||
color: var(--color-light-5);
|
||||
.component.dh-style.card-preview-container {
|
||||
background-image: url('../assets/parchments/dh-parchment-light.png');
|
||||
|
||||
.preview-text-container {
|
||||
background-image: url(../assets/parchments/dh-parchment-dark.png);
|
||||
}
|
||||
|
||||
.preview-selected-icon-container {
|
||||
background-image: url(../assets/parchments/dh-parchment-dark.png);
|
||||
color: var(--color-light-5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
.appTheme({
|
||||
.item-card-header .item-icons-list .item-icon img {
|
||||
filter: invert(88%) sepia(98%) saturate(1784%) hue-rotate(311deg) brightness(104%) contrast(91%);
|
||||
filter: @golden-filter;
|
||||
}
|
||||
}, {
|
||||
.item-card-header .item-icons-list .item-icon img {
|
||||
filter: invert(87%) sepia(15%) saturate(343%) hue-rotate(333deg) brightness(110%) contrast(87%);
|
||||
filter: @bright-beige-filter;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -17,4 +17,6 @@
|
|||
|
||||
@import './resources/resources.less';
|
||||
|
||||
@import './settings/settings.less';
|
||||
@import './settings/settings.less';
|
||||
|
||||
@import './settings/homebrew-settings/domains.less';
|
||||
|
|
|
|||
155
styles/less/ui/settings/homebrew-settings/domains.less
Normal file
155
styles/less/ui/settings/homebrew-settings/domains.less
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
.theme-light .daggerheart.dh-style.setting.homebrew-settings .domains.tab {
|
||||
.domains-container .domain-container {
|
||||
.domain-label {
|
||||
background-image: url('../assets/parchments/dh-parchment-light.png');
|
||||
}
|
||||
|
||||
img {
|
||||
filter: @dark-filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.daggerheart.dh-style.setting.homebrew-settings {
|
||||
.domains.tab {
|
||||
.title-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
|
||||
&:first-child {
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.top-lines {
|
||||
position: relative;
|
||||
bottom: 8px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: @font-subtitle;
|
||||
position: relative;
|
||||
width: auto;
|
||||
white-space: nowrap;
|
||||
margin-top: 16px;
|
||||
gap: 8px;
|
||||
color: light-dark(@dark, @beige);
|
||||
|
||||
.add-button {
|
||||
border-radius: 50%;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.domains-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||
gap: 8px;
|
||||
|
||||
.domain-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 6px;
|
||||
|
||||
&.selectable {
|
||||
height: 100%;
|
||||
background: inherit;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.inactive {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.domain-label {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 6px;
|
||||
padding: 0 2px;
|
||||
color: light-dark(@dark, @beige);
|
||||
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||
white-space: nowrap;
|
||||
text-wrap: auto;
|
||||
text-align: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 6px;
|
||||
filter: @beige-filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.domain-edit-container {
|
||||
display: grid;
|
||||
grid-template-rows: 0fr;
|
||||
transition: grid-template-rows 0.3s ease-in-out;
|
||||
overflow: hidden;
|
||||
|
||||
&.extended {
|
||||
grid-template-rows: 1fr;
|
||||
|
||||
fieldset {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
fieldset {
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
|
||||
legend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
button {
|
||||
border-radius: 50%;
|
||||
font-size: 12px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.domain-filepicker-row {
|
||||
width: 100%;
|
||||
|
||||
.form-group {
|
||||
flex: 1;
|
||||
gap: 8px;
|
||||
|
||||
.form-fields {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
||||
file-picker {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -119,6 +119,7 @@
|
|||
top: -7px;
|
||||
font-size: 12px;
|
||||
font-variant: petite-caps;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
input {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
@golden-10: #f3c26710;
|
||||
@golden-40: #f3c26740;
|
||||
@golden-bg: #f3c2671a;
|
||||
@golden-filter: brightness(0) saturate(100%) invert(89%) sepia(13%) saturate(2008%) hue-rotate(332deg) brightness(99%)
|
||||
contrast(92%);
|
||||
|
||||
@chat-blue: #8f87ee;
|
||||
@chat-blue-10: #8f87ee10;
|
||||
|
|
@ -49,6 +51,7 @@
|
|||
@dark: #222;
|
||||
@dark-15: #22222215;
|
||||
@dark-40: #22222240;
|
||||
@dark-filter: brightness(0) saturate(100%);
|
||||
|
||||
@deep-black: #0e0d15;
|
||||
|
||||
|
|
@ -56,6 +59,10 @@
|
|||
@beige-15: #efe6d815;
|
||||
@beige-50: #efe6d850;
|
||||
@beige-80: #efe6d880;
|
||||
@beige-filter: brightness(0) saturate(100%) invert(87%) sepia(25%) saturate(164%) hue-rotate(339deg) brightness(106%)
|
||||
contrast(87%);
|
||||
@bright-beige-filter: brightness(0) saturate(100%) invert(87%) sepia(15%) saturate(343%) hue-rotate(333deg)
|
||||
brightness(110%) contrast(87%);
|
||||
|
||||
@soft-white-shadow: rgba(255, 255, 255, 0.05);
|
||||
|
||||
|
|
|
|||
45
templates/settings/homebrew-settings/domains.hbs
Normal file
45
templates/settings/homebrew-settings/domains.hbs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<section
|
||||
class="tab {{tabs.domains.cssClass}} {{tabs.domains.id}}"
|
||||
data-tab="{{tabs.domains.id}}"
|
||||
data-group="{{tabs.domains.group}}"
|
||||
>
|
||||
<div class="title-wrapper">
|
||||
<side-line-div class="invert top-lines"></side-line-div>
|
||||
<h2>{{localize "DAGGERHEART.SETTINGS.Homebrew.domains.domainsTitle"}}</h2>
|
||||
<side-line-div class="top-lines"></side-line-div>
|
||||
</div>
|
||||
<div class="domains-container">
|
||||
{{#each configDomains as | domain |}}
|
||||
<div class="domain-container">
|
||||
<div class="domain-label">{{localize domain.label}}</div>
|
||||
<img src="{{domain.src}}" class="domain-icon" />
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
<div class="title-wrapper">
|
||||
<side-line-div class="invert"></side-line-div>
|
||||
<h2>
|
||||
{{localize "DAGGERHEART.SETTINGS.Homebrew.domains.homebrewDomains"}}
|
||||
<button class="add-button" data-action="addDomain"><i class="fa-solid fa-plus"></i></button>
|
||||
</h2>
|
||||
<side-line-div></side-line-div>
|
||||
</div>
|
||||
<div class="domains-container">
|
||||
{{#each homebrewDomains as | domain id |}}
|
||||
<button class="domain-container selectable {{#unless (eq @root.selectedDomain.id id)}}inactive{{/unless}}" id="{{id}}" data-action="toggleSelectedDomain">
|
||||
<div class="domain-label">{{localize domain.label}}</div>
|
||||
<img src="{{domain.src}}" class="domain-icon" style="--domain-icon: url({{domain.src}})" />
|
||||
</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
<div class="domain-edit-container {{#if @root.selectedDomain}}extended{{/if}}">
|
||||
<fieldset>
|
||||
<legend>{{localize "DAGGERHEART.SETTINGS.Homebrew.domains.editDomain"}} <button class="add-button" data-action="deleteDomain"><i class="fa-solid fa-x"></i></button></legend>
|
||||
|
||||
<div class="domain-filepicker-row">{{formGroup settingFields.schema.fields.domains.element.fields.src value=selectedDomain.src name=(concat "domains." selectedDomain.id ".src") localize=true}}</div>
|
||||
<textarea name="{{concat "domains." selectedDomain.id ".description"}}">{{selectedDomain.description}}</textarea>
|
||||
</fieldset>
|
||||
</div>
|
||||
</section>
|
||||
51
templates/settings/homebrew-settings/downtime.hbs
Normal file
51
templates/settings/homebrew-settings/downtime.hbs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<section
|
||||
class="tab {{tabs.downtime.cssClass}} {{tabs.downtime.id}}"
|
||||
data-tab="{{tabs.downtime.id}}"
|
||||
data-group="{{tabs.downtime.group}}"
|
||||
>
|
||||
<fieldset class="two-columns even">
|
||||
<legend>{{localize "DAGGERHEART.SETTINGS.Homebrew.downtimeMoves"}}</legend>
|
||||
|
||||
<fieldset class="start-align">
|
||||
<legend>
|
||||
{{localize "DAGGERHEART.APPLICATIONS.Downtime.longRest.title"}}
|
||||
<a data-action="addItem" data-type="longRest"><i class="fa-solid fa-plus"></i></a>
|
||||
<a data-action="resetMoves" data-type="longRest"><i class="fa-solid fa-arrow-rotate-left"></i></a>
|
||||
</legend>
|
||||
|
||||
<div class="form-group setting-group-field">
|
||||
<label>{{localize "DAGGERHEART.SETTINGS.Homebrew.nrChoices"}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="restMoves.longRest.nrChoices" value="{{settingFields._source.restMoves.longRest.nrChoices}}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-items">
|
||||
{{#each settingFields._source.restMoves.longRest.moves as |move id|}}
|
||||
{{> "systems/daggerheart/templates/settings/components/settings-item-line.hbs" this type="longRest" id=id }}
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="start-align">
|
||||
<legend>
|
||||
{{localize "DAGGERHEART.APPLICATIONS.Downtime.shortRest.title"}}
|
||||
<a data-action="addItem" data-type="shortRest"><i class="fa-solid fa-plus"></i></a>
|
||||
<a data-action="resetMoves" data-type="shortRest"><i class="fa-solid fa-arrow-rotate-left"></i></a>
|
||||
</legend>
|
||||
|
||||
<div class="form-group setting-group-field">
|
||||
<label>{{localize "DAGGERHEART.SETTINGS.Homebrew.nrChoices"}}</label>
|
||||
<div class="form-fields">
|
||||
<input type="text" name="restMoves.shortRest.nrChoices" value="{{settingFields._source.restMoves.shortRest.nrChoices}}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-items">
|
||||
{{#each settingFields._source.restMoves.shortRest.moves as |move id|}}
|
||||
{{> "systems/daggerheart/templates/settings/components/settings-item-line.hbs" this type="shortRest" id=id }}
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
</section>
|
||||
10
templates/settings/homebrew-settings/footer.hbs
Normal file
10
templates/settings/homebrew-settings/footer.hbs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<footer class="form-footer">
|
||||
<button type="button" data-action="reset">
|
||||
<i class="fa-solid fa-arrow-rotate-left"></i>
|
||||
<span>{{localize "Reset"}}</span>
|
||||
</button>
|
||||
<button type="button" data-action="save" >
|
||||
<i class="fa-solid fa-floppy-disk"></i>
|
||||
<span>{{localize "Save Changes"}}</span>
|
||||
</button>
|
||||
</footer>
|
||||
38
templates/settings/homebrew-settings/settings.hbs
Normal file
38
templates/settings/homebrew-settings/settings.hbs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<section
|
||||
class="tab {{tabs.settings.cssClass}} {{tabs.settings.id}}"
|
||||
data-tab="{{tabs.settings.id}}"
|
||||
data-group="{{tabs.settings.group}}"
|
||||
>
|
||||
<div class="scrollable">
|
||||
<header class="dialog-header">
|
||||
<h1>{{localize 'DAGGERHEART.SETTINGS.Menu.homebrew.name'}}</h1>
|
||||
</header>
|
||||
{{formGroup settingFields.schema.fields.maxFear value=settingFields._source.maxFear localize=true}}
|
||||
{{formGroup settingFields.schema.fields.maxDomains value=settingFields._source.maxDomains localize=true}}
|
||||
{{formGroup settingFields.schema.fields.maxLoadout value=settingFields._source.maxLoadout localize=true}}
|
||||
<div class="settings-hint"><label>{{localize "DAGGERHEART.SETTINGS.Homebrew.FIELDS.maxLoadout.hint"}}</label></div>
|
||||
|
||||
<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.single"}} {{add index 1}}</label>
|
||||
<input type="text" data-dtype="Number" name="{{concat "traitArray." index}}" value="{{this}}" />
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
<fieldset>
|
||||
<legend>
|
||||
{{localize "DAGGERHEART.SETTINGS.Homebrew.currency.title"}}
|
||||
</legend>
|
||||
{{formGroup settingFields.schema.fields.currency.fields.enabled value=settingFields._source.currency.enabled localize=true}}
|
||||
{{formGroup settingFields.schema.fields.currency.fields.title value=settingFields._source.currency.title localize=true}}
|
||||
{{formGroup settingFields.schema.fields.currency.fields.coins value=settingFields._source.currency.coins localize=true}}
|
||||
{{formGroup settingFields.schema.fields.currency.fields.handfulls value=settingFields._source.currency.handfulls localize=true}}
|
||||
{{formGroup settingFields.schema.fields.currency.fields.bags value=settingFields._source.currency.bags localize=true}}
|
||||
{{formGroup settingFields.schema.fields.currency.fields.chests value=settingFields._source.currency.chests localize=true}}
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -7,8 +7,8 @@
|
|||
<i class="fa-solid fa-bolt"></i>
|
||||
</span>
|
||||
<span class="item-icon">
|
||||
<span class="recall-label">{{localize (concat 'DAGGERHEART.GENERAL.Domain.' source.system.domain '.label')}}</span>
|
||||
<img src="{{concat 'systems/daggerheart/assets/icons/domains/' source.system.domain '.svg'}}" alt="">
|
||||
<span class="recall-label">{{localize @root.domain.label}}</span>
|
||||
<img src="{{@root.domain.src}}" alt="">
|
||||
</span>
|
||||
</div>
|
||||
<div class='item-info'>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
<h3>
|
||||
{{localize (concat 'DAGGERHEART.CONFIG.DomainCardTypes.' source.system.type)}}
|
||||
<span>-</span>
|
||||
{{localize (concat 'DAGGERHEART.GENERAL.Domain.' source.system.domain '.label')}}
|
||||
{{localize @root.domain.label}}
|
||||
<span>-</span>
|
||||
{{localize "DAGGERHEART.GENERAL.level"}}:
|
||||
{{source.system.level}}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<span>{{localize "DAGGERHEART.GENERAL.type"}}</span>
|
||||
{{formField systemFields.type value=source.system.type localize=true}}
|
||||
<span>{{localize "DAGGERHEART.GENERAL.Domain.single"}}</span>
|
||||
{{formField systemFields.domain value=source.system.domain localize=true}}
|
||||
{{formField systemFields.domain value=source.system.domain choices=domainChoices valueAttr="id" labelAttr="label" localize=true}}
|
||||
<span>{{localize "DAGGERHEART.GENERAL.level"}}</span>
|
||||
{{formField systemFields.level value=source.system.level data-dtype="Number"}}
|
||||
<span>{{localize "DAGGERHEART.ITEMS.DomainCard.recallCost"}}</span>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue