mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-07 14:36:13 +01:00
Merged with main
This commit is contained in:
commit
2123ae1965
177 changed files with 2677 additions and 657 deletions
143
module/applications/dialogs/CompendiumBrowserSettings.mjs
Normal file
143
module/applications/dialogs/CompendiumBrowserSettings.mjs
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
|
||||
|
||||
export default class CompendiumBrowserSettings extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.browserSettings = game.settings
|
||||
.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings)
|
||||
.toObject();
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'div',
|
||||
classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'compendium-brower-settings'],
|
||||
window: {
|
||||
icon: 'fa-solid fa-book',
|
||||
title: 'DAGGERHEART.APPLICATIONS.CompendiumBrowserSettings.title'
|
||||
},
|
||||
position: {
|
||||
width: 500
|
||||
},
|
||||
actions: {
|
||||
toggleSource: CompendiumBrowserSettings.#toggleSource,
|
||||
finish: CompendiumBrowserSettings.#finish
|
||||
}
|
||||
};
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
packs: {
|
||||
id: 'packs',
|
||||
template: 'systems/daggerheart/templates/dialogs/compendiumBrowserSettingsDialog/packs.hbs'
|
||||
},
|
||||
footer: { template: 'systems/daggerheart/templates/dialogs/compendiumBrowserSettingsDialog/footer.hbs' }
|
||||
};
|
||||
|
||||
static #browserPackTypes = ['Actor', 'Item'];
|
||||
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
for (const element of htmlElement.querySelectorAll('.pack-checkbox'))
|
||||
element.addEventListener('change', this.toggleTypedPack.bind(this));
|
||||
}
|
||||
|
||||
/**@inheritdoc */
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
|
||||
const excludedSourceData = this.browserSettings.excludedSources;
|
||||
const excludedPackData = this.browserSettings.excludedPacks;
|
||||
context.typePackCollections = game.packs.reduce((acc, pack) => {
|
||||
const { type, label, packageType, packageName: basePackageName, id } = pack.metadata;
|
||||
if (!CompendiumBrowserSettings.#browserPackTypes.includes(type)) return acc;
|
||||
|
||||
const isWorldPack = packageType === 'world';
|
||||
const packageName = isWorldPack ? 'world' : basePackageName;
|
||||
const sourceChecked =
|
||||
!excludedSourceData[packageName] ||
|
||||
!excludedSourceData[packageName].excludedDocumentTypes.includes(type);
|
||||
|
||||
const sourceLabel =
|
||||
game.modules.get(packageName)?.title ??
|
||||
(isWorldPack
|
||||
? game.i18n.localize('DAGGERHEART.APPLICATIONS.CompendiumBrowserSettings.worldCompendiums')
|
||||
: game.system.title);
|
||||
if (!acc[type]) acc[type] = { label: game.i18n.localize(`DOCUMENT.${type}s`), sources: {} };
|
||||
if (!acc[type].sources[packageName])
|
||||
acc[type].sources[packageName] = { label: sourceLabel, checked: sourceChecked, packs: [] };
|
||||
|
||||
const checked = !excludedPackData[id] || !excludedPackData[id].excludedDocumentTypes.includes(type);
|
||||
|
||||
acc[type].sources[packageName].packs.push({
|
||||
pack: id,
|
||||
type,
|
||||
label: id === game.system.id ? game.system.title : game.i18n.localize(label),
|
||||
checked: checked
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static #toggleSource(event, button) {
|
||||
event.stopPropagation();
|
||||
|
||||
const { type, source } = button.dataset;
|
||||
const currentlyExcluded = this.browserSettings.excludedSources[source]
|
||||
? this.browserSettings.excludedSources[source].excludedDocumentTypes.includes(type)
|
||||
: false;
|
||||
|
||||
if (!this.browserSettings.excludedSources[source])
|
||||
this.browserSettings.excludedSources[source] = { excludedDocumentTypes: [] };
|
||||
this.browserSettings.excludedSources[source].excludedDocumentTypes = currentlyExcluded
|
||||
? this.browserSettings.excludedSources[source].excludedDocumentTypes.filter(x => x !== type)
|
||||
: [...(this.browserSettings.excludedSources[source]?.excludedDocumentTypes ?? []), type];
|
||||
|
||||
const toggleIcon = button.querySelector('a > i');
|
||||
toggleIcon.classList.toggle('fa-toggle-off');
|
||||
toggleIcon.classList.toggle('fa-toggle-on');
|
||||
button.closest('.source-container').querySelector('.checks-container').classList.toggle('collapsed');
|
||||
}
|
||||
|
||||
toggleTypedPack(event) {
|
||||
event.stopPropagation();
|
||||
|
||||
const { type, pack } = event.target.dataset;
|
||||
const currentlyExcluded = this.browserSettings.excludedPacks[pack]
|
||||
? this.browserSettings.excludedPacks[pack].excludedDocumentTypes.includes(type)
|
||||
: false;
|
||||
|
||||
if (!this.browserSettings.excludedPacks[pack])
|
||||
this.browserSettings.excludedPacks[pack] = { excludedDocumentTypes: [] };
|
||||
this.browserSettings.excludedPacks[pack].excludedDocumentTypes = currentlyExcluded
|
||||
? this.browserSettings.excludedPacks[pack].excludedDocumentTypes.filter(x => x !== type)
|
||||
: [...(this.browserSettings.excludedPacks[pack]?.excludedDocumentTypes ?? []), type];
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async #finish() {
|
||||
const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings);
|
||||
await settings.updateSource(this.browserSettings);
|
||||
await game.settings.set(
|
||||
CONFIG.DH.id,
|
||||
CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings,
|
||||
settings.toObject()
|
||||
);
|
||||
|
||||
this.updated = true;
|
||||
this.close();
|
||||
}
|
||||
|
||||
static async configure() {
|
||||
return new Promise(resolve => {
|
||||
const app = new this();
|
||||
app.addEventListener('close', () => resolve(app.updated), { once: true });
|
||||
app.render({ force: true });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -16,3 +16,4 @@ export { default as ActionSelectionDialog } from './actionSelectionDialog.mjs';
|
|||
export { default as GroupRollDialog } from './group-roll-dialog.mjs';
|
||||
export { default as TagTeamDialog } from './tagTeamDialog.mjs';
|
||||
export { default as RiskItAllDialog } from './riskItAllDialog.mjs';
|
||||
export { default as CompendiumBrowserSettingsDialog } from './CompendiumBrowserSettings.mjs';
|
||||
|
|
|
|||
|
|
@ -54,7 +54,11 @@ export default class AttributionDialog extends HandlebarsApplicationMixin(Applic
|
|||
const after = label.slice(matchIndex + search.length, label.length);
|
||||
|
||||
const element = document.createElement('li');
|
||||
element.innerHTML = `${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`;
|
||||
element.innerHTML =
|
||||
`${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`.replaceAll(
|
||||
' ',
|
||||
' '
|
||||
);
|
||||
if (item.hint) {
|
||||
element.dataset.tooltip = game.i18n.localize(item.hint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,9 +165,10 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
}
|
||||
if (rest.hasOwnProperty('trait')) {
|
||||
this.config.roll.trait = rest.trait;
|
||||
this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||
ability: game.i18n.localize(abilities[this.config.roll.trait]?.label)
|
||||
});
|
||||
if (!this.config.source.item)
|
||||
this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||
ability: game.i18n.localize(abilities[this.config.roll.trait]?.label)
|
||||
});
|
||||
}
|
||||
this.config.extraFormula = rest.extraFormula;
|
||||
this.render();
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
|
|||
return context;
|
||||
}
|
||||
|
||||
async handleAvoidDeath() {
|
||||
async handleAvoidDeath(useAutomation) {
|
||||
const target = this.actor.uuid;
|
||||
const config = await enrichedFateRoll({
|
||||
target,
|
||||
|
|
@ -53,6 +53,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
|
|||
});
|
||||
|
||||
if (!config.roll.fate) return;
|
||||
if (!useAutomation) return '';
|
||||
|
||||
let returnMessage = game.i18n.localize('DAGGERHEART.UI.Chat.deathMove.avoidScar');
|
||||
if (config.roll.fate.value <= this.actor.system.levelData.level.current) {
|
||||
|
|
@ -75,7 +76,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
|
|||
return returnMessage;
|
||||
}
|
||||
|
||||
async handleRiskItAll() {
|
||||
async handleRiskItAll(useAutomation) {
|
||||
const config = await enrichedDualityRoll({
|
||||
reaction: true,
|
||||
traitValue: null,
|
||||
|
|
@ -90,6 +91,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
|
|||
});
|
||||
|
||||
if (!config.roll.result) return;
|
||||
if (!useAutomation) return '';
|
||||
|
||||
const clearAllStressAndHitpointsUpdates = [
|
||||
{ key: 'hitPoints', clear: true },
|
||||
|
|
@ -128,7 +130,9 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
|
|||
return chatMessage;
|
||||
}
|
||||
|
||||
async handleBlazeOfGlory() {
|
||||
async handleBlazeOfGlory(useAutomation) {
|
||||
if (!useAutomation) return '';
|
||||
|
||||
this.actor.createEmbeddedDocuments('ActiveEffect', [
|
||||
{
|
||||
name: game.i18n.localize('DAGGERHEART.CONFIG.DeathMoves.blazeOfGlory.name'),
|
||||
|
|
@ -160,19 +164,23 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
|
|||
|
||||
let result = '';
|
||||
|
||||
const deathMoveAutomation = game.settings.get(
|
||||
CONFIG.DH.id,
|
||||
CONFIG.DH.SETTINGS.gameSettings.Automation
|
||||
).deathMoveAutomation;
|
||||
if (CONFIG.DH.GENERAL.deathMoves.blazeOfGlory === this.selectedMove) {
|
||||
result = await this.handleBlazeOfGlory();
|
||||
result = await this.handleBlazeOfGlory(deathMoveAutomation.blazeOfGlory);
|
||||
}
|
||||
|
||||
if (CONFIG.DH.GENERAL.deathMoves.avoidDeath === this.selectedMove) {
|
||||
result = await this.handleAvoidDeath();
|
||||
result = await this.handleAvoidDeath(deathMoveAutomation.avoidDeath);
|
||||
}
|
||||
|
||||
if (CONFIG.DH.GENERAL.deathMoves.riskItAll === this.selectedMove) {
|
||||
result = await this.handleRiskItAll();
|
||||
result = await this.handleRiskItAll(deathMoveAutomation.riskItAll);
|
||||
}
|
||||
|
||||
if (!result) return;
|
||||
if (result === undefined) return;
|
||||
|
||||
const autoExpandDescription = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance)
|
||||
.expandRollMessage?.desc;
|
||||
|
|
@ -192,7 +200,6 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV
|
|||
description: game.i18n.localize(this.selectedMove.description),
|
||||
result: result,
|
||||
open: autoExpandDescription ? 'open' : '',
|
||||
chevron: autoExpandDescription ? 'fa-chevron-up' : 'fa-chevron-down',
|
||||
showRiskItAllButton: this.showRiskItAllButton,
|
||||
riskItAllButtonLabel: this.riskItAllButtonLabel,
|
||||
riskItAllHope: this.riskItAllHope
|
||||
|
|
|
|||
|
|
@ -196,6 +196,9 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
|||
.filter(x => x.testUserPermission(game.user, 'LIMITED'))
|
||||
.filter(x => x.uuid !== this.actor.uuid);
|
||||
|
||||
const autoExpandDescription = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance)
|
||||
.expandRollMessage?.desc;
|
||||
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
const msg = {
|
||||
user: game.user.id,
|
||||
|
|
@ -216,7 +219,8 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
|||
actor: { name: this.actor.name, img: this.actor.img },
|
||||
moves: moves,
|
||||
characters: characters,
|
||||
selfId: this.actor.uuid
|
||||
selfId: this.actor.uuid,
|
||||
open: autoExpandDescription ? 'open' : ''
|
||||
}
|
||||
),
|
||||
flags: {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,11 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
|
|||
element.appendChild(img);
|
||||
|
||||
const label = document.createElement('span');
|
||||
label.innerHTML = `${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`;
|
||||
label.innerHTML =
|
||||
`${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`.replaceAll(
|
||||
' ',
|
||||
' '
|
||||
);
|
||||
element.appendChild(label);
|
||||
|
||||
return element;
|
||||
|
|
@ -119,7 +123,11 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
|
|||
element.appendChild(img);
|
||||
|
||||
const label = document.createElement('span');
|
||||
label.innerHTML = `${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`;
|
||||
label.innerHTML =
|
||||
`${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`.replaceAll(
|
||||
' ',
|
||||
' '
|
||||
);
|
||||
element.appendChild(label);
|
||||
|
||||
return element;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,11 @@ export default class DhSceneConfigSettings extends foundry.applications.sheets.S
|
|||
|
||||
/** @override */
|
||||
async _processSubmitData(event, form, submitData, options) {
|
||||
submitData.flags.daggerheart = this.daggerheartFlag.toObject();
|
||||
if (!submitData.flags) submitData.flags = {};
|
||||
submitData.flags.daggerheart = foundry.utils.mergeObject(
|
||||
this.daggerheartFlag.toObject(),
|
||||
submitData.flags.daggerheart
|
||||
);
|
||||
submitData.flags.daggerheart.sceneEnvironments = submitData.flags.daggerheart.sceneEnvironments.filter(x =>
|
||||
foundry.utils.fromUuidSync(x)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export default class DhAutomationSettings extends HandlebarsApplicationMixin(App
|
|||
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||
header: { template: 'systems/daggerheart/templates/settings/automation-settings/header.hbs' },
|
||||
general: { template: 'systems/daggerheart/templates/settings/automation-settings/general.hbs' },
|
||||
rules: { template: 'systems/daggerheart/templates/settings/automation-settings/rules.hbs' },
|
||||
rules: { template: 'systems/daggerheart/templates/settings/automation-settings/deathMoves.hbs' },
|
||||
roll: { template: 'systems/daggerheart/templates/settings/automation-settings/roll.hbs' },
|
||||
footer: { template: 'systems/daggerheart/templates/settings/automation-settings/footer.hbs' }
|
||||
};
|
||||
|
|
@ -42,7 +42,7 @@ export default class DhAutomationSettings extends HandlebarsApplicationMixin(App
|
|||
/** @inheritdoc */
|
||||
static TABS = {
|
||||
main: {
|
||||
tabs: [{ id: 'general' }, { id: 'rules' }, { id: 'roll' }],
|
||||
tabs: [{ id: 'general' }, { id: 'deathMoves' }, { id: 'roll' }],
|
||||
initial: 'general',
|
||||
labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,12 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
? { id: this.selected.adversaryType, ...this.settings.adversaryTypes[this.selected.adversaryType] }
|
||||
: null;
|
||||
break;
|
||||
case 'downtime':
|
||||
context.restOptions = {
|
||||
shortRest: CONFIG.DH.GENERAL.defaultRestOptions.shortRest(),
|
||||
longRest: CONFIG.DH.GENERAL.defaultRestOptions.longRest()
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
return context;
|
||||
|
|
@ -165,7 +171,8 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
name: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.newDowntimeMove'),
|
||||
img: 'icons/magic/life/cross-worn-green.webp',
|
||||
description: '',
|
||||
actions: []
|
||||
actions: [],
|
||||
effects: []
|
||||
}
|
||||
});
|
||||
} else if (['armorFeatures', 'weaponFeatures'].includes(type)) {
|
||||
|
|
@ -224,6 +231,15 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
}
|
||||
|
||||
static async removeItem(_, target) {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.localize(`DAGGERHEART.SETTINGS.Homebrew.deleteItemTitle`)
|
||||
},
|
||||
content: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.deleteItemText')
|
||||
});
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
const { type, id } = target.dataset;
|
||||
const isDowntime = ['shortRest', 'longRest'].includes(type);
|
||||
const path = isDowntime ? `restMoves.${type}.moves` : `itemFeatures.${type}`;
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
|||
const index = Number.parseInt(button.dataset.index);
|
||||
const toggle = (element, codeMirror) => {
|
||||
codeMirror.classList.toggle('revealed');
|
||||
const button = element.querySelector('a > i');
|
||||
const button = element.querySelector('.expand-trigger > i');
|
||||
button.classList.toggle('fa-angle-up');
|
||||
button.classList.toggle('fa-angle-down');
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,20 +4,60 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac
|
|||
constructor(options) {
|
||||
super(options);
|
||||
|
||||
const ignoredActorKeys = ['config', 'DhEnvironment'];
|
||||
this.changeChoices = Object.keys(game.system.api.models.actors).reduce((acc, key) => {
|
||||
if (!ignoredActorKeys.includes(key)) {
|
||||
const model = game.system.api.models.actors[key];
|
||||
const attributes = CONFIG.Token.documentClass.getTrackedAttributes(model);
|
||||
// As per DHToken._getTrackedAttributesFromSchema, attributes.bar have a max version as well.
|
||||
const maxAttributes = attributes.bar.map(x => [...x, 'max']);
|
||||
attributes.value.push(...maxAttributes);
|
||||
const group = game.i18n.localize(model.metadata.label);
|
||||
const choices = CONFIG.Token.documentClass
|
||||
.getTrackedAttributeChoices(attributes, model)
|
||||
.map(x => ({ ...x, group: group }));
|
||||
acc.push(...choices);
|
||||
const ignoredActorKeys = ['config', 'DhEnvironment', 'DhParty'];
|
||||
|
||||
const getAllLeaves = (root, group, parentPath = '') => {
|
||||
const leaves = [];
|
||||
const rootKey = `${parentPath ? `${parentPath}.` : ''}${root.name}`;
|
||||
for (const field of Object.values(root.fields)) {
|
||||
if (field instanceof foundry.data.fields.SchemaField)
|
||||
leaves.push(...getAllLeaves(field, group, rootKey));
|
||||
else
|
||||
leaves.push({
|
||||
value: `${rootKey}.${field.name}`,
|
||||
label: game.i18n.localize(field.label),
|
||||
hint: game.i18n.localize(field.hint),
|
||||
group
|
||||
});
|
||||
}
|
||||
|
||||
return leaves;
|
||||
};
|
||||
this.changeChoices = Object.keys(game.system.api.models.actors).reduce((acc, key) => {
|
||||
if (ignoredActorKeys.includes(key)) return acc;
|
||||
|
||||
const model = game.system.api.models.actors[key];
|
||||
const group = game.i18n.localize(model.metadata.label);
|
||||
const attributes = CONFIG.Token.documentClass.getTrackedAttributes(model.metadata.type);
|
||||
|
||||
const getTranslations = path => {
|
||||
if (path === 'resources.hope.max')
|
||||
return {
|
||||
label: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.FIELDS.maxHope.label'),
|
||||
hint: ''
|
||||
};
|
||||
|
||||
const field = model.schema.getField(path);
|
||||
return {
|
||||
label: field ? game.i18n.localize(field.label) : path,
|
||||
hint: field ? game.i18n.localize(field.hint) : ''
|
||||
};
|
||||
};
|
||||
|
||||
const bars = attributes.bar.flatMap(x => {
|
||||
const joined = `${x.join('.')}.max`;
|
||||
return { value: joined, ...getTranslations(joined), group };
|
||||
});
|
||||
const values = attributes.value.flatMap(x => {
|
||||
const joined = x.join('.');
|
||||
return { value: joined, ...getTranslations(joined), group };
|
||||
});
|
||||
|
||||
const bonuses = getAllLeaves(model.schema.fields.bonuses, group);
|
||||
const rules = getAllLeaves(model.schema.fields.rules, group);
|
||||
|
||||
acc.push(...bars, ...values, ...rules, ...bonuses);
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
|
@ -68,14 +108,18 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac
|
|||
},
|
||||
render: function (item, search) {
|
||||
const label = game.i18n.localize(item.label);
|
||||
const matchIndex = label.toLowerCase().indexOf(search);
|
||||
const matchIndex = label.toLowerCase().indexOf(search.toLowerCase());
|
||||
|
||||
const beforeText = label.slice(0, matchIndex);
|
||||
const matchText = label.slice(matchIndex, matchIndex + search.length);
|
||||
const after = label.slice(matchIndex + search.length, label.length);
|
||||
|
||||
const element = document.createElement('li');
|
||||
element.innerHTML = `${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`;
|
||||
element.innerHTML =
|
||||
`${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`.replaceAll(
|
||||
' ',
|
||||
' '
|
||||
);
|
||||
if (item.hint) {
|
||||
element.dataset.tooltip = game.i18n.localize(item.hint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,11 @@ export default class SettingActiveEffectConfig extends HandlebarsApplicationMixi
|
|||
const after = label.slice(matchIndex + search.length, label.length);
|
||||
|
||||
const element = document.createElement('li');
|
||||
element.innerHTML = `${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`;
|
||||
element.innerHTML =
|
||||
`${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`.replaceAll(
|
||||
' ',
|
||||
' '
|
||||
);
|
||||
if (item.hint) {
|
||||
element.dataset.tooltip = game.i18n.localize(item.hint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -431,18 +431,18 @@ export default function DHApplicationMixin(Base) {
|
|||
{
|
||||
name: 'disableEffect',
|
||||
icon: 'fa-solid fa-lightbulb',
|
||||
condition: target => {
|
||||
const doc = getDocFromElementSync(target);
|
||||
return doc && !doc.disabled;
|
||||
condition: element => {
|
||||
const target = element.closest('[data-item-uuid]');
|
||||
return !target.dataset.disabled && target.dataset.itemType !== 'beastform';
|
||||
},
|
||||
callback: async target => (await getDocFromElement(target)).update({ disabled: true })
|
||||
},
|
||||
{
|
||||
name: 'enableEffect',
|
||||
icon: 'fa-regular fa-lightbulb',
|
||||
condition: target => {
|
||||
const doc = getDocFromElementSync(target);
|
||||
return doc && doc.disabled;
|
||||
condition: element => {
|
||||
const target = element.closest('[data-item-uuid]');
|
||||
return target.dataset.disabled && target.dataset.itemType !== 'beastform';
|
||||
},
|
||||
callback: async target => (await getDocFromElement(target)).update({ disabled: false })
|
||||
}
|
||||
|
|
@ -570,6 +570,10 @@ export default function DHApplicationMixin(Base) {
|
|||
options.push({
|
||||
name: 'CONTROLS.CommonDelete',
|
||||
icon: 'fa-solid fa-trash',
|
||||
condition: element => {
|
||||
const target = element.closest('[data-item-uuid]');
|
||||
return target.dataset.itemType !== 'beastform';
|
||||
},
|
||||
callback: async (target, event) => {
|
||||
const doc = await getDocFromElement(target);
|
||||
if (event.shiftKey) return doc.delete();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
export default function ItemAttachmentSheet(Base) {
|
||||
return class extends Base {
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
dragDrop: [
|
||||
...(super.DEFAULT_OPTIONS.dragDrop || []),
|
||||
{ dragSelector: null, dropSelector: '.attachments-section' }
|
||||
|
|
|
|||
|
|
@ -43,4 +43,54 @@ export default class DhActorDirectory extends foundry.applications.sidebar.tabs.
|
|||
event.dataTransfer.setDragImage(preview, w / 2, h / 2);
|
||||
}
|
||||
}
|
||||
|
||||
_getEntryContextOptions() {
|
||||
const options = super._getEntryContextOptions();
|
||||
options.push({
|
||||
name: 'DAGGERHEART.UI.Sidebar.actorDirectory.duplicateToNewTier',
|
||||
icon: `<i class="fa-solid fa-arrow-trend-up" inert></i>`,
|
||||
condition: li => {
|
||||
const actor = game.actors.get(li.dataset.entryId);
|
||||
return actor?.type === 'adversary' && actor.system.type !== 'social';
|
||||
},
|
||||
callback: async li => {
|
||||
const actor = game.actors.get(li.dataset.entryId);
|
||||
if (!actor) throw new Error('Unexpected missing actor');
|
||||
|
||||
const tiers = [1, 2, 3, 4].filter(t => t !== actor.system.tier);
|
||||
const content = document.createElement('div');
|
||||
const select = document.createElement('select');
|
||||
select.name = 'tier';
|
||||
select.append(
|
||||
...tiers.map(t => {
|
||||
const option = document.createElement('option');
|
||||
option.value = t;
|
||||
option.textContent = game.i18n.localize(`DAGGERHEART.GENERAL.Tiers.${t}`);
|
||||
return option;
|
||||
})
|
||||
);
|
||||
content.append(select);
|
||||
|
||||
const tier = await foundry.applications.api.Dialog.input({
|
||||
classes: ['dh-style', 'dialog'],
|
||||
window: { title: 'DAGGERHEART.UI.Sidebar.actorDirectory.pickTierTitle' },
|
||||
content,
|
||||
ok: {
|
||||
label: 'Create Adversary',
|
||||
callback: (event, button, dialog) => Number(button.form.elements.tier.value)
|
||||
}
|
||||
});
|
||||
|
||||
if (tier === actor.system.tier) {
|
||||
ui.notifications.warn('This actor is already at this tier');
|
||||
} else if (tier) {
|
||||
const source = actor.system.adjustForTier(tier);
|
||||
await Actor.create(source);
|
||||
ui.notifications.info(`Tier ${tier} ${actor.name} created`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
|||
position: {
|
||||
width: 222,
|
||||
height: 222
|
||||
// top: "200px",
|
||||
// left: "120px"
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -66,7 +64,7 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
|||
max = this.maxFear,
|
||||
percent = (current / max) * 100,
|
||||
isGM = game.user.isGM;
|
||||
// Return the data for rendering
|
||||
|
||||
return { display, current, max, percent, isGM };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
/**
|
||||
|
|
@ -17,6 +19,15 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
this.config = CONFIG.DH.ITEMBROWSER.compendiumConfig;
|
||||
this.presets = {};
|
||||
this.compendiumBrowserTypeKey = 'compendiumBrowserDefault';
|
||||
|
||||
this.setupHooks = Hooks.on(socketEvent.Refresh, ({ refreshType }) => {
|
||||
if (refreshType === RefreshType.CompendiumBrowser) {
|
||||
if (this.rendered) {
|
||||
this.render();
|
||||
this.loadItems();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
|
|
@ -35,7 +46,8 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
selectFolder: this.selectFolder,
|
||||
expandContent: this.expandContent,
|
||||
resetFilters: this.resetFilters,
|
||||
sortList: this.sortList
|
||||
sortList: this.sortList,
|
||||
openSettings: this.openSettings
|
||||
},
|
||||
position: {
|
||||
left: 100,
|
||||
|
|
@ -157,6 +169,8 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
context.formatChoices = this.formatChoices;
|
||||
context.items = this.items;
|
||||
context.presets = this.presets;
|
||||
context.isGM = game.user.isGM;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
@ -214,6 +228,10 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
loadItems() {
|
||||
let loadTimeout = this.toggleLoader(true);
|
||||
|
||||
const browserSettings = game.settings.get(
|
||||
CONFIG.DH.id,
|
||||
CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings
|
||||
);
|
||||
const promises = [];
|
||||
|
||||
game.packs.forEach(pack => {
|
||||
|
|
@ -227,7 +245,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
|
||||
Promise.all(promises).then(async result => {
|
||||
this.items = ItemBrowser.sortBy(
|
||||
result.flatMap(r => r),
|
||||
result.flatMap(r => r).filter(r => !browserSettings.isEntryExcluded.bind(browserSettings)(r)),
|
||||
'name'
|
||||
);
|
||||
|
||||
|
|
@ -512,6 +530,22 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
itemListContainer.replaceChildren(...newOrder);
|
||||
}
|
||||
|
||||
static async openSettings() {
|
||||
const settingsUpdated = await game.system.api.applications.dialogs.CompendiumBrowserSettingsDialog.configure();
|
||||
if (settingsUpdated) {
|
||||
if (this.rendered) {
|
||||
this.render();
|
||||
this.loadItems();
|
||||
}
|
||||
await game.socket.emit(`system.${CONFIG.DH.id}`, {
|
||||
action: socketEvent.Refresh,
|
||||
data: {
|
||||
refreshType: RefreshType.CompendiumBrowser
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_createDragProcess() {
|
||||
new foundry.applications.ux.DragDrop.implementation({
|
||||
dragSelector: '.item-container',
|
||||
|
|
@ -571,4 +605,9 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
headerActions.append(button);
|
||||
}
|
||||
}
|
||||
|
||||
async close(options = {}) {
|
||||
Hooks.off(socketEvent.Refresh, this.setupHooks);
|
||||
await super.close(options);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,8 @@ export default class DhSceneNavigation extends foundry.applications.ui.SceneNavi
|
|||
if (scene.flags.daggerheart.sceneEnvironments[0] !== environment.uuid) {
|
||||
const newEnvironments = scene.flags.daggerheart.sceneEnvironments;
|
||||
const newFirst = newEnvironments.splice(
|
||||
newEnvironments.findIndex(x => x === environment.uuid)
|
||||
newEnvironments.findIndex(x => x === environment.uuid),
|
||||
1
|
||||
)[0];
|
||||
newEnvironments.unshift(newFirst);
|
||||
emitAsGM(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue