Merge remote-tracking branch 'origin/main' into foundry/v12
This commit is contained in:
commit
76cca3f672
17 changed files with 223 additions and 81 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -6,7 +6,7 @@ references/
|
||||||
/.*/
|
/.*/
|
||||||
!/.vscode/
|
!/.vscode/
|
||||||
!/.github/
|
!/.github/
|
||||||
/foundry.js
|
/*.ref.*
|
||||||
*.lock
|
*.lock
|
||||||
*.zip
|
*.zip
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,9 +81,11 @@
|
||||||
"send-to-chat": "Send to Chat",
|
"send-to-chat": "Send to Chat",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
|
"reset": "Reset",
|
||||||
"empty": "---",
|
"empty": "---",
|
||||||
"help": "Help",
|
"help": "Help",
|
||||||
"gm": "Server"
|
"gm": "Server",
|
||||||
|
"view-larger": "View Larger"
|
||||||
},
|
},
|
||||||
"sheet-names": {
|
"sheet-names": {
|
||||||
"*DataSheet": "Data Sheet"
|
"*DataSheet": "Data Sheet"
|
||||||
|
|
@ -93,6 +95,12 @@
|
||||||
"title": "What is Calculated Capacity?",
|
"title": "What is Calculated Capacity?",
|
||||||
"content": "<p>The calculated capacity is how much space in your inventory that the item will take up, the way it is calculated is determined by the item. Usually the main thing that affects the capacity is the item's quantity, but this can be turned off by the @dotdungeon.common.gm, which means that no matter the quantity it will only use up one capacity. The @dotdungeon.common.gm can also entirely disable capacity usage which will make the used capacity always be zero.</p>"
|
"content": "<p>The calculated capacity is how much space in your inventory that the item will take up, the way it is calculated is determined by the item. Usually the main thing that affects the capacity is the item's quantity, but this can be turned off by the @dotdungeon.common.gm, which means that no matter the quantity it will only use up one capacity. The @dotdungeon.common.gm can also entirely disable capacity usage which will make the used capacity always be zero.</p>"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"ActiveEffect": {
|
||||||
|
"title": "Delete Effect",
|
||||||
|
"content": "<p>Are you sure you would like to delete the active effect: {name}</p>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"TYPES": {
|
"TYPES": {
|
||||||
|
|
@ -113,6 +121,9 @@
|
||||||
"legendaryItem": "Legendary Item",
|
"legendaryItem": "Legendary Item",
|
||||||
"spell": "Spell",
|
"spell": "Spell",
|
||||||
"untyped": "Custom"
|
"untyped": "Custom"
|
||||||
|
},
|
||||||
|
"ActiveEffect": {
|
||||||
|
"base": "Effect"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
7
module/documents/ActiveEffect/GenericActiveEffect.mjs
Normal file
7
module/documents/ActiveEffect/GenericActiveEffect.mjs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export class DotDungeonActiveEffect extends ActiveEffect {
|
||||||
|
|
||||||
|
// Invert the logic of the disabled property so it's easier to modify via
|
||||||
|
// embedded controls
|
||||||
|
get enabled() { return !this.disabled };
|
||||||
|
set enabled(newValue) { this.disabled = !newValue };
|
||||||
|
};
|
||||||
42
module/documents/ActiveEffect/_proxy.mjs
Normal file
42
module/documents/ActiveEffect/_proxy.mjs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { DotDungeonActiveEffect } from "./GenericActiveEffect.mjs";
|
||||||
|
|
||||||
|
const classes = {};
|
||||||
|
|
||||||
|
const defaultClass = DotDungeonActiveEffect;
|
||||||
|
|
||||||
|
export const ActiveEffectProxy = new Proxy(function () {}, {
|
||||||
|
construct(target, args) {
|
||||||
|
const [data] = args;
|
||||||
|
|
||||||
|
if (!classes.hasOwnProperty(data.type)) {
|
||||||
|
return new defaultClass(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new classes[data.type](...args);
|
||||||
|
},
|
||||||
|
get(target, prop, receiver) {
|
||||||
|
|
||||||
|
if (["create", "createDocuments"].includes(prop)) {
|
||||||
|
return function (data, options) {
|
||||||
|
if (data.constructor === Array) {
|
||||||
|
return data.map(i => ActiveEffectProxy.create(i, options))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!classes.hasOwnProperty(data.type)) {
|
||||||
|
return defaultClass.create(data, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes[data.type].create(data, options);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (prop == Symbol.hasInstance) {
|
||||||
|
return function (instance) {
|
||||||
|
if (instance instanceof defaultClass) return true;
|
||||||
|
return Object.values(classes).some(i => instance instanceof i);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return defaultClass[prop];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -1,4 +1,15 @@
|
||||||
export class DotDungeonActor extends Actor {
|
export class DotDungeonActor extends Actor {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Using this to take a "snapshot" of the system data prior to applying AE's so
|
||||||
|
that the inputs can still have the non-modified value in them, while we still
|
||||||
|
provide all that data to AE's without needing to disable any inputs.
|
||||||
|
*/
|
||||||
|
prepareEmbeddedDocuments() {
|
||||||
|
this.preAE = foundry.utils.deepClone(this.system);
|
||||||
|
super.prepareEmbeddedDocuments();
|
||||||
|
};
|
||||||
|
|
||||||
async createEmbeddedItem(defaults, opts = {}) {
|
async createEmbeddedItem(defaults, opts = {}) {
|
||||||
let items = await this.createEmbeddedDocuments(`Item`, defaults);
|
let items = await this.createEmbeddedDocuments(`Item`, defaults);
|
||||||
if (!Array.isArray(items)) items = items ? [items] : [];
|
if (!Array.isArray(items)) items = items ? [items] : [];
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,22 @@
|
||||||
import { DotDungeonActor } from "./GenericActor.mjs";
|
import { DotDungeonActor } from "./GenericActor.mjs";
|
||||||
import { DotDungeonItem } from "../Item/GenericItem.mjs";
|
|
||||||
|
|
||||||
export class Player extends DotDungeonActor {
|
export class Player extends DotDungeonActor {
|
||||||
|
|
||||||
|
applyActiveEffects() {
|
||||||
|
super.applyActiveEffects();
|
||||||
|
|
||||||
|
/*
|
||||||
|
These are the (groups of) fields that ActiveEffects may modify safely and
|
||||||
|
remain editable in the sheet. This needs to be done because of default
|
||||||
|
Foundry behaviour that otherwise prevents these fields from being edited.
|
||||||
|
The deletes must use optional chaining otherwise they can cause issues
|
||||||
|
during the document preparation lifecycle as an actor with no AE's affecting
|
||||||
|
anything in one of these areas will result in these paths being undefined.
|
||||||
|
*/
|
||||||
|
delete this.overrides.system?.stats;
|
||||||
|
delete this.overrides.system?.skills;
|
||||||
|
};
|
||||||
|
|
||||||
async createCustomPet() {
|
async createCustomPet() {
|
||||||
const body = new URLSearchParams({
|
const body = new URLSearchParams({
|
||||||
number: 1,
|
number: 1,
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,11 @@ export class Material extends DotDungeonItem {
|
||||||
let affects = game.settings.get(`dotdungeon`, `materialsAffectCapacity`);
|
let affects = game.settings.get(`dotdungeon`, `materialsAffectCapacity`);
|
||||||
return affects ? super.usedCapacity : 0;
|
return affects ? super.usedCapacity : 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
get availableLocations() {
|
||||||
|
return [
|
||||||
|
{ value: null, label: `dotdungeon.location.unknown` },
|
||||||
|
{ value: `inventory`, label: `dotdungeon.location.inventory` },
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { SyncData } from "./models/Actor/Sync.mjs";
|
||||||
import { MobData } from "./models/Actor/Mob.mjs";
|
import { MobData } from "./models/Actor/Mob.mjs";
|
||||||
|
|
||||||
// Main Documents
|
// Main Documents
|
||||||
|
import { ActiveEffectProxy } from "./documents/ActiveEffect/_proxy.mjs";
|
||||||
import { ActorProxy } from "./documents/Actor/_proxy.mjs";
|
import { ActorProxy } from "./documents/Actor/_proxy.mjs";
|
||||||
import { ItemProxy } from "./documents/Item/_proxy.mjs";
|
import { ItemProxy } from "./documents/Item/_proxy.mjs";
|
||||||
|
|
||||||
|
|
@ -56,6 +57,7 @@ Hooks.once(`init`, async () => {
|
||||||
CONFIG.Item.dataModels.pet = PetItemData;
|
CONFIG.Item.dataModels.pet = PetItemData;
|
||||||
CONFIG.Actor.documentClass = ActorProxy;
|
CONFIG.Actor.documentClass = ActorProxy;
|
||||||
CONFIG.Item.documentClass = ItemProxy;
|
CONFIG.Item.documentClass = ItemProxy;
|
||||||
|
CONFIG.ActiveEffect.documentClass = ActiveEffectProxy;
|
||||||
|
|
||||||
CONFIG.DOTDUNGEON = DOTDUNGEON;
|
CONFIG.DOTDUNGEON = DOTDUNGEON;
|
||||||
|
|
||||||
|
|
@ -111,9 +113,6 @@ Hooks.once(`init`, async () => {
|
||||||
hbs.registerHandlebarsHelpers();
|
hbs.registerHandlebarsHelpers();
|
||||||
hbs.preloadHandlebarsTemplates();
|
hbs.preloadHandlebarsTemplates();
|
||||||
registerCustomComponents();
|
registerCustomComponents();
|
||||||
|
|
||||||
CONFIG.CACHE ??= {};
|
|
||||||
CONFIG.CACHE.icons = await hbs.preloadIcons();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,25 +43,6 @@ export const preAliasedPartials = {
|
||||||
"dotdungeon.pc.v2.foil": "actors/char-sheet/v2/partials/inventory/items/untyped.v2.pc.hbs",
|
"dotdungeon.pc.v2.foil": "actors/char-sheet/v2/partials/inventory/items/untyped.v2.pc.hbs",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const icons = [
|
|
||||||
`caret-right.svg`,
|
|
||||||
`caret-down.svg`,
|
|
||||||
`garbage-bin.svg`,
|
|
||||||
`chat-bubble.svg`,
|
|
||||||
`dice/d4.svg`,
|
|
||||||
`dice/d6.svg`,
|
|
||||||
`dice/d8.svg`,
|
|
||||||
`dice/d10.svg`,
|
|
||||||
`dice/d12.svg`,
|
|
||||||
`dice/d20.svg`,
|
|
||||||
`create.svg`,
|
|
||||||
`close.svg`,
|
|
||||||
`edit.svg`,
|
|
||||||
`sheet.svg`,
|
|
||||||
`minus.svg`,
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
export async function registerHandlebarsHelpers() {
|
export async function registerHandlebarsHelpers() {
|
||||||
Handlebars.registerHelper(helpers);
|
Handlebars.registerHelper(helpers);
|
||||||
};
|
};
|
||||||
|
|
@ -97,38 +78,3 @@ export async function preloadHandlebarsTemplates() {
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
return loadTemplates(paths);
|
return loadTemplates(paths);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads all of the icons that are needed in the handlebars templating to make
|
|
||||||
* the sheet look nicer.
|
|
||||||
*
|
|
||||||
* @returns An object containing icon names to the corresponding HTML data for
|
|
||||||
* displaying the icon
|
|
||||||
*/
|
|
||||||
export async function preloadIcons() {
|
|
||||||
const pathPrefix = `systems/dotdungeon/assets/`
|
|
||||||
const parsedIcons = {};
|
|
||||||
|
|
||||||
for (const icon of icons) {
|
|
||||||
const iconName = icon.split(`/`).slice(-1)[0].slice(0, -4);
|
|
||||||
if (icon.endsWith(`.svg`)) {
|
|
||||||
try {
|
|
||||||
const response = await fetchWithTimeout(`${pathPrefix}${icon}`);
|
|
||||||
if (response.status !== 200) { continue };
|
|
||||||
const svgData = await response.text();
|
|
||||||
parsedIcons[iconName] = svgData;
|
|
||||||
} catch {
|
|
||||||
console.error(`.dungeon | Failed to fetch/parse icon: ${icon}`);
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (icon.endsWith(`.png`)) {
|
|
||||||
parsedIcons[iconName] = `<img alt="" src="${pathPrefix}${icon}">`;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.warn(`.dungeon | Icon "${icon}" failed to be handled by a loader`)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return parsedIcons;
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,8 @@ export class PlayerSheetv2 extends GenericActorSheet {
|
||||||
|
|
||||||
html.find(`.create-ae`).on(`click`, async ($e) => {
|
html.find(`.create-ae`).on(`click`, async ($e) => {
|
||||||
console.debug(`Creating an ActiveEffect?`);
|
console.debug(`Creating an ActiveEffect?`);
|
||||||
ActiveEffect.implementation.create({
|
const ae = this.actor.createEmbeddedDocuments(`ActiveEffect`, [{name: "Default AE"}]);
|
||||||
name: "Default AE",
|
ae.sheet.render(true);
|
||||||
}, { parent: this.actor, renderSheet: true });
|
|
||||||
});
|
});
|
||||||
html.find(`[data-filter-toggle]`).on(`change`, ($e) => {
|
html.find(`[data-filter-toggle]`).on(`change`, ($e) => {
|
||||||
const target = $e.delegateTarget;
|
const target = $e.delegateTarget;
|
||||||
|
|
@ -74,6 +73,7 @@ export class PlayerSheetv2 extends GenericActorSheet {
|
||||||
/** @type {ActorHandler} */
|
/** @type {ActorHandler} */
|
||||||
const actor = this.actor;
|
const actor = this.actor;
|
||||||
|
|
||||||
|
ctx.preAE = actor.preAE;
|
||||||
ctx.system = actor.system;
|
ctx.system = actor.system;
|
||||||
ctx.flags = actor.flags;
|
ctx.flags = actor.flags;
|
||||||
ctx.items = this.actor.itemTypes;
|
ctx.items = this.actor.itemTypes;
|
||||||
|
|
@ -97,6 +97,7 @@ export class PlayerSheetv2 extends GenericActorSheet {
|
||||||
const stat = {
|
const stat = {
|
||||||
key: statName,
|
key: statName,
|
||||||
name: localizer(`dotdungeon.stat.${statName}`),
|
name: localizer(`dotdungeon.stat.${statName}`),
|
||||||
|
original: this.actor.preAE.stats[statName],
|
||||||
value: this.actor.system.stats[statName],
|
value: this.actor.system.stats[statName],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -111,7 +112,7 @@ export class PlayerSheetv2 extends GenericActorSheet {
|
||||||
return {
|
return {
|
||||||
value: die,
|
value: die,
|
||||||
label: localizer(`dotdungeon.die.${die}`, { stat: statName }),
|
label: localizer(`dotdungeon.die.${die}`, { stat: statName }),
|
||||||
disabled: usedDice.has(die) && this.actor.system.stats[statName] !== die,
|
disabled: usedDice.has(die) && this.actor.preAE.stats[statName] !== die,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
@ -127,8 +128,9 @@ export class PlayerSheetv2 extends GenericActorSheet {
|
||||||
key: skill,
|
key: skill,
|
||||||
name: game.i18n.format(`dotdungeon.skills.${skill}`),
|
name: game.i18n.format(`dotdungeon.skills.${skill}`),
|
||||||
value,
|
value,
|
||||||
|
original: this.actor.preAE.skills[statName][skill],
|
||||||
formula: `1` + stat.value + modifierToString(value, { spaces: true }),
|
formula: `1` + stat.value + modifierToString(value, { spaces: true }),
|
||||||
rollDisabled: value === -1,
|
rollDisabled: this.actor.preAE.skills[statName][skill] === -1,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ export class GenericActorSheet extends ActorSheet {
|
||||||
|
|
||||||
ctx.actor = this.actor;
|
ctx.actor = this.actor;
|
||||||
ctx.config = DOTDUNGEON;
|
ctx.config = DOTDUNGEON;
|
||||||
ctx.icons = CONFIG.CACHE.icons;
|
ctx.icons = {};
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,10 @@ export class GenericItemSheet extends ItemSheet {
|
||||||
ctx.item = this.item;
|
ctx.item = this.item;
|
||||||
ctx.system = this.item.system;
|
ctx.system = this.item.system;
|
||||||
ctx.flags = this.item.flags;
|
ctx.flags = this.item.flags;
|
||||||
|
ctx.effects = this.item.effects;
|
||||||
|
|
||||||
ctx.config = DOTDUNGEON;
|
ctx.config = DOTDUNGEON;
|
||||||
ctx.icons = CONFIG.CACHE.icons;
|
ctx.icons = {};
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import { GenericContextMenu } from "../../utils/GenericContextMenu.mjs";
|
import { GenericContextMenu } from "../../utils/GenericContextMenu.mjs";
|
||||||
|
import { DialogManager } from "../../utils/DialogManager.mjs";
|
||||||
import { GenericItemSheet } from "./GenericItemSheet.mjs";
|
import { GenericItemSheet } from "./GenericItemSheet.mjs";
|
||||||
|
import { localizer } from "../../utils/localizer.mjs";
|
||||||
|
|
||||||
export class UntypedItemSheet extends GenericItemSheet {
|
export class UntypedItemSheet extends GenericItemSheet {
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
|
|
@ -28,22 +30,78 @@ export class UntypedItemSheet extends GenericItemSheet {
|
||||||
|
|
||||||
new GenericContextMenu(html, `.photo.panel`, [
|
new GenericContextMenu(html, `.photo.panel`, [
|
||||||
{
|
{
|
||||||
name: `View Larger`,
|
name: localizer(`dotdungeon.common.view-larger`),
|
||||||
callback: (html) => {
|
callback: () => {
|
||||||
console.log(`.dungeon | View Larger`);
|
(new ImagePopout(this.item.img)).render(true);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `Change Photo`,
|
name: localizer(`dotdungeon.common.edit`),
|
||||||
condition: () => this.isEditable,
|
condition: () => this.isEditable,
|
||||||
callback: (html) => {
|
callback: () => {
|
||||||
console.log(`.dungeon | Change Photo`);
|
const fp = new FilePicker({
|
||||||
|
callback: (path) => {
|
||||||
|
this.item.update({"img": path});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
fp.render(true);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: localizer(`dotdungeon.common.reset`),
|
||||||
|
condition: () => this.isEditable,
|
||||||
|
callback: () => {
|
||||||
|
console.log(`.dungeon | Reset Item Image`)
|
||||||
|
},
|
||||||
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!this.isEditable) return;
|
if (!this.isEditable) return;
|
||||||
console.debug(`.dungeon | Adding event listeners for Untyped Item: ${this.item.id}`);
|
console.debug(`.dungeon | Adding event listeners for Untyped Item: ${this.item.id}`);
|
||||||
|
|
||||||
|
html.find(`.create-ae`).on(`click`, async () => {
|
||||||
|
await this.item.createEmbeddedDocuments(
|
||||||
|
`ActiveEffect`,
|
||||||
|
[{name: localizer(`dotdungeon.default.name`, { document: `ActiveEffect`, type: `base` })}],
|
||||||
|
{ renderSheet: true }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
new GenericContextMenu(html, `.effect.panel`, [
|
||||||
|
{
|
||||||
|
name: localizer(`dotdungeon.common.edit`),
|
||||||
|
callback: async (html) => {
|
||||||
|
(await fromUuid(html.closest(`.effect`)[0].dataset.embeddedId))?.sheet.render(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: localizer(`dotdungeon.common.delete`),
|
||||||
|
callback: async (html) => {
|
||||||
|
const target = html.closest(`.effect`)[0];
|
||||||
|
const data = target.dataset;
|
||||||
|
const id = data.embeddedId;
|
||||||
|
const doc = await fromUuid(id);
|
||||||
|
DialogManager.createOrFocus(
|
||||||
|
`${doc.uuid}-delete`,
|
||||||
|
{
|
||||||
|
title: localizer(`dotdungeon.delete.ActiveEffect.title`, doc),
|
||||||
|
content: localizer(`dotdungeon.delete.ActiveEffect.content`, doc),
|
||||||
|
buttons: {
|
||||||
|
yes: {
|
||||||
|
label: localizer(`Yes`),
|
||||||
|
callback() {
|
||||||
|
doc.delete();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
no: {
|
||||||
|
label: localizer(`No`),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
async getData() {
|
async getData() {
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,20 @@ export function localizer(key, args = {}, depth = 0) {
|
||||||
return localized;
|
return localized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helps prevent recursion on the same key so that we aren't doing excess work.
|
||||||
|
*/
|
||||||
|
const localizedSubkeys = new Map();
|
||||||
for (const match of subkeys) {
|
for (const match of subkeys) {
|
||||||
const subkey = match.groups.key;
|
const subkey = match.groups.key;
|
||||||
localized =
|
if (localizedSubkeys.has(subkey)) continue;
|
||||||
localized.slice(0, match.index)
|
localizedSubkeys.set(subkey, localizer(subkey, args, depth + 1));
|
||||||
+ localizer(subkey, args, depth + 1)
|
|
||||||
+ localized.slice(match.index + subkey.length + 1)
|
|
||||||
};
|
};
|
||||||
return localized;
|
|
||||||
|
return localized.replace(
|
||||||
|
localizerConfig.subKeyPattern,
|
||||||
|
(_fullMatch, subkey) => {
|
||||||
|
return localizedSubkeys.get(subkey);
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
%flex-col {
|
%flex-col {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include utils.tab("details") {
|
@include utils.tab("details") {
|
||||||
|
|
@ -56,6 +57,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@include utils.tab("effects") {
|
||||||
|
@extend %flex-col;
|
||||||
|
}
|
||||||
|
|
||||||
@include utils.tab("settings") {
|
@include utils.tab("settings") {
|
||||||
@extend %flex-col;
|
@extend %flex-col;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
name="system.stats.{{stat.key}}"
|
name="system.stats.{{stat.key}}"
|
||||||
class="e-2dp dice-select"
|
class="e-2dp dice-select"
|
||||||
>
|
>
|
||||||
{{{dd-options stat.value stat.dieOptions}}}
|
{{{dd-options stat.original stat.dieOptions}}}
|
||||||
</select>
|
</select>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
class="e-2dp skill__training"
|
class="e-2dp skill__training"
|
||||||
>
|
>
|
||||||
{{{dd-options
|
{{{dd-options
|
||||||
skill.value
|
skill.original
|
||||||
@root.config.trainingLevels
|
@root.config.trainingLevels
|
||||||
localize=true
|
localize=true
|
||||||
}}}
|
}}}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,34 @@
|
||||||
<div class="tab" data-group="page" data-tab="effects">
|
<div class="tab" data-group="page" data-tab="effects">
|
||||||
Effects Tab
|
{{#each effects as | effect |}}
|
||||||
|
<div class="effect panel" data-embedded-id="{{effect.uuid}}">
|
||||||
|
<div class="effect__name">
|
||||||
|
{{effect.name}}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ifThen effect.disabled "Disabled" "Enabled"}}
|
||||||
|
</div>
|
||||||
|
{{!-- TODO: For some reason this embedded update logic was failing
|
||||||
|
<label
|
||||||
|
class="effect__name"
|
||||||
|
for="{{effect.uuid}}-toggle"
|
||||||
|
>
|
||||||
|
{{ effect.name }}
|
||||||
|
</label>
|
||||||
|
<div class="effect__active">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
{{checked effect.enabled}}
|
||||||
|
id="{{effect.uuid}}-toggle"
|
||||||
|
data-embedded-id="{{effect.uuid}}"
|
||||||
|
data-embedded-update="disabled"
|
||||||
|
data-embedded-update-on="change"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
--}}
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
<button type="button" class="create-ae">
|
||||||
|
<dd-icon name="ui/plus" var:fill="currentColor"></dd-icon>
|
||||||
|
Create Effect
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue