mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-07 14:36:13 +01:00
Merge branch 'main' into release
This commit is contained in:
commit
35bceac520
58 changed files with 1075 additions and 286 deletions
3
.editorconfig
Normal file
3
.editorconfig
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
[*]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = spaces
|
||||||
|
|
@ -242,6 +242,38 @@ Hooks.on('setup', () => {
|
||||||
systemEffect: true
|
systemEffect: true
|
||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const actorCommon = {
|
||||||
|
bar: ['resources.stress'],
|
||||||
|
value: []
|
||||||
|
};
|
||||||
|
const damageThresholds = ['damageThresholds.major', 'damageThresholds.severe'];
|
||||||
|
const traits = Object.keys(game.system.api.data.actors.DhCharacter.schema.fields.traits.fields).map(
|
||||||
|
trait => `traits.${trait}.value`
|
||||||
|
);
|
||||||
|
CONFIG.Actor.trackableAttributes = {
|
||||||
|
character: {
|
||||||
|
bar: [...actorCommon.bar, 'resources.hitPoints', 'resources.hope'],
|
||||||
|
value: [
|
||||||
|
...actorCommon.value,
|
||||||
|
...traits,
|
||||||
|
...damageThresholds,
|
||||||
|
'proficiency',
|
||||||
|
'evasion',
|
||||||
|
'armorScore',
|
||||||
|
'scars',
|
||||||
|
'levelData.level.current'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
adversary: {
|
||||||
|
bar: [...actorCommon.bar, 'resources.hitPoints'],
|
||||||
|
value: [...actorCommon.value, ...damageThresholds, 'criticalThreshold']
|
||||||
|
},
|
||||||
|
companion: {
|
||||||
|
bar: [...actorCommon.bar],
|
||||||
|
value: [...actorCommon.value, 'evasion', 'levelData.level.current']
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
Hooks.on('ready', async () => {
|
Hooks.on('ready', async () => {
|
||||||
|
|
|
||||||
72
lang/en.json
72
lang/en.json
|
|
@ -192,6 +192,9 @@
|
||||||
},
|
},
|
||||||
"age": "Age",
|
"age": "Age",
|
||||||
"backgroundQuestions": "Backgrounds",
|
"backgroundQuestions": "Backgrounds",
|
||||||
|
"burden": {
|
||||||
|
"ignore": { "label": "Burden: Ignore", "hint": "Ignore burden rules" }
|
||||||
|
},
|
||||||
"companionFeatures": "Companion Features",
|
"companionFeatures": "Companion Features",
|
||||||
"connections": "Connections",
|
"connections": "Connections",
|
||||||
"contextMenu": {
|
"contextMenu": {
|
||||||
|
|
@ -214,6 +217,12 @@
|
||||||
"maxEvasionBonus": "Max Evasion Increase",
|
"maxEvasionBonus": "Max Evasion Increase",
|
||||||
"maxHPBonus": "Max HP Increase",
|
"maxHPBonus": "Max HP Increase",
|
||||||
"pronouns": "Pronouns",
|
"pronouns": "Pronouns",
|
||||||
|
"roll": {
|
||||||
|
"guaranteedCritical": {
|
||||||
|
"label": "Guaranteed Critical",
|
||||||
|
"hint": "Set to 1 to always roll a critical"
|
||||||
|
}
|
||||||
|
},
|
||||||
"story": {
|
"story": {
|
||||||
"backgroundTitle": "Background",
|
"backgroundTitle": "Background",
|
||||||
"characteristics": "Characteristics",
|
"characteristics": "Characteristics",
|
||||||
|
|
@ -343,6 +352,11 @@
|
||||||
"requestSpotlight": "Request The Spotlight",
|
"requestSpotlight": "Request The Spotlight",
|
||||||
"openCountdowns": "Countdowns"
|
"openCountdowns": "Countdowns"
|
||||||
},
|
},
|
||||||
|
"CompendiumBrowserSettings": {
|
||||||
|
"title": "Enable Compendiums",
|
||||||
|
"enableSource": "Enable Source",
|
||||||
|
"disableSource": "Disable Source"
|
||||||
|
},
|
||||||
"ContextMenu": {
|
"ContextMenu": {
|
||||||
"disableEffect": "Disable Effect",
|
"disableEffect": "Disable Effect",
|
||||||
"enableEffect": "Enable Effect",
|
"enableEffect": "Enable Effect",
|
||||||
|
|
@ -446,6 +460,10 @@
|
||||||
"description": "Describe how you are preparing for the next day's adventure, then gain a Hope. If you choose to Prepare with one or more members of your party, you may each take two Hope.",
|
"description": "Describe how you are preparing for the next day's adventure, then gain a Hope. If you choose to Prepare with one or more members of your party, you may each take two Hope.",
|
||||||
"name": "Prepare"
|
"name": "Prepare"
|
||||||
},
|
},
|
||||||
|
"prepareWithFriends": {
|
||||||
|
"description": "Describe how you are preparing for the next day's adventure, then gain a Hope. If you choose to Prepare with one or more members of your party, you may each take two Hope.",
|
||||||
|
"name": "Prepare (with Friends)"
|
||||||
|
},
|
||||||
"repairArmor": {
|
"repairArmor": {
|
||||||
"description": "Describe how you spend time repairing your armor and clear all of its Armor Slots. You may also do this to an ally's armor instead.",
|
"description": "Describe how you spend time repairing your armor and clear all of its Armor Slots. You may also do this to an ally's armor instead.",
|
||||||
"name": "Repair Armor"
|
"name": "Repair Armor"
|
||||||
|
|
@ -477,6 +495,10 @@
|
||||||
"prepare": {
|
"prepare": {
|
||||||
"name": "Prepare",
|
"name": "Prepare",
|
||||||
"description": "Describe how you prepare yourself for the path ahead, then gain a Hope. If you choose to Prepare with one or more members of your party, you each gain 2 Hope."
|
"description": "Describe how you prepare yourself for the path ahead, then gain a Hope. If you choose to Prepare with one or more members of your party, you each gain 2 Hope."
|
||||||
|
},
|
||||||
|
"prepareWithFriends": {
|
||||||
|
"name": "Prepare (with Friends)",
|
||||||
|
"description": "Describe how you prepare yourself for the path ahead, then gain a Hope. If you choose to Prepare with one or more members of your party, you each gain 2 Hope."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"refreshable": {
|
"refreshable": {
|
||||||
|
|
@ -1840,6 +1862,16 @@
|
||||||
"singular": "Adversary",
|
"singular": "Adversary",
|
||||||
"plural": "Adversaries"
|
"plural": "Adversaries"
|
||||||
},
|
},
|
||||||
|
"Attack": {
|
||||||
|
"hpDamageMultiplier": {
|
||||||
|
"label": "HP Damage Multiplier",
|
||||||
|
"hint": "Multiply any damage you deal by this number"
|
||||||
|
},
|
||||||
|
"hpDamageTakenMultiplier": {
|
||||||
|
"label": "HP Damage Taken Multiplier",
|
||||||
|
"hint": "Multiply any damage dealt to you by this number"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Bonuses": {
|
"Bonuses": {
|
||||||
"rest": {
|
"rest": {
|
||||||
"downtimeAction": "Downtime Action",
|
"downtimeAction": "Downtime Action",
|
||||||
|
|
@ -2024,16 +2056,40 @@
|
||||||
"reaction": "Reaction Roll"
|
"reaction": "Reaction Roll"
|
||||||
},
|
},
|
||||||
"Rules": {
|
"Rules": {
|
||||||
|
"conditionImmunities": {
|
||||||
|
"hidden": "Condition Immunity: Hidden",
|
||||||
|
"restrained": "Condition Immunity: Restrained",
|
||||||
|
"vulnerable": "Condition Immunity: Vulnerable"
|
||||||
|
},
|
||||||
"damageReduction": {
|
"damageReduction": {
|
||||||
|
"disabledArmor": { "label": "Disabled Armorslots" },
|
||||||
"increasePerArmorMark": {
|
"increasePerArmorMark": {
|
||||||
"label": "Damage Reduction per Armor Slot",
|
"label": "Damage Reduction per Armor Slot",
|
||||||
"hint": "A used armor slot normally reduces damage by one step. This value increases the number of steps damage is reduced by."
|
"hint": "A used armor slot normally reduces damage by one step. This value increases the number of steps damage is reduced by."
|
||||||
},
|
},
|
||||||
|
"magical": {
|
||||||
|
"label": "Daamge Reduction: Only Magical",
|
||||||
|
"hint": "Armor can only be used to reduce magical damage"
|
||||||
|
},
|
||||||
"maxArmorMarkedBonus": "Max Armor Used",
|
"maxArmorMarkedBonus": "Max Armor Used",
|
||||||
"maxArmorMarkedStress": {
|
"maxArmorMarkedStress": {
|
||||||
"label": "Max Armor Used With Stress",
|
"label": "Max Armor Used With Stress",
|
||||||
"hint": "If this value is set you can use up to that much stress to spend additional Armor Marks beyond your normal maximum."
|
"hint": "If this value is set you can use up to that much stress to spend additional Armor Marks beyond your normal maximum."
|
||||||
},
|
},
|
||||||
|
"reduceSeverity": {
|
||||||
|
"magical": {
|
||||||
|
"label": "Reduce Damage Severity: Magical",
|
||||||
|
"hint": "Lowers any magical damage received by the set amount of severity degrees"
|
||||||
|
},
|
||||||
|
"physical": {
|
||||||
|
"label": "Reduce Damage Severity: Physical",
|
||||||
|
"hint": "Lowers any physical damage received by the set amount of severity degrees"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"physical": {
|
||||||
|
"label": "Damage Reduction: Only Physical",
|
||||||
|
"hint": "Armor can only be used to reduce physical damage"
|
||||||
|
},
|
||||||
"stress": {
|
"stress": {
|
||||||
"any": {
|
"any": {
|
||||||
"label": "Stress Damage Reduction: Any",
|
"label": "Stress Damage Reduction: Any",
|
||||||
|
|
@ -2051,6 +2107,12 @@
|
||||||
"label": "Stress Damage Reduction: Minor",
|
"label": "Stress Damage Reduction: Minor",
|
||||||
"hint": "The cost in stress you can pay to reduce minor damage to none."
|
"hint": "The cost in stress you can pay to reduce minor damage to none."
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"thresholdImmunities": {
|
||||||
|
"minor": {
|
||||||
|
"label": "Threshold Immunities: Minor",
|
||||||
|
"hint": "Automatically ignores minor damage"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"attack": {
|
"attack": {
|
||||||
|
|
@ -2120,7 +2182,9 @@
|
||||||
"configuration": "Configuration",
|
"configuration": "Configuration",
|
||||||
"base": "Base",
|
"base": "Base",
|
||||||
"triggers": "Triggers",
|
"triggers": "Triggers",
|
||||||
"deathMoves": "Deathmoves"
|
"deathMoves": "Deathmoves",
|
||||||
|
"sources": "Sources",
|
||||||
|
"packs": "Packs"
|
||||||
},
|
},
|
||||||
"Tiers": {
|
"Tiers": {
|
||||||
"singular": "Tier",
|
"singular": "Tier",
|
||||||
|
|
@ -2152,6 +2216,7 @@
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
"criticalSuccess": "Critical Success",
|
"criticalSuccess": "Critical Success",
|
||||||
"criticalShort": "Critical",
|
"criticalShort": "Critical",
|
||||||
|
"currentLevel": "Current Level",
|
||||||
"custom": "Custom",
|
"custom": "Custom",
|
||||||
"d20Roll": "D20 Roll",
|
"d20Roll": "D20 Roll",
|
||||||
"damage": "Damage",
|
"damage": "Damage",
|
||||||
|
|
@ -2555,6 +2620,8 @@
|
||||||
"resetMovesTitle": "Reset {type} Downtime Moves",
|
"resetMovesTitle": "Reset {type} Downtime Moves",
|
||||||
"resetItemFeaturesTitle": "Reset {type}",
|
"resetItemFeaturesTitle": "Reset {type}",
|
||||||
"resetMovesText": "Are you sure you want to reset?",
|
"resetMovesText": "Are you sure you want to reset?",
|
||||||
|
"deleteItemTitle": "Delete Homebrew Item",
|
||||||
|
"deleteItemText": "Are you sure you want to delete the item?",
|
||||||
"FIELDS": {
|
"FIELDS": {
|
||||||
"maxFear": { "label": "Max Fear" },
|
"maxFear": { "label": "Max Fear" },
|
||||||
"maxHope": { "label": "Max Hope" },
|
"maxHope": { "label": "Max Hope" },
|
||||||
|
|
@ -2786,6 +2853,7 @@
|
||||||
"ItemBrowser": {
|
"ItemBrowser": {
|
||||||
"title": "Daggerheart Compendium Browser",
|
"title": "Daggerheart Compendium Browser",
|
||||||
"hint": "Select a Folder in sidebar to start browsing through the compendium",
|
"hint": "Select a Folder in sidebar to start browsing through the compendium",
|
||||||
|
"browserSettings": "Browser Settings",
|
||||||
"searchPlaceholder": "Search...",
|
"searchPlaceholder": "Search...",
|
||||||
"columnName": "Name",
|
"columnName": "Name",
|
||||||
"tooltipFilters": "Filters",
|
"tooltipFilters": "Filters",
|
||||||
|
|
@ -2942,7 +3010,7 @@
|
||||||
"rulesOn": "Rules On",
|
"rulesOn": "Rules On",
|
||||||
"rulesOff": "Rules Off",
|
"rulesOff": "Rules Off",
|
||||||
"remainingUses": "Uses refresh on {type}",
|
"remainingUses": "Uses refresh on {type}",
|
||||||
"rightClickExtand": "Right-Click to extand",
|
"rightClickExtend": "Right-Click to extend",
|
||||||
"companionPartnerLevelBlock": "The companion needs an assigned partner to level up.",
|
"companionPartnerLevelBlock": "The companion needs an assigned partner to level up.",
|
||||||
"configureAttribution": "Configure Attribution",
|
"configureAttribution": "Configure Attribution",
|
||||||
"deleteItem": "Delete Item",
|
"deleteItem": "Delete Item",
|
||||||
|
|
|
||||||
136
module/applications/dialogs/CompendiumBrowserSettings.mjs
Normal file
136
module/applications/dialogs/CompendiumBrowserSettings.mjs
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
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, id } = pack.metadata;
|
||||||
|
if (packageType === 'world' || !CompendiumBrowserSettings.#browserPackTypes.includes(type)) return acc;
|
||||||
|
|
||||||
|
const sourceChecked =
|
||||||
|
!excludedSourceData[packageName] ||
|
||||||
|
!excludedSourceData[packageName].excludedDocumentTypes.includes(type);
|
||||||
|
const sourceLabel = game.modules.get(packageName)?.title ?? 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 GroupRollDialog } from './group-roll-dialog.mjs';
|
||||||
export { default as TagTeamDialog } from './tagTeamDialog.mjs';
|
export { default as TagTeamDialog } from './tagTeamDialog.mjs';
|
||||||
export { default as RiskItAllDialog } from './riskItAllDialog.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 after = label.slice(matchIndex + search.length, label.length);
|
||||||
|
|
||||||
const element = document.createElement('li');
|
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) {
|
if (item.hint) {
|
||||||
element.dataset.tooltip = game.i18n.localize(item.hint);
|
element.dataset.tooltip = game.i18n.localize(item.hint);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
}
|
}
|
||||||
if (rest.hasOwnProperty('trait')) {
|
if (rest.hasOwnProperty('trait')) {
|
||||||
this.config.roll.trait = rest.trait;
|
this.config.roll.trait = rest.trait;
|
||||||
|
if (!this.config.source.item)
|
||||||
this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||||
ability: game.i18n.localize(abilities[this.config.roll.trait]?.label)
|
ability: game.i18n.localize(abilities[this.config.roll.trait]?.label)
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,11 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
element.appendChild(img);
|
element.appendChild(img);
|
||||||
|
|
||||||
const label = document.createElement('span');
|
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);
|
element.appendChild(label);
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
|
|
@ -119,7 +123,11 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
element.appendChild(img);
|
element.appendChild(img);
|
||||||
|
|
||||||
const label = document.createElement('span');
|
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);
|
element.appendChild(label);
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,12 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
? { id: this.selected.adversaryType, ...this.settings.adversaryTypes[this.selected.adversaryType] }
|
? { id: this.selected.adversaryType, ...this.settings.adversaryTypes[this.selected.adversaryType] }
|
||||||
: null;
|
: null;
|
||||||
break;
|
break;
|
||||||
|
case 'downtime':
|
||||||
|
context.restOptions = {
|
||||||
|
shortRest: CONFIG.DH.GENERAL.defaultRestOptions.shortRest(),
|
||||||
|
longRest: CONFIG.DH.GENERAL.defaultRestOptions.longRest()
|
||||||
|
};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
|
|
@ -225,6 +231,15 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
}
|
}
|
||||||
|
|
||||||
static async removeItem(_, target) {
|
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 { type, id } = target.dataset;
|
||||||
const isDowntime = ['shortRest', 'longRest'].includes(type);
|
const isDowntime = ['shortRest', 'longRest'].includes(type);
|
||||||
const path = isDowntime ? `restMoves.${type}.moves` : `itemFeatures.${type}`;
|
const path = isDowntime ? `restMoves.${type}.moves` : `itemFeatures.${type}`;
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,55 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
|
|
||||||
const ignoredActorKeys = ['config', 'DhEnvironment'];
|
const ignoredActorKeys = ['config', 'DhEnvironment', 'DhParty'];
|
||||||
this.changeChoices = Object.keys(game.system.api.models.actors).reduce((acc, key) => {
|
|
||||||
if (!ignoredActorKeys.includes(key)) {
|
const getAllLeaves = (root, group, parentPath = '') => {
|
||||||
const model = game.system.api.models.actors[key];
|
const leaves = [];
|
||||||
const attributes = CONFIG.Token.documentClass.getTrackedAttributes(model);
|
const rootKey = `${parentPath ? `${parentPath}.` : ''}${root.name}`;
|
||||||
// As per DHToken._getTrackedAttributesFromSchema, attributes.bar have a max version as well.
|
for (const field of Object.values(root.fields)) {
|
||||||
const maxAttributes = attributes.bar.map(x => [...x, 'max']);
|
if (field instanceof foundry.data.fields.SchemaField)
|
||||||
attributes.value.push(...maxAttributes);
|
leaves.push(...getAllLeaves(field, group, rootKey));
|
||||||
const group = game.i18n.localize(model.metadata.label);
|
else
|
||||||
const choices = CONFIG.Token.documentClass
|
leaves.push({
|
||||||
.getTrackedAttributeChoices(attributes, model)
|
value: `${rootKey}.${field.name}`,
|
||||||
.map(x => ({ ...x, group: group }));
|
label: game.i18n.localize(field.label),
|
||||||
acc.push(...choices);
|
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 getLabel = path => {
|
||||||
|
const label = model.schema.getField(path)?.label;
|
||||||
|
return label ? game.i18n.localize(label) : path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const bars = attributes.bar.flatMap(x => {
|
||||||
|
const joined = `${x.join('.')}.max`;
|
||||||
|
const label =
|
||||||
|
joined === 'resources.hope.max'
|
||||||
|
? 'DAGGERHEART.SETTINGS.Homebrew.FIELDS.maxHope.label'
|
||||||
|
: getLabel(joined);
|
||||||
|
return { value: joined, label, group };
|
||||||
|
});
|
||||||
|
const values = attributes.value.flatMap(x => {
|
||||||
|
const joined = x.join('.');
|
||||||
|
return { value: joined, label: getLabel(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;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
@ -68,14 +103,18 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac
|
||||||
},
|
},
|
||||||
render: function (item, search) {
|
render: function (item, search) {
|
||||||
const label = game.i18n.localize(item.label);
|
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 beforeText = label.slice(0, matchIndex);
|
||||||
const matchText = label.slice(matchIndex, matchIndex + search.length);
|
const matchText = label.slice(matchIndex, matchIndex + search.length);
|
||||||
const after = label.slice(matchIndex + search.length, label.length);
|
const after = label.slice(matchIndex + search.length, label.length);
|
||||||
|
|
||||||
const element = document.createElement('li');
|
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) {
|
if (item.hint) {
|
||||||
element.dataset.tooltip = game.i18n.localize(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 after = label.slice(matchIndex + search.length, label.length);
|
||||||
|
|
||||||
const element = document.createElement('li');
|
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) {
|
if (item.hint) {
|
||||||
element.dataset.tooltip = game.i18n.localize(item.hint);
|
element.dataset.tooltip = game.i18n.localize(item.hint);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -433,7 +433,7 @@ export default function DHApplicationMixin(Base) {
|
||||||
icon: 'fa-solid fa-lightbulb',
|
icon: 'fa-solid fa-lightbulb',
|
||||||
condition: target => {
|
condition: target => {
|
||||||
const doc = getDocFromElementSync(target);
|
const doc = getDocFromElementSync(target);
|
||||||
return doc && !doc.disabled;
|
return doc && !doc.disabled && doc.type !== 'beastform';
|
||||||
},
|
},
|
||||||
callback: async target => (await getDocFromElement(target)).update({ disabled: true })
|
callback: async target => (await getDocFromElement(target)).update({ disabled: true })
|
||||||
},
|
},
|
||||||
|
|
@ -442,7 +442,7 @@ export default function DHApplicationMixin(Base) {
|
||||||
icon: 'fa-regular fa-lightbulb',
|
icon: 'fa-regular fa-lightbulb',
|
||||||
condition: target => {
|
condition: target => {
|
||||||
const doc = getDocFromElementSync(target);
|
const doc = getDocFromElementSync(target);
|
||||||
return doc && doc.disabled;
|
return doc && doc.disabled && doc.type !== 'beastform';
|
||||||
},
|
},
|
||||||
callback: async target => (await getDocFromElement(target)).update({ disabled: false })
|
callback: async target => (await getDocFromElement(target)).update({ disabled: false })
|
||||||
}
|
}
|
||||||
|
|
@ -536,6 +536,10 @@ export default function DHApplicationMixin(Base) {
|
||||||
options.push({
|
options.push({
|
||||||
name: 'CONTROLS.CommonDelete',
|
name: 'CONTROLS.CommonDelete',
|
||||||
icon: 'fa-solid fa-trash',
|
icon: 'fa-solid fa-trash',
|
||||||
|
condition: target => {
|
||||||
|
const doc = getDocFromElementSync(target);
|
||||||
|
return doc && doc.type !== 'beastform';
|
||||||
|
},
|
||||||
callback: async (target, event) => {
|
callback: async (target, event) => {
|
||||||
const doc = await getDocFromElement(target);
|
const doc = await getDocFromElement(target);
|
||||||
if (event.shiftKey) return doc.delete();
|
if (event.shiftKey) return doc.delete();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
export default function ItemAttachmentSheet(Base) {
|
export default function ItemAttachmentSheet(Base) {
|
||||||
return class extends Base {
|
return class extends Base {
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
...super.DEFAULT_OPTIONS,
|
|
||||||
dragDrop: [
|
dragDrop: [
|
||||||
...(super.DEFAULT_OPTIONS.dragDrop || []),
|
...(super.DEFAULT_OPTIONS.dragDrop || []),
|
||||||
{ dragSelector: null, dropSelector: '.attachments-section' }
|
{ dragSelector: null, dropSelector: '.attachments-section' }
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -17,6 +19,15 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
this.config = CONFIG.DH.ITEMBROWSER.compendiumConfig;
|
this.config = CONFIG.DH.ITEMBROWSER.compendiumConfig;
|
||||||
this.presets = {};
|
this.presets = {};
|
||||||
this.compendiumBrowserTypeKey = 'compendiumBrowserDefault';
|
this.compendiumBrowserTypeKey = 'compendiumBrowserDefault';
|
||||||
|
|
||||||
|
this.setupHooks = Hooks.on(socketEvent.Refresh, ({ refreshType }) => {
|
||||||
|
if (refreshType === RefreshType.CompendiumBrowser) {
|
||||||
|
if (this.rendered) {
|
||||||
|
this.render();
|
||||||
|
this.loadItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
|
|
@ -35,7 +46,8 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
selectFolder: this.selectFolder,
|
selectFolder: this.selectFolder,
|
||||||
expandContent: this.expandContent,
|
expandContent: this.expandContent,
|
||||||
resetFilters: this.resetFilters,
|
resetFilters: this.resetFilters,
|
||||||
sortList: this.sortList
|
sortList: this.sortList,
|
||||||
|
openSettings: this.openSettings
|
||||||
},
|
},
|
||||||
position: {
|
position: {
|
||||||
left: 100,
|
left: 100,
|
||||||
|
|
@ -157,6 +169,8 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
context.formatChoices = this.formatChoices;
|
context.formatChoices = this.formatChoices;
|
||||||
context.items = this.items;
|
context.items = this.items;
|
||||||
context.presets = this.presets;
|
context.presets = this.presets;
|
||||||
|
context.isGM = game.user.isGM;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,6 +228,10 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
loadItems() {
|
loadItems() {
|
||||||
let loadTimeout = this.toggleLoader(true);
|
let loadTimeout = this.toggleLoader(true);
|
||||||
|
|
||||||
|
const browserSettings = game.settings.get(
|
||||||
|
CONFIG.DH.id,
|
||||||
|
CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings
|
||||||
|
);
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
game.packs.forEach(pack => {
|
game.packs.forEach(pack => {
|
||||||
|
|
@ -227,7 +245,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
|
|
||||||
Promise.all(promises).then(async result => {
|
Promise.all(promises).then(async result => {
|
||||||
this.items = ItemBrowser.sortBy(
|
this.items = ItemBrowser.sortBy(
|
||||||
result.flatMap(r => r),
|
result.flatMap(r => r).filter(r => !browserSettings.isEntryExcluded.bind(browserSettings)(r)),
|
||||||
'name'
|
'name'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -512,6 +530,22 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
itemListContainer.replaceChildren(...newOrder);
|
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() {
|
_createDragProcess() {
|
||||||
new foundry.applications.ux.DragDrop.implementation({
|
new foundry.applications.ux.DragDrop.implementation({
|
||||||
dragSelector: '.item-container',
|
dragSelector: '.item-container',
|
||||||
|
|
@ -571,4 +605,9 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
headerActions.append(button);
|
headerActions.append(button);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async close(options = {}) {
|
||||||
|
Hooks.off(socketEvent.Refresh, this.setupHooks);
|
||||||
|
await super.close(options);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import DhMeasuredTemplate from "./measuredTemplate.mjs";
|
import DhMeasuredTemplate from './measuredTemplate.mjs';
|
||||||
|
|
||||||
export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
|
|
@ -63,7 +63,7 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
const originRadius = (this.bounds.width * boundsCorrection) / 2;
|
const originRadius = (this.bounds.width * boundsCorrection) / 2;
|
||||||
const targetRadius = (target.bounds.width * boundsCorrection) / 2;
|
const targetRadius = (target.bounds.width * boundsCorrection) / 2;
|
||||||
const distance = canvas.grid.measurePath([originPoint, destinationPoint]).distance;
|
const distance = canvas.grid.measurePath([originPoint, destinationPoint]).distance;
|
||||||
return distance - originRadius - targetRadius + canvas.grid.distance;
|
return Math.floor(distance - originRadius - targetRadius + canvas.grid.distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute what the closest grid space of each token is, then compute that distance
|
// Compute what the closest grid space of each token is, then compute that distance
|
||||||
|
|
@ -85,7 +85,7 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
|
|
||||||
// Check if the setting is enabled
|
// Check if the setting is enabled
|
||||||
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance).showTokenDistance;
|
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance).showTokenDistance;
|
||||||
if (setting === "never" || (setting === "encounters" && !game.combat?.started)) return;
|
if (setting === 'never' || (setting === 'encounters' && !game.combat?.started)) return;
|
||||||
|
|
||||||
// Check if this token isn't invisible and is actually being hovered
|
// Check if this token isn't invisible and is actually being hovered
|
||||||
const isTokenValid =
|
const isTokenValid =
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,7 @@ export const defaultRestOptions = {
|
||||||
actionType: 'action',
|
actionType: 'action',
|
||||||
chatDisplay: false,
|
chatDisplay: false,
|
||||||
target: {
|
target: {
|
||||||
|
amount: 1,
|
||||||
type: 'friendly'
|
type: 'friendly'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
|
|
@ -304,6 +305,7 @@ export const defaultRestOptions = {
|
||||||
actionType: 'action',
|
actionType: 'action',
|
||||||
chatDisplay: false,
|
chatDisplay: false,
|
||||||
target: {
|
target: {
|
||||||
|
amount: 1,
|
||||||
type: 'friendly'
|
type: 'friendly'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
|
|
@ -329,7 +331,56 @@ export const defaultRestOptions = {
|
||||||
icon: 'fa-solid fa-dumbbell',
|
icon: 'fa-solid fa-dumbbell',
|
||||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepare.description'),
|
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepare.description'),
|
||||||
actions: {},
|
actions: {
|
||||||
|
prepare: {
|
||||||
|
type: 'healing',
|
||||||
|
systemPath: 'restMoves.shortRest.moves.prepare.actions',
|
||||||
|
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepare.name'),
|
||||||
|
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||||
|
actionType: 'action',
|
||||||
|
chatDisplay: false,
|
||||||
|
target: {
|
||||||
|
type: 'self'
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
parts: [
|
||||||
|
{
|
||||||
|
applyTo: healingTypes.hope.id,
|
||||||
|
value: {
|
||||||
|
custom: {
|
||||||
|
enabled: true,
|
||||||
|
formula: '1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prepareWithFriends: {
|
||||||
|
type: 'healing',
|
||||||
|
systemPath: 'restMoves.shortRest.moves.prepare.actions',
|
||||||
|
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepareWithFriends.name'),
|
||||||
|
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||||
|
actionType: 'action',
|
||||||
|
chatDisplay: false,
|
||||||
|
target: {
|
||||||
|
type: 'self'
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
parts: [
|
||||||
|
{
|
||||||
|
applyTo: healingTypes.hope.id,
|
||||||
|
value: {
|
||||||
|
custom: {
|
||||||
|
enabled: true,
|
||||||
|
formula: '2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
effects: []
|
effects: []
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
@ -349,6 +400,7 @@ export const defaultRestOptions = {
|
||||||
actionType: 'action',
|
actionType: 'action',
|
||||||
chatDisplay: false,
|
chatDisplay: false,
|
||||||
target: {
|
target: {
|
||||||
|
amount: 1,
|
||||||
type: 'friendly'
|
type: 'friendly'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
|
|
@ -417,6 +469,7 @@ export const defaultRestOptions = {
|
||||||
actionType: 'action',
|
actionType: 'action',
|
||||||
chatDisplay: false,
|
chatDisplay: false,
|
||||||
target: {
|
target: {
|
||||||
|
amount: 1,
|
||||||
type: 'friendly'
|
type: 'friendly'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
|
|
@ -442,7 +495,56 @@ export const defaultRestOptions = {
|
||||||
icon: 'fa-solid fa-dumbbell',
|
icon: 'fa-solid fa-dumbbell',
|
||||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepare.description'),
|
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepare.description'),
|
||||||
actions: {},
|
actions: {
|
||||||
|
prepare: {
|
||||||
|
type: 'healing',
|
||||||
|
systemPath: 'restMoves.longRest.moves.prepare.actions',
|
||||||
|
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepare.name'),
|
||||||
|
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||||
|
actionType: 'action',
|
||||||
|
chatDisplay: false,
|
||||||
|
target: {
|
||||||
|
type: 'self'
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
parts: [
|
||||||
|
{
|
||||||
|
applyTo: healingTypes.hope.id,
|
||||||
|
value: {
|
||||||
|
custom: {
|
||||||
|
enabled: true,
|
||||||
|
formula: '1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prepareWithFriends: {
|
||||||
|
type: 'healing',
|
||||||
|
systemPath: 'restMoves.longRest.moves.prepare.actions',
|
||||||
|
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepareWithFriends.name'),
|
||||||
|
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||||
|
actionType: 'action',
|
||||||
|
chatDisplay: false,
|
||||||
|
target: {
|
||||||
|
type: 'self'
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
parts: [
|
||||||
|
{
|
||||||
|
applyTo: healingTypes.hope.id,
|
||||||
|
value: {
|
||||||
|
custom: {
|
||||||
|
enabled: true,
|
||||||
|
formula: '2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
effects: []
|
effects: []
|
||||||
},
|
},
|
||||||
workOnAProject: {
|
workOnAProject: {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ export const gameSettings = {
|
||||||
LastMigrationVersion: 'LastMigrationVersion',
|
LastMigrationVersion: 'LastMigrationVersion',
|
||||||
TagTeamRoll: 'TagTeamRoll',
|
TagTeamRoll: 'TagTeamRoll',
|
||||||
SpotlightRequestQueue: 'SpotlightRequestQueue',
|
SpotlightRequestQueue: 'SpotlightRequestQueue',
|
||||||
|
CompendiumBrowserSettings: 'CompendiumBrowserSettings'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const actionAutomationChoices = {
|
export const actionAutomationChoices = {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ export { default as DhCombatant } from './combatant.mjs';
|
||||||
export { default as DhTagTeamRoll } from './tagTeamRoll.mjs';
|
export { default as DhTagTeamRoll } from './tagTeamRoll.mjs';
|
||||||
export { default as DhRollTable } from './rollTable.mjs';
|
export { default as DhRollTable } from './rollTable.mjs';
|
||||||
export { default as RegisteredTriggers } from './registeredTriggers.mjs';
|
export { default as RegisteredTriggers } from './registeredTriggers.mjs';
|
||||||
|
export { default as CompendiumBrowserSettings } from './compendiumBrowserSettings.mjs';
|
||||||
|
|
||||||
export * as countdowns from './countdowns.mjs';
|
export * as countdowns from './countdowns.mjs';
|
||||||
export * as actions from './action/_module.mjs';
|
export * as actions from './action/_module.mjs';
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
|
|
||||||
if (Hooks.call(`${CONFIG.DH.id}.postUseAction`, this, config) === false) return;
|
if (Hooks.call(`${CONFIG.DH.id}.postUseAction`, this, config) === false) return;
|
||||||
|
|
||||||
if (this.chatDisplay) await this.toChat();
|
if (this.chatDisplay && !config.actionChatMessageHandled) await this.toChat();
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
@ -240,9 +240,13 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
* @returns {object}
|
* @returns {object}
|
||||||
*/
|
*/
|
||||||
prepareBaseConfig(event) {
|
prepareBaseConfig(event) {
|
||||||
|
const isActor = this.item instanceof CONFIG.Actor.documentClass;
|
||||||
|
const actionTitle = game.i18n.localize(this.name);
|
||||||
|
const itemTitle = isActor || this.item.name === actionTitle ? '' : `${this.item.name} - `;
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
event,
|
event,
|
||||||
title: `${this.item instanceof CONFIG.Actor.documentClass ? '' : `${this.item.name}: `}${game.i18n.localize(this.name)}`,
|
title: `${itemTitle}${actionTitle}`,
|
||||||
source: {
|
source: {
|
||||||
item: this.item._id,
|
item: this.item._id,
|
||||||
originItem: this.originItem,
|
originItem: this.originItem,
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,14 @@ export default class DhpAdversary extends BaseDataActor {
|
||||||
integer: true,
|
integer: true,
|
||||||
label: 'DAGGERHEART.GENERAL.hordeHp'
|
label: 'DAGGERHEART.GENERAL.hordeHp'
|
||||||
}),
|
}),
|
||||||
criticalThreshold: new fields.NumberField({ required: true, integer: true, min: 1, max: 20, initial: 20 }),
|
criticalThreshold: new fields.NumberField({
|
||||||
|
required: true,
|
||||||
|
integer: true,
|
||||||
|
min: 1,
|
||||||
|
max: 20,
|
||||||
|
initial: 20,
|
||||||
|
label: 'DAGGERHEART.ACTIONS.Settings.criticalThreshold'
|
||||||
|
}),
|
||||||
damageThresholds: new fields.SchemaField({
|
damageThresholds: new fields.SchemaField({
|
||||||
major: new fields.NumberField({
|
major: new fields.NumberField({
|
||||||
required: true,
|
required: true,
|
||||||
|
|
|
||||||
|
|
@ -29,17 +29,40 @@ const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) =>
|
||||||
/* Common rules applying to Characters and Adversaries */
|
/* Common rules applying to Characters and Adversaries */
|
||||||
export const commonActorRules = (extendedData = { damageReduction: {}, attack: { damage: {} } }) => ({
|
export const commonActorRules = (extendedData = { damageReduction: {}, attack: { damage: {} } }) => ({
|
||||||
conditionImmunities: new fields.SchemaField({
|
conditionImmunities: new fields.SchemaField({
|
||||||
hidden: new fields.BooleanField({ initial: false }),
|
hidden: new fields.BooleanField({
|
||||||
restrained: new fields.BooleanField({ initial: false }),
|
initial: false,
|
||||||
vulnerable: new fields.BooleanField({ initial: false })
|
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.hidden'
|
||||||
|
}),
|
||||||
|
restrained: new fields.BooleanField({
|
||||||
|
initial: false,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.restrained'
|
||||||
|
}),
|
||||||
|
vulnerable: new fields.BooleanField({
|
||||||
|
initial: false,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.vulnerable'
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
damageReduction: new fields.SchemaField({
|
damageReduction: new fields.SchemaField({
|
||||||
thresholdImmunities: new fields.SchemaField({
|
thresholdImmunities: new fields.SchemaField({
|
||||||
minor: new fields.BooleanField({ initial: false })
|
minor: new fields.BooleanField({
|
||||||
|
initial: false,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.thresholdImmunities.minor.label',
|
||||||
|
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.thresholdImmunities.minor.hint'
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
reduceSeverity: new fields.SchemaField({
|
reduceSeverity: new fields.SchemaField({
|
||||||
magical: new fields.NumberField({ initial: 0, min: 0 }),
|
magical: new fields.NumberField({
|
||||||
physical: new fields.NumberField({ initial: 0, min: 0 })
|
initial: 0,
|
||||||
|
min: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.magical.label',
|
||||||
|
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.magical.hint'
|
||||||
|
}),
|
||||||
|
physical: new fields.NumberField({
|
||||||
|
initial: 0,
|
||||||
|
min: 0,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.physical.label',
|
||||||
|
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.reduceSeverity.physical.hint'
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
...(extendedData.damageReduction ?? {})
|
...(extendedData.damageReduction ?? {})
|
||||||
}),
|
}),
|
||||||
|
|
@ -49,12 +72,16 @@ export const commonActorRules = (extendedData = { damageReduction: {}, attack: {
|
||||||
hpDamageMultiplier: new fields.NumberField({
|
hpDamageMultiplier: new fields.NumberField({
|
||||||
required: true,
|
required: true,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
initial: 1
|
initial: 1,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Attack.hpDamageMultiplier.label',
|
||||||
|
hint: 'DAGGERHEART.GENERAL.Attack.hpDamageMultiplier.hint'
|
||||||
}),
|
}),
|
||||||
hpDamageTakenMultiplier: new fields.NumberField({
|
hpDamageTakenMultiplier: new fields.NumberField({
|
||||||
required: true,
|
required: true,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
initial: 1
|
initial: 1,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Attack.hpDamageTakenMultiplier.label',
|
||||||
|
hint: 'DAGGERHEART.GENERAL.Attack.hpDamageTakenMultiplier.hint'
|
||||||
}),
|
}),
|
||||||
...(extendedData.attack?.damage ?? {})
|
...(extendedData.attack?.damage ?? {})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,8 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
'DAGGERHEART.ACTORS.Character.maxHPBonus'
|
'DAGGERHEART.ACTORS.Character.maxHPBonus'
|
||||||
),
|
),
|
||||||
stress: resourceField(6, 0, 'DAGGERHEART.GENERAL.stress', true),
|
stress: resourceField(6, 0, 'DAGGERHEART.GENERAL.stress', true),
|
||||||
hope: new fields.SchemaField({
|
hope: new fields.SchemaField(
|
||||||
|
{
|
||||||
value: new fields.NumberField({
|
value: new fields.NumberField({
|
||||||
initial: 2,
|
initial: 2,
|
||||||
min: 0,
|
min: 0,
|
||||||
|
|
@ -43,7 +44,9 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
label: 'DAGGERHEART.GENERAL.hope'
|
label: 'DAGGERHEART.GENERAL.hope'
|
||||||
}),
|
}),
|
||||||
isReversed: new fields.BooleanField({ initial: false })
|
isReversed: new fields.BooleanField({ initial: false })
|
||||||
})
|
},
|
||||||
|
{ label: 'DAGGERHEART.GENERAL.hope' }
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
traits: new fields.SchemaField({
|
traits: new fields.SchemaField({
|
||||||
agility: attributeField('DAGGERHEART.CONFIG.Traits.agility.name'),
|
agility: attributeField('DAGGERHEART.CONFIG.Traits.agility.name'),
|
||||||
|
|
@ -222,8 +225,16 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
rules: new fields.SchemaField({
|
rules: new fields.SchemaField({
|
||||||
...commonActorRules({
|
...commonActorRules({
|
||||||
damageReduction: {
|
damageReduction: {
|
||||||
magical: new fields.BooleanField({ initial: false }),
|
magical: new fields.BooleanField({
|
||||||
physical: new fields.BooleanField({ initial: false }),
|
initial: false,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.magical.label',
|
||||||
|
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.magical.hint'
|
||||||
|
}),
|
||||||
|
physical: new fields.BooleanField({
|
||||||
|
initial: false,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.physical.label',
|
||||||
|
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.physical.hint'
|
||||||
|
}),
|
||||||
maxArmorMarked: new fields.SchemaField({
|
maxArmorMarked: new fields.SchemaField({
|
||||||
value: new fields.NumberField({
|
value: new fields.NumberField({
|
||||||
required: true,
|
required: true,
|
||||||
|
|
@ -253,7 +264,10 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.label',
|
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.label',
|
||||||
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.hint'
|
hint: 'DAGGERHEART.GENERAL.Rules.damageReduction.increasePerArmorMark.hint'
|
||||||
}),
|
}),
|
||||||
disabledArmor: new fields.BooleanField({ intial: false })
|
disabledArmor: new fields.BooleanField({
|
||||||
|
intial: false,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.damageReduction.disabledArmor.label'
|
||||||
|
})
|
||||||
},
|
},
|
||||||
attack: {
|
attack: {
|
||||||
damage: {
|
damage: {
|
||||||
|
|
@ -301,12 +315,14 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
label: 'DAGGERHEART.ACTORS.Character.defaultFearDice'
|
label: 'DAGGERHEART.ACTORS.Character.defaultFearDice'
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
runeWard: new fields.BooleanField({ initial: false }),
|
|
||||||
burden: new fields.SchemaField({
|
burden: new fields.SchemaField({
|
||||||
ignore: new fields.BooleanField()
|
ignore: new fields.BooleanField({ label: 'DAGGERHEART.ACTORS.Character.burden.ignore.label' })
|
||||||
}),
|
}),
|
||||||
roll: new fields.SchemaField({
|
roll: new fields.SchemaField({
|
||||||
guaranteedCritical: new fields.BooleanField()
|
guaranteedCritical: new fields.BooleanField({
|
||||||
|
label: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.label',
|
||||||
|
hint: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.hint'
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,18 @@ export default class DhCompanion extends BaseDataActor {
|
||||||
),
|
),
|
||||||
rules: new fields.SchemaField({
|
rules: new fields.SchemaField({
|
||||||
conditionImmunities: new fields.SchemaField({
|
conditionImmunities: new fields.SchemaField({
|
||||||
hidden: new fields.BooleanField({ initial: false }),
|
hidden: new fields.BooleanField({
|
||||||
restrained: new fields.BooleanField({ initial: false }),
|
initial: false,
|
||||||
vulnerable: new fields.BooleanField({ initial: false })
|
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.hidden'
|
||||||
|
}),
|
||||||
|
restrained: new fields.BooleanField({
|
||||||
|
initial: false,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.restrained'
|
||||||
|
}),
|
||||||
|
vulnerable: new fields.BooleanField({
|
||||||
|
initial: false,
|
||||||
|
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.vulnerable'
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
attack: new ActionField({
|
attack: new ActionField({
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
|
||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
return {
|
return {
|
||||||
title: new fields.StringField(),
|
title: new fields.StringField(),
|
||||||
|
actionDescription: new fields.HTMLField(),
|
||||||
roll: new fields.ObjectField(),
|
roll: new fields.ObjectField(),
|
||||||
targets: targetsField(),
|
targets: targetsField(),
|
||||||
hasRoll: new fields.BooleanField({ initial: false }),
|
hasRoll: new fields.BooleanField({ initial: false }),
|
||||||
|
|
|
||||||
35
module/data/compendiumBrowserSettings.mjs
Normal file
35
module/data/compendiumBrowserSettings.mjs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
export default class CompendiumBrowserSettings extends foundry.abstract.DataModel {
|
||||||
|
static defineSchema() {
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
|
||||||
|
return {
|
||||||
|
excludedSources: new fields.TypedObjectField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
excludedDocumentTypes: new fields.ArrayField(
|
||||||
|
new fields.StringField({ required: true, choices: CONST.SYSTEM_SPECIFIC_COMPENDIUM_TYPES })
|
||||||
|
)
|
||||||
|
})
|
||||||
|
),
|
||||||
|
excludedPacks: new fields.TypedObjectField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
excludedDocumentTypes: new fields.ArrayField(
|
||||||
|
new fields.StringField({ required: true, choices: CONST.SYSTEM_SPECIFIC_COMPENDIUM_TYPES })
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
isEntryExcluded(item) {
|
||||||
|
const pack = game.packs.get(item.pack);
|
||||||
|
if (!pack) return false;
|
||||||
|
|
||||||
|
const excludedSourceData = this.excludedSources[pack.metadata.packageName];
|
||||||
|
if (excludedSourceData && excludedSourceData.excludedDocumentTypes.includes(pack.metadata.type)) return true;
|
||||||
|
|
||||||
|
const excludedPackData = this.excludedPacks[item.pack];
|
||||||
|
if (excludedPackData && excludedPackData.excludedDocumentTypes.includes(pack.metadata.type)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -68,6 +68,8 @@ export default class DamageField extends fields.SchemaField {
|
||||||
|
|
||||||
const damageResult = await CONFIG.Dice.daggerheart.DamageRoll.build(damageConfig);
|
const damageResult = await CONFIG.Dice.daggerheart.DamageRoll.build(damageConfig);
|
||||||
if (!damageResult) return false;
|
if (!damageResult) return false;
|
||||||
|
if (damageResult.actionChatMessageHandled) config.actionChatMessageHandled = true;
|
||||||
|
|
||||||
config.damage = damageResult.damage;
|
config.damage = damageResult.damage;
|
||||||
config.message ??= damageConfig.message;
|
config.message ??= damageConfig.message;
|
||||||
}
|
}
|
||||||
|
|
@ -107,8 +109,8 @@ export default class DamageField extends fields.SchemaField {
|
||||||
);
|
);
|
||||||
else {
|
else {
|
||||||
const configDamage = foundry.utils.deepClone(config.damage);
|
const configDamage = foundry.utils.deepClone(config.damage);
|
||||||
const hpDamageMultiplier = config.actionActor?.system.rules.attack.damage.hpDamageMultiplier ?? 1;
|
const hpDamageMultiplier = config.actionActor?.system.rules?.attack?.damage?.hpDamageMultiplier ?? 1;
|
||||||
const hpDamageTakenMultiplier = actor.system.rules.attack.damage.hpDamageTakenMultiplier;
|
const hpDamageTakenMultiplier = actor.system.rules?.attack?.damage?.hpDamageTakenMultiplier;
|
||||||
if (configDamage.hitPoints) {
|
if (configDamage.hitPoints) {
|
||||||
for (const part of configDamage.hitPoints.parts) {
|
for (const part of configDamage.hitPoints.parts) {
|
||||||
part.total = Math.ceil(part.total * hpDamageMultiplier * hpDamageTakenMultiplier);
|
part.total = Math.ceil(part.total * hpDamageMultiplier * hpDamageTakenMultiplier);
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,20 @@ const attributeField = label =>
|
||||||
});
|
});
|
||||||
|
|
||||||
const resourceField = (max = 0, initial = 0, label, reverse = false, maxLabel) =>
|
const resourceField = (max = 0, initial = 0, label, reverse = false, maxLabel) =>
|
||||||
new fields.SchemaField({
|
new fields.SchemaField(
|
||||||
|
{
|
||||||
value: new fields.NumberField({ initial: initial, min: 0, integer: true, label }),
|
value: new fields.NumberField({ initial: initial, min: 0, integer: true, label }),
|
||||||
max: new fields.NumberField({
|
max: new fields.NumberField({
|
||||||
initial: max,
|
initial: max,
|
||||||
integer: true,
|
integer: true,
|
||||||
label:
|
label:
|
||||||
maxLabel ?? game.i18n.format('DAGGERHEART.GENERAL.maxWithThing', { thing: game.i18n.localize(label) })
|
maxLabel ??
|
||||||
|
game.i18n.format('DAGGERHEART.GENERAL.maxWithThing', { thing: game.i18n.localize(label) })
|
||||||
}),
|
}),
|
||||||
isReversed: new fields.BooleanField({ initial: reverse })
|
isReversed: new fields.BooleanField({ initial: reverse })
|
||||||
});
|
},
|
||||||
|
{ label }
|
||||||
|
);
|
||||||
|
|
||||||
const stressDamageReductionRule = localizationPath =>
|
const stressDamageReductionRule = localizationPath =>
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
|
|
|
||||||
|
|
@ -253,4 +253,20 @@ export default class DHBeastform extends BaseDataItem {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onCreate(_data, _options, userId) {
|
||||||
|
if (!this.actor && game.user.id === userId) {
|
||||||
|
const hasBeastformEffect = this.parent.effects.some(x => x.type === 'beastform');
|
||||||
|
if (!hasBeastformEffect)
|
||||||
|
this.parent.createEmbeddedDocuments('ActiveEffect', [
|
||||||
|
{
|
||||||
|
type: 'beastform',
|
||||||
|
name: game.i18n.localize('DAGGERHEART.ITEMS.Beastform.beastformEffect'),
|
||||||
|
img: 'icons/creatures/abilities/paw-print-pair-purple.webp'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,12 @@ export default class DhLevelData extends foundry.abstract.DataModel {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
level: new fields.SchemaField({
|
level: new fields.SchemaField({
|
||||||
current: new fields.NumberField({ required: true, integer: true, initial: 1 }),
|
current: new fields.NumberField({
|
||||||
|
required: true,
|
||||||
|
integer: true,
|
||||||
|
initial: 1,
|
||||||
|
label: 'DAGGERHEART.GENERAL.currentLevel'
|
||||||
|
}),
|
||||||
changed: new fields.NumberField({ required: true, integer: true, initial: 1 }),
|
changed: new fields.NumberField({ required: true, integer: true, initial: 1 }),
|
||||||
bonuses: new fields.TypedObjectField(new fields.NumberField({ integer: true, nullable: false }))
|
bonuses: new fields.TypedObjectField(new fields.NumberField({ integer: true, nullable: false }))
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export default class DhAppearance extends foundry.abstract.DataModel {
|
||||||
extendEnvironmentDescriptions: new BooleanField(),
|
extendEnvironmentDescriptions: new BooleanField(),
|
||||||
extendItemDescriptions: new BooleanField(),
|
extendItemDescriptions: new BooleanField(),
|
||||||
expandRollMessage: new SchemaField({
|
expandRollMessage: new SchemaField({
|
||||||
desc: new BooleanField(),
|
desc: new BooleanField({ initial: true }),
|
||||||
roll: new BooleanField(),
|
roll: new BooleanField(),
|
||||||
damage: new BooleanField(),
|
damage: new BooleanField(),
|
||||||
target: new BooleanField()
|
target: new BooleanField()
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,19 @@ export default class DHRoll extends Roll {
|
||||||
}
|
}
|
||||||
|
|
||||||
static async toMessage(roll, config) {
|
static async toMessage(roll, config) {
|
||||||
|
const item = config.data.parent?.items?.get?.(config.source.item) ?? null;
|
||||||
|
const action = item ? item.system.actions.get(config.source.action) : null;
|
||||||
|
let actionDescription = null;
|
||||||
|
if (action?.chatDisplay) {
|
||||||
|
actionDescription = action
|
||||||
|
? await foundry.applications.ux.TextEditor.implementation.enrichHTML(action.description, {
|
||||||
|
relativeTo: config.data,
|
||||||
|
rollData: config.data.getRollData?.() ?? {}
|
||||||
|
})
|
||||||
|
: null;
|
||||||
|
config.actionChatMessageHandled = true;
|
||||||
|
}
|
||||||
|
|
||||||
const cls = getDocumentClass('ChatMessage'),
|
const cls = getDocumentClass('ChatMessage'),
|
||||||
msgData = {
|
msgData = {
|
||||||
type: this.messageType,
|
type: this.messageType,
|
||||||
|
|
@ -103,7 +116,7 @@ export default class DHRoll extends Roll {
|
||||||
title: roll.title,
|
title: roll.title,
|
||||||
speaker: cls.getSpeaker({ actor: roll.data?.parent }),
|
speaker: cls.getSpeaker({ actor: roll.data?.parent }),
|
||||||
sound: config.mute ? null : CONFIG.sounds.dice,
|
sound: config.mute ? null : CONFIG.sounds.dice,
|
||||||
system: config,
|
system: { ...config, actionDescription },
|
||||||
rolls: [roll]
|
rolls: [roll]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,14 +61,15 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
|
||||||
update.img = 'icons/magic/life/heart-cross-blue.webp';
|
update.img = 'icons/magic/life/heart-cross-blue.webp';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const statuses = Object.keys(data.statuses ?? {});
|
||||||
const immuneStatuses =
|
const immuneStatuses =
|
||||||
data.statuses?.filter(
|
statuses.filter(
|
||||||
status =>
|
status =>
|
||||||
this.parent.system.rules?.conditionImmunities &&
|
this.parent.system.rules?.conditionImmunities &&
|
||||||
this.parent.system.rules.conditionImmunities[status]
|
this.parent.system.rules.conditionImmunities[status]
|
||||||
) ?? [];
|
) ?? [];
|
||||||
if (immuneStatuses.length > 0) {
|
if (immuneStatuses.length > 0) {
|
||||||
update.statuses = data.statuses.filter(x => !immuneStatuses.includes(x));
|
update.statuses = statuses.filter(x => !immuneStatuses.includes(x));
|
||||||
const conditions = CONFIG.DH.GENERAL.conditions();
|
const conditions = CONFIG.DH.GENERAL.conditions();
|
||||||
const scrollingTexts = immuneStatuses.map(status => ({
|
const scrollingTexts = immuneStatuses.map(status => ({
|
||||||
text: game.i18n.format('DAGGERHEART.ACTIVEEFFECT.immuneStatusText', {
|
text: game.i18n.format('DAGGERHEART.ACTIVEEFFECT.immuneStatusText', {
|
||||||
|
|
@ -113,6 +114,11 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
|
||||||
super.applyField(model, change, field);
|
super.applyField(model, change, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_applyLegacy(actor, change, changes) {
|
||||||
|
change.value = DhActiveEffect.getChangeValue(actor, change, change.effect);
|
||||||
|
super._applyLegacy(actor, change, changes);
|
||||||
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
static getChangeValue(model, change, effect) {
|
static getChangeValue(model, change, effect) {
|
||||||
let value = change.value;
|
let value = change.value;
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,8 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
||||||
} else if (s.classList.contains('damage-section'))
|
} else if (s.classList.contains('damage-section'))
|
||||||
s.classList.toggle('expanded', autoExpandRoll.damage);
|
s.classList.toggle('expanded', autoExpandRoll.damage);
|
||||||
else if (s.classList.contains('target-section')) s.classList.toggle('expanded', autoExpandRoll.target);
|
else if (s.classList.contains('target-section')) s.classList.toggle('expanded', autoExpandRoll.target);
|
||||||
|
else if (s.classList.contains('description-section'))
|
||||||
|
s.classList.toggle('expanded', autoExpandRoll.desc);
|
||||||
});
|
});
|
||||||
if (itemDesc && autoExpandRoll.desc) itemDesc.setAttribute('open', '');
|
if (itemDesc && autoExpandRoll.desc) itemDesc.setAttribute('open', '');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,78 +1,30 @@
|
||||||
export default class DHToken extends CONFIG.Token.documentClass {
|
export default class DHToken extends CONFIG.Token.documentClass {
|
||||||
/**
|
/**@inheritdoc */
|
||||||
* Inspect the Actor data model and identify the set of attributes which could be used for a Token Bar.
|
static getTrackedAttributeChoices(attributes, typeKey) {
|
||||||
* @param {object} attributes The tracked attributes which can be chosen from
|
|
||||||
* @returns {object} A nested object of attribute choices to display
|
|
||||||
*/
|
|
||||||
static getTrackedAttributeChoices(attributes, model) {
|
|
||||||
attributes = attributes || this.getTrackedAttributes();
|
attributes = attributes || this.getTrackedAttributes();
|
||||||
const barGroup = game.i18n.localize('TOKEN.BarAttributes');
|
const barGroup = game.i18n.localize('TOKEN.BarAttributes');
|
||||||
const valueGroup = game.i18n.localize('TOKEN.BarValues');
|
const valueGroup = game.i18n.localize('TOKEN.BarValues');
|
||||||
|
const actorModel = typeKey ? game.system.api.data.actors[`Dh${typeKey.capitalize()}`] : null;
|
||||||
|
const getLabel = path => {
|
||||||
|
const label = actorModel.schema.getField(path)?.label;
|
||||||
|
return label ? game.i18n.localize(label) : path;
|
||||||
|
};
|
||||||
|
|
||||||
const bars = attributes.bar.map(v => {
|
const bars = attributes.bar.map(v => {
|
||||||
const a = v.join('.');
|
const a = v.join('.');
|
||||||
const modelLabel = model ? game.i18n.localize(model.schema.getField(`${a}.value`).label) : null;
|
return { group: barGroup, value: a, label: getLabel(a) };
|
||||||
return { group: barGroup, value: a, label: modelLabel ? modelLabel : a };
|
|
||||||
});
|
});
|
||||||
bars.sort((a, b) => a.label.compare(b.label));
|
bars.sort((a, b) => a.value.compare(b.value));
|
||||||
|
|
||||||
const invalidAttributes = [
|
const values = attributes.value.map(v => {
|
||||||
'gold',
|
|
||||||
'levelData',
|
|
||||||
'actions',
|
|
||||||
'biography',
|
|
||||||
'class',
|
|
||||||
'multiclass',
|
|
||||||
'companion',
|
|
||||||
'notes',
|
|
||||||
'partner',
|
|
||||||
'description',
|
|
||||||
'impulses',
|
|
||||||
'tier',
|
|
||||||
'type'
|
|
||||||
];
|
|
||||||
const values = attributes.value.reduce((acc, v) => {
|
|
||||||
const a = v.join('.');
|
const a = v.join('.');
|
||||||
if (invalidAttributes.some(x => a.startsWith(x))) return acc;
|
return { group: valueGroup, value: a, label: getLabel(a) };
|
||||||
|
});
|
||||||
const field = model ? model.schema.getField(a) : null;
|
|
||||||
const modelLabel = field ? game.i18n.localize(field.label) : null;
|
|
||||||
const hint = field ? game.i18n.localize(field.hint) : null;
|
|
||||||
acc.push({ group: valueGroup, value: a, label: modelLabel ? modelLabel : a, hint: hint });
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
values.sort((a, b) => a.label.compare(b.label));
|
|
||||||
|
|
||||||
|
values.sort((a, b) => a.value.compare(b.value));
|
||||||
return bars.concat(values);
|
return bars.concat(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
static _getTrackedAttributesFromSchema(schema, _path = []) {
|
|
||||||
const attributes = { bar: [], value: [] };
|
|
||||||
for (const [name, field] of Object.entries(schema.fields)) {
|
|
||||||
const p = _path.concat([name]);
|
|
||||||
if (field instanceof foundry.data.fields.NumberField) attributes.value.push(p);
|
|
||||||
if (field instanceof foundry.data.fields.BooleanField && field.options.isAttributeChoice)
|
|
||||||
attributes.value.push(p);
|
|
||||||
if (field instanceof foundry.data.fields.StringField) attributes.value.push(p);
|
|
||||||
if (field instanceof foundry.data.fields.ArrayField) attributes.value.push(p);
|
|
||||||
const isSchema = field instanceof foundry.data.fields.SchemaField;
|
|
||||||
const isModel = field instanceof foundry.data.fields.EmbeddedDataField;
|
|
||||||
|
|
||||||
if (isSchema || isModel) {
|
|
||||||
const schema = isModel ? field.model.schema : field;
|
|
||||||
const isBar = schema.has && schema.has('value') && schema.has('max');
|
|
||||||
if (isBar) attributes.bar.push(p);
|
|
||||||
else {
|
|
||||||
const inner = this.getTrackedAttributes(schema, p);
|
|
||||||
attributes.bar.push(...inner.bar);
|
|
||||||
attributes.value.push(...inner.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
_shouldRecordMovementHistory() {
|
_shouldRecordMovementHistory() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ export const preloadHandlebarsTemplates = async function () {
|
||||||
'systems/daggerheart/templates/dialogs/downtime/activities.hbs',
|
'systems/daggerheart/templates/dialogs/downtime/activities.hbs',
|
||||||
'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs',
|
'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs',
|
||||||
'systems/daggerheart/templates/ui/chat/parts/roll-part.hbs',
|
'systems/daggerheart/templates/ui/chat/parts/roll-part.hbs',
|
||||||
|
'systems/daggerheart/templates/ui/chat/parts/description-part.hbs',
|
||||||
'systems/daggerheart/templates/ui/chat/parts/damage-part.hbs',
|
'systems/daggerheart/templates/ui/chat/parts/damage-part.hbs',
|
||||||
'systems/daggerheart/templates/ui/chat/parts/target-part.hbs',
|
'systems/daggerheart/templates/ui/chat/parts/target-part.hbs',
|
||||||
'systems/daggerheart/templates/ui/chat/parts/button-part.hbs',
|
'systems/daggerheart/templates/ui/chat/parts/button-part.hbs',
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
DhHomebrewSettings,
|
DhHomebrewSettings,
|
||||||
DhVariantRuleSettings
|
DhVariantRuleSettings
|
||||||
} from '../applications/settings/_module.mjs';
|
} from '../applications/settings/_module.mjs';
|
||||||
import { DhTagTeamRoll } from '../data/_module.mjs';
|
import { CompendiumBrowserSettings, DhTagTeamRoll } from '../data/_module.mjs';
|
||||||
|
|
||||||
export const registerDHSettings = () => {
|
export const registerDHSettings = () => {
|
||||||
registerMenuSettings();
|
registerMenuSettings();
|
||||||
|
|
@ -142,6 +142,12 @@ const registerNonConfigSettings = () => {
|
||||||
config: false,
|
config: false,
|
||||||
type: DhTagTeamRoll
|
type: DhTagTeamRoll
|
||||||
});
|
});
|
||||||
|
|
||||||
|
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings, {
|
||||||
|
scope: 'client',
|
||||||
|
config: false,
|
||||||
|
type: CompendiumBrowserSettings
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,8 @@ export const RefreshType = {
|
||||||
Countdown: 'DhCoundownRefresh',
|
Countdown: 'DhCoundownRefresh',
|
||||||
TagTeamRoll: 'DhTagTeamRollRefresh',
|
TagTeamRoll: 'DhTagTeamRollRefresh',
|
||||||
EffectsDisplay: 'DhEffectsDisplayRefresh',
|
EffectsDisplay: 'DhEffectsDisplayRefresh',
|
||||||
Scene: 'DhSceneRefresh'
|
Scene: 'DhSceneRefresh',
|
||||||
|
CompendiumBrowser: 'DhCompendiumBrowserRefresh'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const registerSocketHooks = () => {
|
export const registerSocketHooks = () => {
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
"startRound": null,
|
"startRound": null,
|
||||||
"startTurn": null
|
"startTurn": null
|
||||||
},
|
},
|
||||||
"description": "<p class=\"Body-Foundation\">Add your Strength to the presence roll roll.</p>",
|
"description": "<p class=\"Body-Foundation\">Add your Strength to the presence roll.</p>",
|
||||||
"tint": "#ffffff",
|
"tint": "#ffffff",
|
||||||
"statuses": [],
|
"statuses": [],
|
||||||
"sort": 0,
|
"sort": 0,
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,8 @@
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"recovery": "shortRest",
|
"recovery": "shortRest",
|
||||||
"max": "1",
|
"max": "1",
|
||||||
"icon": ""
|
"icon": "",
|
||||||
|
"progression": "decreasing"
|
||||||
},
|
},
|
||||||
"attribution": {
|
"attribution": {
|
||||||
"source": "Daggerheart SRD",
|
"source": "Daggerheart SRD",
|
||||||
|
|
|
||||||
105
styles/less/dialog/compendiumBrowserPackDialog/sheet.less
Normal file
105
styles/less/dialog/compendiumBrowserPackDialog/sheet.less
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
.daggerheart.dialog.dh-style.views.compendium-brower-settings {
|
||||||
|
--text-color: light-dark(@dark-blue, @beige);
|
||||||
|
color: var(--text-color);
|
||||||
|
|
||||||
|
.window-content {
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
overflow: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
max-height: 440px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.types-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.type-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: var(--font-size-16);
|
||||||
|
font-family: @font-subtitle;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
flex: 1;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, light-dark(@dark-blue, @golden) 100%);
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
flex: 1;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(90deg, light-dark(@dark-blue, @golden) 0%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sources-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.source-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
|
||||||
|
.source-inner-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.source-inner-label-container {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 18px;
|
||||||
|
// color: light-dark(@dark-blue, @golden);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.checks-container {
|
||||||
|
padding-left: 24px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 4px;
|
||||||
|
transition: height 0.4s ease-in-out;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.collapsed {
|
||||||
|
height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
margin-top: 8px;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,7 +17,9 @@
|
||||||
|
|
||||||
.dialog-header-inner {
|
.dialog-header-inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
|
@ -45,6 +47,29 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reaction-chip {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: fit-content;
|
||||||
|
gap: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px;
|
||||||
|
background: light-dark(@dark-blue-10, @golden-10);
|
||||||
|
color: light-dark(@dark-blue, @golden);
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: var(--font-size-14);
|
||||||
|
line-height: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background: light-dark(@dark-blue-40, @golden-40);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.tag-team-controller {
|
.tag-team-controller {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
||||||
|
|
@ -43,3 +43,5 @@
|
||||||
@import './risk-it-all/sheet.less';
|
@import './risk-it-all/sheet.less';
|
||||||
|
|
||||||
@import './character-reset/sheet.less';
|
@import './character-reset/sheet.less';
|
||||||
|
|
||||||
|
@import './compendiumBrowserPackDialog/sheet.less';
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type='checkbox'] {
|
||||||
|
&:indeterminate {
|
||||||
|
&::before {
|
||||||
|
content: '\f0fe';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
input[type='checkbox'],
|
input[type='checkbox'],
|
||||||
input[type='radio'] {
|
input[type='radio'] {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
|
|
||||||
|
|
@ -38,124 +38,6 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
details[open] {
|
|
||||||
.fa-chevron-down {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-move {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.fa-chevron-down {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-section {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
margin: 8px 8px 0;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
width: -webkit-fill-available;
|
|
||||||
gap: 5px;
|
|
||||||
border-bottom: 1px solid @golden;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: @golden-10;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-img {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
border-radius: 3px;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-header {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 5px;
|
|
||||||
color: @beige;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: var(--font-size-20);
|
|
||||||
color: @golden;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
font-size: var(--font-size-12);
|
|
||||||
color: @beige;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
.summons-header {
|
|
||||||
font-size: var(--font-size-14);
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
span {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before,
|
|
||||||
&:after {
|
|
||||||
content: ' ';
|
|
||||||
height: 1px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, light-dark(@dark-blue, @golden) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
background: linear-gradient(90deg, light-dark(@dark-blue, @golden) 0%, rgba(0, 0, 0, 0) 100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.summons-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
|
|
||||||
.summon-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.summon-label-container {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ability-card-footer {
|
.ability-card-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,15 @@
|
||||||
font-size: var(--font-size-12);
|
font-size: var(--font-size-12);
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
|
|
||||||
|
.roll-part-title {
|
||||||
|
text-align: center;
|
||||||
|
font-family: @font-subtitle;
|
||||||
|
font-size: var(--font-size-18);
|
||||||
|
font-weight: bold;
|
||||||
|
color: light-dark(@dark-blue, var(--text-color));
|
||||||
|
margin-bottom: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
> .roll-part-header {
|
> .roll-part-header {
|
||||||
font-size: var(--font-size-14);
|
font-size: var(--font-size-14);
|
||||||
}
|
}
|
||||||
|
|
@ -286,6 +295,7 @@
|
||||||
|
|
||||||
> :first-child:not(.target-selector) {
|
> :first-child:not(.target-selector) {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
> :last-child {
|
> :last-child {
|
||||||
|
|
@ -573,6 +583,30 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-roll .description-section {
|
||||||
|
.roll-part-content {
|
||||||
|
.dice-tooltip {
|
||||||
|
.wrapper {
|
||||||
|
i {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> :first-child:not(.target-selector) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.roll-buttons {
|
.roll-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
|
|
@ -590,5 +624,124 @@
|
||||||
.dice-roll .dice-tooltip fieldset {
|
.dice-roll .dice-tooltip fieldset {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
details[open] {
|
||||||
|
.fa-chevron-down {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-move {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.fa-chevron-down {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin: 8px 8px 0;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
width: -webkit-fill-available;
|
||||||
|
gap: 5px;
|
||||||
|
border-bottom: 1px solid @golden;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @golden-10;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-img {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 3px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
color: @beige;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: var(--font-size-20);
|
||||||
|
color: @golden;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: var(--font-size-12);
|
||||||
|
color: @beige;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
.summons-header {
|
||||||
|
font-size: var(--font-size-14);
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
content: ' ';
|
||||||
|
height: 1px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, light-dark(@dark-blue, @golden) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
background: linear-gradient(90deg, light-dark(@dark-blue, @golden) 0%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.summons-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
.summon-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.summon-label-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@
|
||||||
li[role='option'] {
|
li[role='option'] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
|
||||||
font-size: var(--font-size-14);
|
font-size: var(--font-size-14);
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "daggerheart",
|
"id": "daggerheart",
|
||||||
"title": "Daggerheart",
|
"title": "Daggerheart",
|
||||||
"description": "An unofficial implementation of the Daggerheart system",
|
"description": "An unofficial implementation of the Daggerheart system",
|
||||||
"version": "1.6.4",
|
"version": "1.7.0",
|
||||||
"compatibility": {
|
"compatibility": {
|
||||||
"minimum": "13.346",
|
"minimum": "13.346",
|
||||||
"verified": "13.351",
|
"verified": "13.351",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<footer>
|
||||||
|
<button data-action="finish">{{localize "Save Settings"}}</button>
|
||||||
|
</footer>
|
||||||
36
templates/dialogs/compendiumBrowserSettingsDialog/packs.hbs
Normal file
36
templates/dialogs/compendiumBrowserSettingsDialog/packs.hbs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<div>
|
||||||
|
<div class="types-container">
|
||||||
|
{{#each typePackCollections as |type|}}
|
||||||
|
<div class="type-container">
|
||||||
|
<label>{{type.label}}</label>
|
||||||
|
|
||||||
|
<div class="sources-container">
|
||||||
|
{{#each type.sources as |source|}}
|
||||||
|
<div class="source-container">
|
||||||
|
<div class="source-inner-container">
|
||||||
|
<div class="source-inner-label-container">
|
||||||
|
<a
|
||||||
|
data-action="toggleSource" data-source="{{@key}}" data-type="{{@../key}}"
|
||||||
|
data-tooltip="{{#if source.checked}}{{localize "DAGGERHEART.APPLICATIONS.CompendiumBrowserSettings.disableSource"}}{{else}}{{localize "DAGGERHEART.APPLICATIONS.CompendiumBrowserSettings.enableSource"}}{{/if}}"
|
||||||
|
>
|
||||||
|
<i class="fa-solid {{#if source.checked}}fa-toggle-on{{else}}fa-toggle-off{{/if}}"></i>
|
||||||
|
</a>
|
||||||
|
<label>{{source.label}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checks-container {{#unless source.checked}}collapsed{{/unless}}">
|
||||||
|
{{#each source.packs as |pack|}}
|
||||||
|
<div class="check-container">
|
||||||
|
<input type="checkbox" class="pack-checkbox" data-type="{{pack.type}}" data-pack="{{pack.pack}}" {{checked pack.checked}} />
|
||||||
|
<label>{{pack.label}}</label>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -1,17 +1,12 @@
|
||||||
<header class="dialog-header">
|
<header class="dialog-header">
|
||||||
<div class="dialog-header-inner">
|
<div class="dialog-header-inner">
|
||||||
<h1>
|
<h1>{{ifThen rollConfig.headerTitle rollConfig.headerTitle rollConfig.title}}</h1>
|
||||||
{{#if reactionOverride}}
|
|
||||||
{{localize "DAGGERHEART.CONFIG.FeatureForm.reaction"}}
|
|
||||||
{{else}}
|
|
||||||
{{ifThen rollConfig.headerTitle rollConfig.headerTitle rollConfig.title}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if showReaction}}
|
{{#if showReaction}}
|
||||||
<button class="reaction-roll-controller {{#if reactionOverride}}active{{/if}}" data-action="toggleReaction" data-tooltip-text="{{localize "DAGGERHEART.GENERAL.reactionRoll"}}">
|
<div class="reaction-chip {{#if reactionOverride}}selected{{/if}}" data-action="toggleReaction">
|
||||||
<i class="fa-solid fa-reply"></i>
|
<span><i class="{{ifThen reactionOverride "fa-solid" "fa-regular"}} fa-circle"></i></span>
|
||||||
</button>
|
<span class="label">{{localize "DAGGERHEART.GENERAL.reactionRoll"}}</span>
|
||||||
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
{{#if (and @root.hasRoll @root.activeTagTeamRoll)}}
|
{{#if (and @root.hasRoll @root.activeTagTeamRoll)}}
|
||||||
<div class="tag-team-controller {{#if @root.tagTeamSelected}}selected{{/if}}" data-action="toggleTagTeamRoll">
|
<div class="tag-team-controller {{#if @root.tagTeamSelected}}selected{{/if}}" data-action="toggleTagTeamRoll">
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@
|
||||||
{{#if name}}
|
{{#if name}}
|
||||||
<div class="experience-chip {{#if (includes ../selectedExperiences id)}}selected{{/if}}" data-action="selectExperience" data-key="{{id}}" data-tooltip="{{this.description}}">
|
<div class="experience-chip {{#if (includes ../selectedExperiences id)}}selected{{/if}}" data-action="selectExperience" data-key="{{id}}" data-tooltip="{{this.description}}">
|
||||||
<span><i class="{{ifThen (includes ../selectedExperiences id) "fa-solid" "fa-regular"}} fa-circle"></i></span>
|
<span><i class="{{ifThen (includes ../selectedExperiences id) "fa-solid" "fa-regular"}} fa-circle"></i></span>
|
||||||
<span class="label">{{name}} +{{value}}</span>
|
<span class="label">{{name}} {{numberFormat value sign=true}}</span>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@
|
||||||
{{#each document.system.experiences as |experience id|}}
|
{{#each document.system.experiences as |experience id|}}
|
||||||
<div class="experience-row" data-tooltip-text="{{experience.description}}">
|
<div class="experience-row" data-tooltip-text="{{experience.description}}">
|
||||||
<span class="experience-value">
|
<span class="experience-value">
|
||||||
+{{experience.value}}
|
{{numberFormat experience.value sign=true}}
|
||||||
</span>
|
</span>
|
||||||
<span class="experience-name">{{experience.name}}</span>
|
<span class="experience-name">{{experience.name}}</span>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ Parameters:
|
||||||
data-tooltip="DAGGERHEART.UI.Tooltip.{{ifThen item.system.inVault 'sendToLoadout' 'sendToVault' }}">
|
data-tooltip="DAGGERHEART.UI.Tooltip.{{ifThen item.system.inVault 'sendToLoadout' 'sendToVault' }}">
|
||||||
<i class="fa-solid {{ifThen item.system.inVault 'fa-arrow-up' 'fa-arrow-down'}}"></i>
|
<i class="fa-solid {{ifThen item.system.inVault 'fa-arrow-up' 'fa-arrow-down'}}"></i>
|
||||||
</a>
|
</a>
|
||||||
{{else if (eq type 'effect')}}
|
{{else if (and (eq type 'effect') (not (eq item.type 'beastform')))}}
|
||||||
<a data-action="toggleEffect"
|
<a data-action="toggleEffect"
|
||||||
data-tooltip="DAGGERHEART.UI.Tooltip.{{ifThen item.disabled 'enableEffect' 'disableEffect' }}">
|
data-tooltip="DAGGERHEART.UI.Tooltip.{{ifThen item.disabled 'enableEffect' 'disableEffect' }}">
|
||||||
<i class="{{ifThen item.disabled 'fa-solid fa-toggle-off' 'fa-solid fa-toggle-on'}}"></i>
|
<i class="{{ifThen item.disabled 'fa-solid fa-toggle-off' 'fa-solid fa-toggle-on'}}"></i>
|
||||||
|
|
|
||||||
11
templates/ui/chat/parts/description-part.hbs
Normal file
11
templates/ui/chat/parts/description-part.hbs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<div class="roll-part dice-roll description-section" data-action="expandRoll">
|
||||||
|
<div class="roll-part-header"><div><span>{{localize "DAGGERHEART.GENERAL.description"}}</span></div></div>
|
||||||
|
|
||||||
|
<div class="roll-part-content description-content">
|
||||||
|
<div class="dice-tooltip">
|
||||||
|
<div class="wrapper">
|
||||||
|
<i>{{{actionDescription}}}</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
<div class="chat-roll">
|
<div class="chat-roll">
|
||||||
<div class="roll-part-header"><span>{{title}}</span></div>
|
<div class="roll-part-title"><span>{{title}}</span></div>
|
||||||
{{#if hasRoll}}{{> 'systems/daggerheart/templates/ui/chat/parts/roll-part.hbs'}}{{/if}}
|
{{#if actionDescription}}{{> 'systems/daggerheart/templates/ui/chat/parts/description-part.hbs'}}{{/if}}
|
||||||
|
{{#if hasRoll}}
|
||||||
|
<div class="roll-part-header"><span>{{localize "Result"}}</span></div>
|
||||||
|
{{> 'systems/daggerheart/templates/ui/chat/parts/roll-part.hbs'}}
|
||||||
|
{{/if}}
|
||||||
{{#if (or hasDamage hasHealing)}}{{> 'systems/daggerheart/templates/ui/chat/parts/damage-part.hbs'}}{{/if}}
|
{{#if (or hasDamage hasHealing)}}{{> 'systems/daggerheart/templates/ui/chat/parts/damage-part.hbs'}}{{/if}}
|
||||||
{{#if hasTarget}}{{> 'systems/daggerheart/templates/ui/chat/parts/target-part.hbs'}}{{/if}}
|
{{#if hasTarget}}{{> 'systems/daggerheart/templates/ui/chat/parts/target-part.hbs'}}{{/if}}
|
||||||
<div class="roll-part-header"><div></div></div>
|
<div class="roll-part-header"><div></div></div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
<div class="compendium-sidebar">
|
<div class="compendium-sidebar">
|
||||||
|
{{#if isGM}}<button data-action="openSettings"><i class="fa-solid fa-gear"></i> {{localize "DAGGERHEART.UI.ItemBrowser.browserSettings"}}</button>{{/if}}
|
||||||
<div class="folder-list">
|
<div class="folder-list">
|
||||||
{{#each compendiums}}
|
{{#each compendiums}}
|
||||||
<div class="{{#if selected}} is-selected{{/if}}" data-action="selectFolder" data-folder-id="{{id}}" {{#if folders.length}}data-tooltip="DAGGERHEART.UI.Tooltip.rightClickExtand" data-tooltip-direction="RIGHT"{{/if}}>{{label}}</div>
|
<div class="{{#if selected}} is-selected{{/if}}" data-action="selectFolder" data-folder-id="{{id}}" {{#if folders.length}}data-tooltip="DAGGERHEART.UI.Tooltip.rightClickExtend" data-tooltip-direction="RIGHT"{{/if}}>{{label}}</div>
|
||||||
{{#if folders.length}}
|
{{#if folders.length}}
|
||||||
<div class="subfolder-list">
|
<div class="subfolder-list">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const foundryPath = process.env.FOUNDRY_MAIN_PATH || '../../../../FoundryDev/mai
|
||||||
const dataPath = process.env.FOUNDRY_DATA_PATH || '../../../';
|
const dataPath = process.env.FOUNDRY_DATA_PATH || '../../../';
|
||||||
|
|
||||||
// Run the original command with proper environment
|
// Run the original command with proper environment
|
||||||
const args = ['rollup -c --watch', `node "${foundryPath}" --dataPath="${dataPath}" --noupnp`, 'gulp'];
|
const args = ['rollup -c --watch', `node "\"${foundryPath}\"" --dataPath="${dataPath}" --noupnp`, 'gulp'];
|
||||||
|
|
||||||
spawn('npx', ['concurrently', ...args.map(arg => `"${arg}"`)], {
|
spawn('npx', ['concurrently', ...args.map(arg => `"${arg}"`)], {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue