diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ca744ed5..aef0ddd1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,7 +15,7 @@ jobs: - name: Build Packs run: | - npm run pullYMLtoLDB + npm run pullYMLtoLDBBuild mv --force src/packs/LICENSE packs/LICENSE - name: Build daggerheart.js diff --git a/daggerheart.mjs b/daggerheart.mjs index 4f9c4a44..a2f41735 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -259,7 +259,10 @@ Hooks.on('moveToken', async (movedToken, data) => { const rangeDependantEffects = movedToken.actor.effects.filter(effect => effect.system.rangeDependence?.enabled); const updateEffects = async (disposition, token, effects, effectUpdates) => { - const rangeMeasurement = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.RangeMeasurement); + const rangeMeasurement = game.settings.get( + CONFIG.DH.id, + CONFIG.DH.SETTINGS.gameSettings.variantRules + ).rangeMeasurement; for (let effect of effects.filter(x => x.system.rangeDependence?.enabled)) { const { target, range, type } = effect.system.rangeDependence; diff --git a/lang/en.json b/lang/en.json index 756c6d17..d03ce369 100755 --- a/lang/en.json +++ b/lang/en.json @@ -188,7 +188,8 @@ "manualMulticlassSubclass": { "title": "Multiclass Subclass", "text": "Do you want to add this subclass as your multiclass subclass?" - } + }, + "cannotRemoveCoreExperience": "You are using Levelup Auto. You cannot remove an experience given to you by the rule progression." }, "Companion": { "FIELDS": { @@ -880,7 +881,7 @@ "Gold": { "title": "Gold", "coins": "Coins", - "handfulls": "Handfulls", + "handfuls": "Handfuls", "bags": "Bags", "chests": "Chests" }, @@ -2115,6 +2116,10 @@ "resourceScrollTexts": { "label": "Show Resource Change Scrolltexts", "hint": "When a character is damaged, uses armor etc, a scrolling text will briefly appear by the token to signify this." + }, + "playerCanEditSheet": { + "label": "Players Can Manually Edit Character Settings", + "hint": "Players are allowed to access the manual Character Settings and change their statistics beyond the rules." } } }, @@ -2138,7 +2143,7 @@ "title": "Currency Overrides", "currencyName": "Currency Name", "coinName": "Coin Name", - "handfullName": "Handfull Name", + "handfulName": "Handful Name", "bagName": "Bag Name", "chestName": "Chest Name" }, @@ -2210,10 +2215,6 @@ "actionTokens": { "enabled": { "label": "Enabled" }, "tokens": { "label": "Tokens" } - }, - "useCoins": { - "label": "Use Coins", - "hint": "test" } } }, @@ -2362,7 +2363,8 @@ "openSheetSettings": "Open Settings", "compendiumBrowser": "Compendium Browser", "rulesOn": "Rules On", - "rulesOff": "Rules Off" + "rulesOff": "Rules Off", + "remainingUses": "Uses refresh on {type}" } } } diff --git a/module/applications/characterCreation/characterCreation.mjs b/module/applications/characterCreation/characterCreation.mjs index e44f82fa..d45fe54e 100644 --- a/module/applications/characterCreation/characterCreation.mjs +++ b/module/applications/characterCreation/characterCreation.mjs @@ -1,7 +1,7 @@ import { abilities } from '../../config/actorConfig.mjs'; import { burden } from '../../config/generalConfig.mjs'; -import { createEmbeddedItemWithEffects } from '../../helpers/utils.mjs'; import { ItemBrowser } from '../ui/itemBrowser.mjs'; +import { createEmbeddedItemsWithEffects, createEmbeddedItemWithEffects } from '../../helpers/utils.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; @@ -21,8 +21,8 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl class: this.character.system.class?.value ?? {}, subclass: this.character.system.class?.subclass ?? {}, experiences: { - [foundry.utils.randomID()]: { name: '', value: 2 }, - [foundry.utils.randomID()]: { name: '', value: 2 } + [foundry.utils.randomID()]: { name: '', value: 2, core: true }, + [foundry.utils.randomID()]: { name: '', value: 2, core: true } }, domainCards: { [foundry.utils.randomID()]: {}, @@ -373,13 +373,18 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl ); context.armor = { ...this.equipment.armor, - suggestion: { ...suggestions.armor, taken: suggestions.armor?.uuid === this.equipment.armor?.uuid }, + suggestion: { + ...suggestions.armor, + uuid: suggestions.armor?.uuid, + taken: suggestions.armor?.uuid === this.equipment.armor?.uuid + }, compendium: 'armors' }; context.primaryWeapon = { ...this.equipment.primaryWeapon, suggestion: { ...suggestions.primaryWeapon, + uuid: suggestions.primaryWeapon?.uuid, taken: suggestions.primaryWeapon?.uuid === this.equipment.primaryWeapon?.uuid }, compendium: 'weapons' @@ -388,6 +393,7 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl ...this.equipment.secondaryWeapon, suggestion: { ...suggestions.secondaryWeapon, + uuid: suggestions.secondaryWeapon?.uuid, taken: suggestions.secondaryWeapon?.uuid === this.equipment.secondaryWeapon?.uuid }, disabled: this.equipment.primaryWeapon?.system?.burden === burden.twoHanded.value, @@ -490,22 +496,22 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl static async viewCompendium(event, target) { const type = target.dataset.compendium ?? target.dataset.type; - + const presets = { - compendium: "daggerheart", + compendium: 'daggerheart', folder: type, render: { noFolder: true } }; - if(type == "domains") + if (type == 'domains') presets.filter = { 'level.max': { key: 'level.max', value: 1 }, - 'system.domain': { key: 'system.domain', value: this.setup.class?.system.domains ?? null }, + 'system.domain': { key: 'system.domain', value: this.setup.class?.system.domains ?? null } }; - return this.itemBrowser = await new ItemBrowser({ presets }).render({ force: true }); + return (this.itemBrowser = await new ItemBrowser({ presets }).render({ force: true })); } static async viewItem(_, target) { @@ -574,13 +580,7 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl await createEmbeddedItemWithEffects(this.character, this.setup.community); await createEmbeddedItemWithEffects(this.character, this.setup.class); await createEmbeddedItemWithEffects(this.character, this.setup.subclass); - await this.character.createEmbeddedDocuments( - 'Item', - Object.values(this.setup.domainCards).map(x => ({ - ...x, - effects: x.effects?.map(effect => effect.toObject()) - })) - ); + await createEmbeddedItemsWithEffects(this.character, Object.values(this.setup.domainCards)); if (this.equipment.armor.uuid) await createEmbeddedItemWithEffects(this.character, this.equipment.armor, { @@ -602,24 +602,28 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl if (this.equipment.inventory.choiceB.uuid) await createEmbeddedItemWithEffects(this.character, this.equipment.inventory.choiceB); - await this.character.createEmbeddedDocuments( - 'Item', - this.setup.class.system.inventory.take - .filter(x => x) - .map(x => ({ - ...x, - effects: x.effects?.map(effect => effect.toObject()) - })) + await createEmbeddedItemsWithEffects( + this.character, + this.setup.class.system.inventory.take.filter(x => x) ); - await this.character.update({ - system: { - traits: this.setup.traits, - experiences: this.setup.experiences - } - }); + await this.character.update( + { + system: { + traits: this.setup.traits, + experiences: { + ...this.setup.experiences, + ...Object.keys(this.character.system.experiences).reduce((acc, key) => { + acc[`-=${key}`] = null; + return acc; + }, {}) + } + } + }, + { overwrite: true } + ); - if(this.itemBrowser) this.itemBrowser.close(); + if (this.itemBrowser) this.itemBrowser.close(); this.close(); } @@ -710,6 +714,10 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl return; } + if (item.system.burden === CONFIG.DH.GENERAL.burden.twoHanded.value) { + this.equipment.secondaryWeapon = {}; + } + this.equipment.primaryWeapon = { ...item, uuid: item.uuid }; } else if (item.type === 'weapon' && event.target.closest('.secondary-weapon-card')) { if (this.equipment.primaryWeapon?.system?.burden === burden.twoHanded.value) { diff --git a/module/applications/dialogs/_module.mjs b/module/applications/dialogs/_module.mjs index 11d6dd2b..520c90b6 100644 --- a/module/applications/dialogs/_module.mjs +++ b/module/applications/dialogs/_module.mjs @@ -2,7 +2,6 @@ export { default as BeastformDialog } from './beastformDialog.mjs'; export { default as d20RollDialog } from './d20RollDialog.mjs'; export { default as DamageDialog } from './damageDialog.mjs'; export { default as DamageReductionDialog } from './damageReductionDialog.mjs'; -export { default as DamageSelectionDialog } from './damageSelectionDialog.mjs'; export { default as DeathMove } from './deathMove.mjs'; export { default as Downtime } from './downtime.mjs'; export { default as MulticlassChoiceDialog } from './multiclassChoiceDialog.mjs'; diff --git a/module/applications/dialogs/damageDialog.mjs b/module/applications/dialogs/damageDialog.mjs index cffa6433..2d372725 100644 --- a/module/applications/dialogs/damageDialog.mjs +++ b/module/applications/dialogs/damageDialog.mjs @@ -38,7 +38,9 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application }; get title() { - return game.i18n.localize(`DAGGERHEART.EFFECTS.ApplyLocations.${this.config.isHealing ? 'healing' : 'damage'}Roll.name`); + return game.i18n.localize( + `DAGGERHEART.EFFECTS.ApplyLocations.${this.config.hasHealing ? 'healing' : 'damage'}Roll.name` + ); } async _prepareContext(_options) { @@ -46,7 +48,7 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application context.config = CONFIG.DH; context.title = this.config.title ?? this.title; context.formula = this.roll.constructFormula(this.config); - context.isHealing = this.config.isHealing; + context.hasHealing = this.config.hasHealing; context.directDamage = this.config.directDamage; context.selectedRollMode = this.config.selectedRollMode; context.rollModes = Object.entries(CONFIG.Dice.rollModes).map(([action, { label, icon }]) => ({ diff --git a/module/applications/dialogs/damageSelectionDialog.mjs b/module/applications/dialogs/damageSelectionDialog.mjs deleted file mode 100644 index 3d4b312c..00000000 --- a/module/applications/dialogs/damageSelectionDialog.mjs +++ /dev/null @@ -1,128 +0,0 @@ -// TO DELETE ? - -const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; - -export default class DamageSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) { - constructor(rollString, bonusDamage, resolve, hope = 0) { - super({}); - - this.data = { - rollString, - bonusDamage: bonusDamage.reduce((acc, x) => { - if (x.appliesOn === CONFIG.DH.EFFECTS.applyLocations.damageRoll.id) { - acc.push({ - ...x, - hopeUses: 0 - }); - } - - return acc; - }, []), - hope - }; - this.resolve = resolve; - } - - static DEFAULT_OPTIONS = { - tag: 'form', - classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'damage-selection'], - position: { - width: 400, - height: 'auto' - }, - actions: { - decreaseHopeUse: this.decreaseHopeUse, - increaseHopeUse: this.increaseHopeUse, - rollDamage: this.rollDamage - }, - form: { - handler: this.updateSelection, - submitOnChange: true, - closeOnSubmit: false - } - }; - - /** @override */ - static PARTS = { - damageSelection: { - id: 'damageSelection', - template: 'systems/daggerheart/templates/dialogs/dice-roll/damageSelection.hbs' - } - }; - - /* -------------------------------------------- */ - - /** @inheritDoc */ - get title() { - return `Damage Options`; - } - - async _prepareContext(_options) { - return { - rollString: this.getRollString(), - bonusDamage: this.data.bonusDamage, - hope: this.data.hope + 1, - hopeUsed: this.getHopeUsed() - }; - } - - static updateSelection(event, _, formData) { - const { bonusDamage, ...rest } = foundry.utils.expandObject(formData.object); - - for (var index in bonusDamage) { - this.data.bonusDamage[index].initiallySelected = bonusDamage[index].initiallySelected; - if (bonusDamage[index].hopeUses) { - const value = Number.parseInt(bonusDamage[index].hopeUses); - if (!Number.isNaN(value)) this.data.bonusDamage[index].hopeUses = value; - } - } - - this.data = foundry.utils.mergeObject(this.data, rest); - this.render(true); - } - - getRollString() { - return this.data.rollString.concat( - this.data.bonusDamage.reduce((acc, x) => { - if (x.initiallySelected) { - const nr = 1 + x.hopeUses; - const baseDamage = x.value; - return acc.concat(` + ${nr}${baseDamage}`); - } - - return acc; - }, '') - ); - } - - getHopeUsed() { - return this.data.bonusDamage.reduce((acc, x) => acc + x.hopeUses, 0); - } - - static decreaseHopeUse(_, button) { - const index = Number.parseInt(button.dataset.index); - if (this.data.bonusDamage[index].hopeUses - 1 >= 0) { - this.data.bonusDamage[index].hopeUses -= 1; - this.render(true); - } - } - - static increaseHopeUse(_, button) { - const index = Number.parseInt(button.dataset.index); - if (this.data.bonusDamage[index].hopeUses <= this.data.hope + 1) { - this.data.bonusDamage[index].hopeUses += 1; - this.render(true); - } - } - - static rollDamage(event) { - event.preventDefault(); - - this.resolve({ - rollString: this.getRollString(), - bonusDamage: this.data.bonusDamage, - hopeUsed: this.getHopeUsed() - }); - this.close(); - } -} diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index 8d6bbda1..10708d02 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -94,7 +94,10 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV const actionItems = this.actor.items.reduce((acc, x) => { if (x.system.actions) { const recoverable = x.system.actions.reduce((acc, action) => { - if (action.uses.recovery && (action.uses.recovery === 'shortRest') === this.shortrest) { + if ( + (action.uses.recovery && (action.uses.recovery === 'longRest') === !this.shortrest) || + action.uses.recovery === 'shortRest' + ) { acc.push({ title: x.name, name: action.name, @@ -116,7 +119,8 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV if ( x.system.resource && x.system.resource.type && - (x.system.resource.recovery === 'shortRest') === this.shortrest + ((x.system.resource.recovery === 'longRest') === !this.shortrest || + x.system.resource.recovery === 'shortRest') ) { acc.push({ title: game.i18n.localize(`TYPES.Item.${x.type}`), @@ -226,14 +230,18 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV ) { for (var data of this.refreshables.actionItems) { const action = await foundry.utils.fromUuid(data.uuid); - await action.parent.parent.update({ [`system.actions.${action.id}.uses.value`]: action.uses.max ?? 1 }); + await action.parent.parent.update({ [`system.actions.${action.id}.uses.value`]: 0 }); } for (var data of this.refreshables.resourceItems) { const feature = await foundry.utils.fromUuid(data.uuid); const increasing = feature.system.resource.progression === CONFIG.DH.ITEM.itemResourceProgression.increasing.id; - const resetValue = increasing ? 0 : (feature.system.resource.max ?? 0); + const resetValue = increasing + ? 0 + : feature.system.resource.max + ? Roll.replaceFormulaData(feature.system.resource.max, this.actor) + : 0; await feature.update({ 'system.resource.value': resetValue }); } diff --git a/module/applications/levelup/characterLevelup.mjs b/module/applications/levelup/characterLevelup.mjs index 1ce2bceb..de28f241 100644 --- a/module/applications/levelup/characterLevelup.mjs +++ b/module/applications/levelup/characterLevelup.mjs @@ -289,7 +289,7 @@ export default class DhCharacterLevelUp extends LevelUpBase { const experience = Object.keys(this.actor.system.experiences).find( x => x === data ); - return this.actor.system.experiences[experience]?.description ?? ''; + return this.actor.system.experiences[experience]?.name ?? ''; }); advancement[choiceKey].push({ data: data, value: checkbox.value }); break; diff --git a/module/applications/levelup/levelup.mjs b/module/applications/levelup/levelup.mjs index f1f4226c..4cca1194 100644 --- a/module/applications/levelup/levelup.mjs +++ b/module/applications/levelup/levelup.mjs @@ -47,10 +47,12 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2) static PARTS = { tabs: { template: 'systems/daggerheart/templates/levelup/tabs/tab-navigation.hbs' }, - advancements: { template: 'systems/daggerheart/templates/levelup/tabs/advancements.hbs' }, + advancements: { + template: 'systems/daggerheart/templates/levelup/tabs/advancements.hbs' + }, selections: { template: 'systems/daggerheart/templates/levelup/tabs/selections.hbs', - scrollable: ['.selections'] + scrollable: ['.levelup-selections-container'] }, summary: { template: 'systems/daggerheart/templates/levelup/tabs/summary.hbs' }, footer: { template: 'systems/daggerheart/templates/levelup/tabs/footer.hbs' } @@ -536,29 +538,28 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2) static async viewCompendium(event, target) { const type = target.dataset.compendium ?? target.dataset.type; - + const presets = { - compendium: "daggerheart", + compendium: 'daggerheart', folder: type, render: { noFolder: true } }; - if(type == "domains") { + if (type == 'domains') { const domains = this.actor.system.domains, multiclassDomain = this.levelup.classUpgradeChoices?.multiclass?.domain; if (multiclassDomain) { - if (!domains.includes(x => x === multiclassDomain)) - domains.push(multiclassDomain); + if (!domains.includes(x => x === multiclassDomain)) domains.push(multiclassDomain); } presets.filter = { 'level.max': { key: 'level.max', value: this.levelup.currentLevel }, - 'system.domain': { key: 'system.domain', value: domains }, + 'system.domain': { key: 'system.domain', value: domains } }; } - return this.itemBrowser = await new ItemBrowser({ presets }).render({ force: true }); + return (this.itemBrowser = await new ItemBrowser({ presets }).render({ force: true })); } static async selectPreview(_, button) { @@ -659,7 +660,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2) }, {}); await this.actor.levelUp(levelupData); - if(this.itemBrowser) this.itemBrowser.close(); + if (this.itemBrowser) this.itemBrowser.close(); this.close(); } } diff --git a/module/applications/settings/_module.mjs b/module/applications/settings/_module.mjs index de11242e..b565777c 100644 --- a/module/applications/settings/_module.mjs +++ b/module/applications/settings/_module.mjs @@ -1,5 +1,4 @@ export { default as DhAppearanceSettings } from './appearanceSettings.mjs'; export { default as DhAutomationSettings } from './automationSettings.mjs'; export { default as DhHomebrewSettings } from './homebrewSettings.mjs'; -export { default as DhRangeMeasurementSettings } from './rangeMeasurementSettings.mjs'; export { default as DhVariantRuleSettings } from './variantRuleSettings.mjs'; diff --git a/module/applications/settings/rangeMeasurementSettings.mjs b/module/applications/settings/rangeMeasurementSettings.mjs deleted file mode 100644 index 410b2cbe..00000000 --- a/module/applications/settings/rangeMeasurementSettings.mjs +++ /dev/null @@ -1,66 +0,0 @@ -import { DhRangeMeasurement } from '../../data/settings/_module.mjs'; - -const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; - -export default class DhRangeMeasurementSettings extends HandlebarsApplicationMixin(ApplicationV2) { - constructor() { - super({}); - - this.settings = new DhRangeMeasurement( - game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.RangeMeasurement).toObject() - ); - } - - get title() { - return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title'); - } - - static DEFAULT_OPTIONS = { - tag: 'form', - id: 'daggerheart-automation-settings', - classes: ['daggerheart', 'dialog', 'dh-style', 'setting'], - position: { width: '600', height: 'auto' }, - window: { - icon: 'fa-solid fa-gears' - }, - actions: { - reset: this.reset, - save: this.save - }, - form: { handler: this.updateData, submitOnChange: true } - }; - - static PARTS = { - main: { - template: 'systems/daggerheart/templates/settings/range-measurement-settings.hbs' - } - }; - - async _prepareContext(_options) { - const context = await super._prepareContext(_options); - context.settingFields = this.settings; - - return context; - } - - static async updateData(event, element, formData) { - const updatedSettings = foundry.utils.expandObject(formData.object); - - await this.settings.updateSource(updatedSettings); - this.render(); - } - - static async reset() { - this.settings = new DhRangeMeasurement(); - this.render(); - } - - static async save() { - await game.settings.set( - CONFIG.DH.id, - CONFIG.DH.SETTINGS.gameSettings.RangeMeasurement, - this.settings.toObject() - ); - this.close(); - } -} diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 82b0fff3..55662f90 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -27,7 +27,7 @@ export default class CharacterSheet extends DHBaseActorSheet { toggleResourceDice: CharacterSheet.#toggleResourceDice, handleResourceDice: CharacterSheet.#handleResourceDice, useDowntime: this.useDowntime, - tempBrowser: CharacterSheet.#tempBrowser, + tempBrowser: CharacterSheet.#tempBrowser }, window: { resizable: true @@ -158,7 +158,7 @@ export default class CharacterSheet extends DHBaseActorSheet { currency: { title: game.i18n.localize('DAGGERHEART.CONFIG.Gold.title'), coins: game.i18n.localize('DAGGERHEART.CONFIG.Gold.coins'), - handfulls: game.i18n.localize('DAGGERHEART.CONFIG.Gold.handfulls'), + handfuls: game.i18n.localize('DAGGERHEART.CONFIG.Gold.handfuls'), bags: game.i18n.localize('DAGGERHEART.CONFIG.Gold.bags'), chests: game.i18n.localize('DAGGERHEART.CONFIG.Gold.chests') } @@ -180,6 +180,13 @@ export default class CharacterSheet extends DHBaseActorSheet { async _preparePartContext(partId, context, options) { context = await super._preparePartContext(partId, context, options); switch (partId) { + case 'header': + const { playerCanEditSheet, levelupAuto } = game.settings.get( + CONFIG.DH.id, + CONFIG.DH.SETTINGS.gameSettings.Automation + ); + context.showSettings = game.user.isGM || !levelupAuto || (levelupAuto && playerCanEditSheet); + break; case 'loadout': await this._prepareLoadoutContext(context, options); break; @@ -190,6 +197,7 @@ export default class CharacterSheet extends DHBaseActorSheet { await this._prepareBiographyContext(context, options); break; } + return context; } @@ -596,7 +604,7 @@ export default class CharacterSheet extends DHBaseActorSheet { const { key } = button.dataset; const presets = { - compendium: "daggerheart", + compendium: 'daggerheart', folder: key, render: { noFolder: true diff --git a/module/applications/sheets/actors/environment.mjs b/module/applications/sheets/actors/environment.mjs index 7a9c92ac..70f833de 100644 --- a/module/applications/sheets/actors/environment.mjs +++ b/module/applications/sheets/actors/environment.mjs @@ -7,7 +7,11 @@ export default class DhpEnvironment extends DHBaseActorSheet { static DEFAULT_OPTIONS = { classes: ['environment'], position: { - width: 500 + width: 500, + height: 725 + }, + window: { + resizable: true }, actions: {}, dragDrop: [{ dragSelector: '.action-section .inventory-item', dropSelector: null }] diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 7c89bf0f..2a02ba01 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -85,7 +85,7 @@ export default function DHApplicationMixin(Base) { toggleEffect: DHSheetV2.#toggleEffect, toggleExtended: DHSheetV2.#toggleExtended, addNewItem: DHSheetV2.#addNewItem, - browseItem: DHSheetV2.#browseItem, + browseItem: DHSheetV2.#browseItem }, contextMenus: [ { @@ -327,17 +327,31 @@ export default function DHApplicationMixin(Base) { if (usable) options.unshift({ - name: 'DAGGERHEART.APPLICATIONS.ContextMenu.useItem', - icon: 'fa-solid fa-burst', + name: 'DAGGERHEART.GENERAL.damage', + icon: 'fa-solid fa-explosion', condition: target => { const doc = getDocFromElementSync(target); - return doc && !(doc.type === 'domainCard' && doc.system.inVault); + return doc?.system?.attack?.damage.parts.length || doc?.damage?.parts.length; }, - callback: async (target, event) => (await getDocFromElement(target)).use(event) + callback: async (target, event) => { + const doc = await getDocFromElement(target), + action = doc?.system?.attack ?? doc; + return action && action.use(event, { byPassRoll: true }); + } }); + options.unshift({ + name: 'DAGGERHEART.APPLICATIONS.ContextMenu.useItem', + icon: 'fa-solid fa-burst', + condition: target => { + const doc = getDocFromElementSync(target); + return doc && !(doc.type === 'domainCard' && doc.system.inVault); + }, + callback: async (target, event) => (await getDocFromElement(target)).use(event) + }); + if (toChat) - options.unshift({ + options.push({ name: 'DAGGERHEART.APPLICATIONS.ContextMenu.sendToChat', icon: 'fa-solid fa-message', callback: async target => (await getDocFromElement(target)).toChat(this.document.id) @@ -419,25 +433,22 @@ export default function DHApplicationMixin(Base) { classes: ['dh-style', 'two-big-buttons'], buttons: [ { - action: "create", - label: "Create Item", - icon: "fa-solid fa-plus" + action: 'create', + label: 'Create Item', + icon: 'fa-solid fa-plus' }, { - action: "browse", - label: "Browse Compendium", - icon: "fa-solid fa-book" + action: 'browse', + label: 'Browse Compendium', + icon: 'fa-solid fa-book' } ] }); - if(!createChoice) return; - - if(createChoice === "browse") - return DHSheetV2.#browseItem.call(this, event, target); - else - return DHSheetV2.#createDoc.call(this, event, target); + if (!createChoice) return; + if (createChoice === 'browse') return DHSheetV2.#browseItem.call(this, event, target); + else return DHSheetV2.#createDoc.call(this, event, target); } static async #browseItem(event, target) { @@ -450,8 +461,8 @@ export default function DHApplicationMixin(Base) { case 'consumable': case 'armor': case 'weapon': - presets.compendium = "daggerheart"; - presets.folder = "equipments"; + presets.compendium = 'daggerheart'; + presets.folder = 'equipments'; presets.render = { noFolder: true }; @@ -460,14 +471,14 @@ export default function DHApplicationMixin(Base) { }; break; case 'domainCard': - presets.compendium = "daggerheart"; - presets.folder = "domains"; + presets.compendium = 'daggerheart'; + presets.folder = 'domains'; presets.render = { noFolder: true }; presets.filter = { 'level.max': { key: 'level.max', value: this.document.system.levelData.level.current }, - 'system.domain': { key: 'system.domain', value: this.document.system.domains }, + 'system.domain': { key: 'system.domain', value: this.document.system.domains } }; break; default: diff --git a/module/applications/sheets/api/base-actor.mjs b/module/applications/sheets/api/base-actor.mjs index 56e48232..b664929c 100644 --- a/module/applications/sheets/api/base-actor.mjs +++ b/module/applications/sheets/api/base-actor.mjs @@ -22,7 +22,8 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { }, actions: { openSettings: DHBaseActorSheet.#openSettings, - sendExpToChat: DHBaseActorSheet.#sendExpToChat + sendExpToChat: DHBaseActorSheet.#sendExpToChat, + increaseActionUses: event => DHBaseActorSheet.#modifyActionUses(event, true) }, contextMenus: [ { @@ -70,6 +71,15 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { return context; } + /**@inheritdoc */ + _attachPartListeners(partId, htmlElement, options) { + super._attachPartListeners(partId, htmlElement, options); + + htmlElement.querySelectorAll('.item-button .action-uses-button').forEach(element => { + element.addEventListener('contextmenu', DHBaseActorSheet.#modifyActionUses); + }); + } + /** * Prepare render context for the Effect part. * @param {ApplicationRenderContext} context @@ -154,6 +164,19 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { cls.create(msg); } + /** + * + */ + static async #modifyActionUses(event, increase) { + event.stopPropagation(); + event.preventDefault(); + const actionId = event.target.dataset.itemUuid; + const action = await foundry.utils.fromUuid(actionId); + + const newValue = (action.uses.value ?? 0) + (increase ? 1 : -1); + await action.update({ 'uses.value': Math.min(Math.max(newValue, 0), action.uses.max ?? 0) }); + } + /* -------------------------------------------- */ /* Application Drag/Drop */ /* -------------------------------------------- */ diff --git a/module/applications/sheets/items/feature.mjs b/module/applications/sheets/items/feature.mjs index fcbec97f..1575067b 100644 --- a/module/applications/sheets/items/feature.mjs +++ b/module/applications/sheets/items/feature.mjs @@ -3,7 +3,6 @@ import DHBaseItemSheet from '../api/base-item.mjs'; export default class FeatureSheet extends DHBaseItemSheet { /** @inheritDoc */ static DEFAULT_OPTIONS = { - id: 'daggerheart-feature', classes: ['feature'], actions: {} }; diff --git a/module/applications/sheets/items/subclass.mjs b/module/applications/sheets/items/subclass.mjs index 54250f51..5c731777 100644 --- a/module/applications/sheets/items/subclass.mjs +++ b/module/applications/sheets/items/subclass.mjs @@ -5,7 +5,7 @@ export default class SubclassSheet extends DHBaseItemSheet { static DEFAULT_OPTIONS = { classes: ['subclass'], position: { width: 600 }, - window: { resizable: false } + window: { resizable: true } }; /**@override */ diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 958d0386..fd9ab096 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -194,8 +194,12 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo event.stopPropagation(); const item = await foundry.utils.fromUuid(message.system.origin); - const action = item.system.actions.get(event.currentTarget.id); - await item.use(action); + const action = + item.system.attack?.id === event.currentTarget.id + ? item.system.attack + : item.system.actions.get(event.currentTarget.id); + if (event.currentTarget.dataset.directDamage) action.use(event, { byPassRoll: true }); + else action.use(event); } async actionUseButton(event, message) { diff --git a/module/applications/ui/combatTracker.mjs b/module/applications/ui/combatTracker.mjs index b3348fe2..d3d8eb66 100644 --- a/module/applications/ui/combatTracker.mjs +++ b/module/applications/ui/combatTracker.mjs @@ -88,7 +88,10 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C } } - await this.viewed.update({ turn: this.viewed.turn === toggleTurn ? null : toggleTurn }); + await this.viewed.update({ + turn: this.viewed.turn === toggleTurn ? null : toggleTurn, + round: this.viewed.round + 1 + }); await combatant.update(update); } diff --git a/module/canvas/placeables/measuredTemplate.mjs b/module/canvas/placeables/measuredTemplate.mjs index 42601d6c..c9950650 100644 --- a/module/canvas/placeables/measuredTemplate.mjs +++ b/module/canvas/placeables/measuredTemplate.mjs @@ -4,8 +4,8 @@ export default class DhMeasuredTemplate extends foundry.canvas.placeables.Measur const rangeMeasurementSettings = game.settings.get( CONFIG.DH.id, - CONFIG.DH.SETTINGS.gameSettings.RangeMeasurement - ); + CONFIG.DH.SETTINGS.gameSettings.variantRules + ).rangeMeasurement; if (rangeMeasurementSettings.enabled) { const splitRulerText = this.ruler.text.split(' '); if (splitRulerText.length > 0) { @@ -29,7 +29,7 @@ export default class DhMeasuredTemplate extends foundry.canvas.placeables.Measur if (distance <= settings.far) { return game.i18n.localize('DAGGERHEART.CONFIG.Range.far.name'); } - if (distance <= settings.veryFar) { + if (distance > settings.far) { return game.i18n.localize('DAGGERHEART.CONFIG.Range.veryFar.name'); } diff --git a/module/canvas/placeables/ruler.mjs b/module/canvas/placeables/ruler.mjs index 498ee3df..6585a1cd 100644 --- a/module/canvas/placeables/ruler.mjs +++ b/module/canvas/placeables/ruler.mjs @@ -5,7 +5,7 @@ export default class DhpRuler extends foundry.canvas.interaction.Ruler { const context = super._getWaypointLabelContext(waypoint, state); if (!context) return; - const range = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.RangeMeasurement); + const range = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).rangeMeasurement; if (range.enabled) { const distance = DhMeasuredTemplate.getDistanceLabel(waypoint.measurement.distance.toNearest(0.01), range); diff --git a/module/canvas/placeables/token.mjs b/module/canvas/placeables/token.mjs index 4c2ae4ed..e6179b10 100644 --- a/module/canvas/placeables/token.mjs +++ b/module/canvas/placeables/token.mjs @@ -53,4 +53,40 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token { this.effects.renderable = true; this.renderFlags.set({ refreshEffects: true }); } + + /** @inheritDoc */ + _drawBar(number, bar, data) { + const val = Number(data.value); + const pct = Math.clamp(val, 0, data.max) / data.max; + + // Determine sizing + const { width, height } = this.document.getSize(); + const s = canvas.dimensions.uiScale; + const bw = width; + const bh = 8 * (this.document.height >= 2 ? 1.5 : 1) * s; + + // Determine the color to use + const fillColor = + number === 0 ? foundry.utils.Color.fromRGB([1, 0, 0]) : foundry.utils.Color.fromString('#0032b1'); + + // Draw the bar + const widthUnit = bw / data.max; + bar.clear().lineStyle(s, 0x000000, 1.0); + const sections = [...Array(data.max).keys()]; + for (let mark of sections) { + const x = mark * widthUnit; + const marked = mark + 1 <= data.value; + const color = marked ? fillColor : foundry.utils.Color.fromRGB([0, 0, 0]); + if (mark === 0 || mark === sections.length - 1) { + bar.beginFill(color, marked ? 1.0 : 0.5).drawRect(x, 0, widthUnit, bh, 2 * s); // Would like drawRoundedRect, but it's very troublsome with the corners. Leaving for now. + } else { + bar.beginFill(color, marked ? 1.0 : 0.5).drawRect(x, 0, widthUnit, bh, 2 * s); + } + } + + // Set position + const posY = number === 0 ? height - bh : 0; + bar.position.set(0, posY); + return true; + } } diff --git a/module/canvas/placeables/tokenRuler.mjs b/module/canvas/placeables/tokenRuler.mjs index ea30ca95..ff8fc0d5 100644 --- a/module/canvas/placeables/tokenRuler.mjs +++ b/module/canvas/placeables/tokenRuler.mjs @@ -5,7 +5,7 @@ export default class DhpTokenRuler extends foundry.canvas.placeables.tokens.Toke const context = super._getWaypointLabelContext(waypoint, state); if (!context) return; - const range = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.RangeMeasurement); + const range = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).rangeMeasurement; if (range.enabled) { const distance = DhMeasuredTemplate.getDistanceLabel(waypoint.measurement.distance.toNearest(0.01), range); diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 09814f1a..7785b6a6 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -21,7 +21,7 @@ export const ruleChoice = { } }; -export const range = { +export const templateRanges = { self: { id: 'self', short: 's', @@ -56,7 +56,11 @@ export const range = { label: 'DAGGERHEART.CONFIG.Range.far.name', description: 'DAGGERHEART.CONFIG.Range.far.description', distance: 20 - }, + } +}; + +export const range = { + ...templateRanges, veryFar: { id: 'veryFar', short: 'vf', @@ -479,7 +483,8 @@ export const multiplierTypes = { cast: 'Spellcast', scale: 'Cost Scaling', result: 'Roll Result', - flat: 'Flat' + flat: 'Flat', + tier: 'Tier' }; export const diceSetNumbers = { diff --git a/module/config/itemConfig.mjs b/module/config/itemConfig.mjs index 95e55daf..e9d8de4c 100644 --- a/module/config/itemConfig.mjs +++ b/module/config/itemConfig.mjs @@ -857,7 +857,7 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.greedy.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.greedy.description', img: 'icons/commodities/currency/coins-crown-stack-gold.webp', - // Should cost handfull of gold, + // Should cost handful of gold, effects: [ { name: 'DAGGERHEART.CONFIG.WeaponFeature.greedy.actions.greed.name', diff --git a/module/config/settingsConfig.mjs b/module/config/settingsConfig.mjs index df3cb619..dd8aeffe 100644 --- a/module/config/settingsConfig.mjs +++ b/module/config/settingsConfig.mjs @@ -20,7 +20,6 @@ export const menu = { export const gameSettings = { Automation: 'Automation', Homebrew: 'Homebrew', - RangeMeasurement: 'RangeMeasurement', appearance: 'Appearance', variantRules: 'VariantRules', Resources: { diff --git a/module/data/action/attackAction.mjs b/module/data/action/attackAction.mjs index 4713938c..1ba5f91e 100644 --- a/module/data/action/attackAction.mjs +++ b/module/data/action/attackAction.mjs @@ -34,8 +34,8 @@ export default class DHAttackAction extends DHDamageAction { }; } - async use(event, ...args) { - const result = await super.use(event, args); + async use(event, options) { + const result = await super.use(event, options); const { updateCountdowns } = game.system.api.applications.ui.DhCountdowns; await updateCountdowns(CONFIG.DH.GENERAL.countdownTypes.characterAttack.id); diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index b8655c91..070864da 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -111,12 +111,13 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel return actorData; } - async use(event, ...args) { + async use(event, options = {}) { if (!this.actor) throw new Error("An Action can't be used outside of an Actor context."); if (this.chatDisplay) await this.toChat(); - let config = this.prepareConfig(event); + let { byPassRoll } = options, + config = this.prepareConfig(event, byPassRoll); for (let i = 0; i < this.constructor.extraSchemas.length; i++) { let clsField = this.constructor.getActionField(this.constructor.extraSchemas[i]); if (clsField?.prepareConfig) { @@ -133,14 +134,14 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel if (!config) return; } - if (this.hasRoll) { + if (config.hasRoll) { const rollConfig = this.prepareRoll(config); config.roll = rollConfig; config = await this.actor.diceRoll(config); if (!config) return; } - if (this.doFollowUp()) { + if (this.doFollowUp(config)) { if (this.rollDamage && this.damage.parts.length) await this.rollDamage(event, config); else if (this.trigger) await this.trigger(event, config); else if (this.hasSave || this.hasEffect) { @@ -160,7 +161,8 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel } /* */ - prepareConfig(event) { + prepareConfig(event, byPass = false) { + const hasRoll = this.getUseHasRoll(byPass); return { event, title: `${this.item.name}: ${this.name}`, @@ -170,10 +172,10 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel actor: this.actor.uuid }, dialog: { - configure: this.hasRoll + configure: hasRoll }, type: this.type, - hasRoll: this.hasRoll, + hasRoll: hasRoll, hasDamage: this.damage?.parts?.length && this.type !== 'healing', hasHealing: this.damage?.parts?.length && this.type === 'healing', hasEffect: !!this.effects?.length, @@ -182,12 +184,12 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel selectedRollMode: game.settings.get('core', 'rollMode'), isFastForward: event.shiftKey, data: this.getRollData(), - evaluate: this.hasRoll + evaluate: hasRoll }; } requireConfigurationDialog(config) { - return !config.event.shiftKey && !this.hasRoll && (config.costs?.length || config.uses); + return !config.event.shiftKey && !config.hasRoll && (config.costs?.length || config.uses); } prepareRoll() { @@ -205,7 +207,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel } doFollowUp(config) { - return !this.hasRoll; + return !config.hasRoll; } async consume(config, successCost = false) { @@ -220,16 +222,13 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel }; } } - + const resources = config.costs - .filter(c => - c.enabled !== false - && - ( - (!successCost && (!c.consumeOnSuccess || config.roll?.success)) - || - (successCost && c.consumeOnSuccess) - ) + .filter( + c => + c.enabled !== false && + ((!successCost && (!c.consumeOnSuccess || config.roll?.success)) || + (successCost && c.consumeOnSuccess)) ) .map(c => { const resource = usefulResources[c.key]; @@ -242,21 +241,23 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel }); await this.actor.modifyResource(resources); - if (config.uses?.enabled - && - ( - (!successCost && (!config.uses?.consumeOnSuccess || config.roll?.success)) - || - (successCost && config.uses?.consumeOnSuccess) - ) - ) this.update({ 'uses.value': this.uses.value + 1 }); + if ( + config.uses?.enabled && + ((!successCost && (!config.uses?.consumeOnSuccess || config.roll?.success)) || + (successCost && config.uses?.consumeOnSuccess)) + ) + this.update({ 'uses.value': this.uses.value + 1 }); - if(config.roll?.success || successCost) - (config.message ?? config.parent).update({'system.successConsumed': true}) + if (config.roll?.success || successCost) + (config.message ?? config.parent).update({ 'system.successConsumed': true }); } /* */ /* ROLL */ + getUseHasRoll(byPass = false) { + return this.hasRoll && !byPass; + } + get hasRoll() { return !!this.roll?.type; } @@ -301,11 +302,9 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel } async applyEffect(effect, actor) { - const origin = effect.parent?.parent ? effect.parent.parent.uuid : effect.parent.uuid; - // Enable an existing effect on the target if it originated from this effect - const existingEffect = actor.effects.find(e => e.origin === origin); + const existingEffect = actor.effects.find(e => e.origin === effect.uuid); if (existingEffect) { - return existingEffect.update( + return effect.update( foundry.utils.mergeObject({ ...effect.constructor.getInitialDuration(), disabled: false @@ -318,7 +317,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel ...effect.toObject(), disabled: false, transfer: false, - origin: origin + origin: effect.uuid }); await ActiveEffect.implementation.create(effectData, { parent: actor }); } diff --git a/module/data/action/beastformAction.mjs b/module/data/action/beastformAction.mjs index 836024ff..8c2dd31e 100644 --- a/module/data/action/beastformAction.mjs +++ b/module/data/action/beastformAction.mjs @@ -4,7 +4,7 @@ import DHBaseAction from './baseAction.mjs'; export default class DhBeastformAction extends DHBaseAction { static extraSchemas = [...super.extraSchemas, 'beastform']; - async use(event, ...args) { + async use(event, options) { const beastformConfig = this.prepareBeastformConfig(); const abort = await this.handleActiveTransformations(); @@ -20,7 +20,7 @@ export default class DhBeastformAction extends DHBaseAction { const { selected, evolved, hybrid } = await BeastformDialog.configure(beastformConfig, this.item); if (!selected) return; - const result = await super.use(event, args); + const result = await super.use(event, options); if (!result) return; await this.transform(selected, evolved, hybrid); diff --git a/module/data/action/damageAction.mjs b/module/data/action/damageAction.mjs index 40fa2a12..88eec481 100644 --- a/module/data/action/damageAction.mjs +++ b/module/data/action/damageAction.mjs @@ -6,7 +6,7 @@ export default class DHDamageAction extends DHBaseAction { getFormulaValue(part, data) { let formulaValue = part.value; - if (this.hasRoll && part.resultBased && data.system.roll.result.duality === -1) return part.valueAlt; + if (data.hasRoll && part.resultBased && data.system.roll.result.duality === -1) return part.valueAlt; const isAdversary = this.actor.type === 'adversary'; if (isAdversary && this.actor.system.type === CONFIG.DH.ACTOR.adversaryTypes.horde.id) { @@ -51,7 +51,7 @@ export default class DHDamageAction extends DHBaseAction { dialog: {}, data: this.getRollData(), targetSelection: systemData.targets.length > 0 - } + }; if (this.hasSave) config.onSave = this.save.damageMod; if (data.system) { config.source.message = data._id; diff --git a/module/data/action/macroAction.mjs b/module/data/action/macroAction.mjs index bfdc8f6b..c4a08df7 100644 --- a/module/data/action/macroAction.mjs +++ b/module/data/action/macroAction.mjs @@ -10,8 +10,6 @@ export default class DHMacroAction extends DHBaseAction { } async trigger(event, ...args) { - // const config = await super.use(event, args); - // if (['error', 'warning'].includes(config.type)) return; const fixUUID = !this.documentUUID.includes('Macro.') ? `Macro.${this.documentUUID}` : this.documentUUID, macro = await fromUuid(fixUUID); try { diff --git a/module/data/action/summonAction.mjs b/module/data/action/summonAction.mjs index 13b4ee99..b06f1d38 100644 --- a/module/data/action/summonAction.mjs +++ b/module/data/action/summonAction.mjs @@ -11,7 +11,6 @@ export default class DHSummonAction extends DHBaseAction { async trigger(event, ...args) { if (!this.canSummon || !canvas.scene) return; - // const config = await super.use(event, args); } get canSummon() { diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 8e665265..d4544d2c 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -68,12 +68,13 @@ export default class DhCharacter extends BaseDataActor { new fields.SchemaField({ name: new fields.StringField(), value: new fields.NumberField({ integer: true, initial: 0 }), - description: new fields.StringField() + description: new fields.StringField(), + core: new fields.BooleanField({ initial: false }) }) ), gold: new fields.SchemaField({ coins: new fields.NumberField({ initial: 0, integer: true }), - handfulls: new fields.NumberField({ initial: 0, integer: true }), + handfuls: new fields.NumberField({ initial: 1, integer: true }), bags: new fields.NumberField({ initial: 0, integer: true }), chests: new fields.NumberField({ initial: 0, integer: true }) }), @@ -573,7 +574,10 @@ export default class DhCharacter extends BaseDataActor { case 'experience': selection.data.forEach(id => { const experience = this.experiences[id]; - if (experience) experience.value += selection.value; + if (experience) { + experience.value += selection.value; + experience.leveledUp = true; + } }); break; } @@ -620,6 +624,23 @@ export default class DhCharacter extends BaseDataActor { }; } + async _preUpdate(changes, options, userId) { + const allowed = await super._preUpdate(changes, options, userId); + if (allowed === false) return; + + /* The first two experiences are always marked as core */ + if (changes.system?.experiences && Object.keys(this.experiences).length < 2) { + const experiences = new Set(Object.keys(this.experiences)); + const changeExperiences = new Set(Object.keys(changes.system.experiences)); + const newExperiences = Array.from(changeExperiences.difference(experiences)); + + for (var i = 0; i < Math.min(newExperiences.length, 2 - experiences.size); i++) { + const experience = newExperiences[i]; + changes.system.experiences[experience].core = true; + } + } + } + async _preDelete() { if (this.companion) { this.companion.updateLevel(1); diff --git a/module/data/chat-message/adversaryRoll.mjs b/module/data/chat-message/adversaryRoll.mjs index d6c8851c..fa6e48a6 100644 --- a/module/data/chat-message/adversaryRoll.mjs +++ b/module/data/chat-message/adversaryRoll.mjs @@ -1,20 +1,21 @@ const fields = foundry.data.fields; -const targetsField = () => new fields.ArrayField( - new fields.SchemaField({ - id: new fields.StringField({}), - actorId: new fields.StringField({}), - name: new fields.StringField({}), - img: new fields.StringField({}), - difficulty: new fields.NumberField({ integer: true, nullable: true }), - evasion: new fields.NumberField({ integer: true }), - hit: new fields.BooleanField({ initial: false }), - saved: new fields.SchemaField({ - result: new fields.NumberField(), - success: new fields.BooleanField({ nullable: true, initial: null }) +const targetsField = () => + new fields.ArrayField( + new fields.SchemaField({ + id: new fields.StringField({}), + actorId: new fields.StringField({}), + name: new fields.StringField({}), + img: new fields.StringField({}), + difficulty: new fields.NumberField({ integer: true, nullable: true }), + evasion: new fields.NumberField({ integer: true }), + hit: new fields.BooleanField({ initial: false }), + saved: new fields.SchemaField({ + result: new fields.NumberField(), + success: new fields.BooleanField({ nullable: true, initial: null }) + }) }) - }) -) + ); export default class DHActorRoll extends foundry.abstract.TypeDataModel { targetHook = null; @@ -40,27 +41,25 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { action: new fields.StringField() }), damage: new fields.ObjectField(), - costs: new fields.ArrayField( - new fields.ObjectField() - ), + costs: new fields.ArrayField(new fields.ObjectField()), successConsumed: new fields.BooleanField({ initial: false }) }; } get actionActor() { - if(!this.source.actor) return null; + if (!this.source.actor) return null; return fromUuidSync(this.source.actor); } get actionItem() { const actionActor = this.actionActor; - if(!actionActor || !this.source.item) return null; + if (!actionActor || !this.source.item) return null; return actionActor.items.get(this.source.item); } get action() { const actionItem = this.actionItem; - if(!actionItem || !this.source.action) return null; + if (!actionItem || !this.source.action) return null; return actionItem.system.actionsList?.find(a => a.id === this.source.action); } @@ -76,90 +75,85 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { this.targetSelection = mode; this.updateTargets(); this.registerTargetHook(); - this.parent.update( - { - system: { - targetSelection: this.targetSelection, - oldTargets: this.oldTargets - } + this.parent.update({ + system: { + targetSelection: this.targetSelection, + oldTargets: this.oldTargets } - ); + }); } get hitTargets() { - return this.currentTargets.filter(t => (t.hit || !this.hasRoll || !this.targetSelection)); + return this.currentTargets.filter(t => t.hit || !this.hasRoll || !this.targetSelection); } async updateTargets() { this.currentTargets = this.getTargetList(); - if(!this.targetSelection) { + if (!this.targetSelection) { this.currentTargets.forEach(ct => { - if(this.targets.find(t => t.actorId === ct.actorId)) return; + if (this.targets.find(t => t.actorId === ct.actorId)) return; const indexTarget = this.oldTargets.findIndex(ot => ot.actorId === ct.actorId); - if(indexTarget === -1) - this.oldTargets.push(ct); + if (indexTarget === -1) this.oldTargets.push(ct); }); - if(this.hasSave) this.setPendingSaves(); - if(this.currentTargets.length) { - if(!this.parent._id) return; - const updates = await this.parent.update( - { - system: { - oldTargets: this.oldTargets - } + if (this.hasSave) this.setPendingSaves(); + if (this.currentTargets.length) { + if (!this.parent._id) return; + const updates = await this.parent.update({ + system: { + oldTargets: this.oldTargets } - ); - if(!updates && ui.chat.collection.get(this.parent.id)) - ui.chat.updateMessage(this.parent); + }); + if (!updates && ui.chat.collection.get(this.parent.id)) ui.chat.updateMessage(this.parent); } } } registerTargetHook() { - if(this.targetSelection && this.targetHook !== null) { - Hooks.off("targetToken", this.targetHook); + if (this.targetSelection && this.targetHook !== null) { + Hooks.off('targetToken', this.targetHook); this.targetHook = null; - } else if(!this.targetSelection && this.targetHook === null) { - this.targetHook = Hooks.on("targetToken", foundry.utils.debounce(this.updateTargets.bind(this), 50)); + } else if (!this.targetSelection && this.targetHook === null) { + this.targetHook = Hooks.on('targetToken', foundry.utils.debounce(this.updateTargets.bind(this), 50)); } } prepareDerivedData() { - if(this.hasTarget) { + if (this.hasTarget) { this.hasHitTarget = this.targets.filter(t => t.hit === true).length > 0; this.updateTargets(); this.registerTargetHook(); - if(this.targetSelection === true) { - this.targetShort = this.targets.reduce((a,c) => { - if(c.hit) a.hit += 1; - else c.miss += 1; - return a; - }, {hit: 0, miss: 0}) + if (this.targetSelection === true) { + this.targetShort = this.targets.reduce( + (a, c) => { + if (c.hit) a.hit += 1; + else a.miss += 1; + return a; + }, + { hit: 0, miss: 0 } + ); } - if(this.hasSave) this.setPendingSaves(); + if (this.hasSave) this.setPendingSaves(); } - + this.canViewSecret = this.parent.speakerActor?.testUserPermission(game.user, 'OBSERVER'); } getTargetList() { return this.targetSelection !== true - ? Array.from(game.user.targets).map(t =>{ - const target = game.system.api.fields.ActionFields.TargetField.formatTarget(t), - oldTarget = this.targets.find(ot => ot.actorId === target.actorId) ?? this.oldTargets.find(ot => ot.actorId === target.actorId); - if(oldTarget) return oldTarget; - return target; - }) + ? Array.from(game.user.targets).map(t => { + const target = game.system.api.fields.ActionFields.TargetField.formatTarget(t), + oldTarget = + this.targets.find(ot => ot.actorId === target.actorId) ?? + this.oldTargets.find(ot => ot.actorId === target.actorId); + if (oldTarget) return oldTarget; + return target; + }) : this.targets; } setPendingSaves() { this.pendingSaves = this.targetSelection - ? this.targets.filter( - target => target.hit && target.saved.success === null - ).length > 0 - : this.currentTargets.filter( - target => target.saved.success === null - ).length > 0; + ? this.targets.filter(target => target.hit && target.saved.success === null).length > 0 + : this.currentTargets.filter(target => target.saved.success === null).length > 0; } } diff --git a/module/data/fields/action/beastformField.mjs b/module/data/fields/action/beastformField.mjs index 25e3cf9c..832bd9f6 100644 --- a/module/data/fields/action/beastformField.mjs +++ b/module/data/fields/action/beastformField.mjs @@ -4,7 +4,25 @@ export default class BeastformField extends fields.SchemaField { constructor(options = {}, context = {}) { const beastformFields = { tierAccess: new fields.SchemaField({ - exact: new fields.NumberField({ integer: true, nullable: true, initial: null }) + exact: new fields.NumberField({ + integer: true, + nullable: true, + initial: null, + choices: () => { + const settingsTiers = game.settings.get( + CONFIG.DH.id, + CONFIG.DH.SETTINGS.gameSettings.LevelTiers + ).tiers; + return Object.values(settingsTiers).reduce( + (acc, tier) => { + acc[tier.tier] = game.i18n.localize(tier.name); + return acc; + }, + { 1: game.i18n.localize('DAGGERHEART.GENERAL.Tiers.1') } + ); + }, + hint: 'DAGGERHEART.ACTIONS.Config.beastform.exactHint' + }) }) }; super(beastformFields, options, context); diff --git a/module/data/fields/action/usesField.mjs b/module/data/fields/action/usesField.mjs index 14ceba61..3993ca3b 100644 --- a/module/data/fields/action/usesField.mjs +++ b/module/data/fields/action/usesField.mjs @@ -12,7 +12,10 @@ export default class UsesField extends fields.SchemaField { initial: null, nullable: true }), - consumeOnSuccess: new fields.BooleanField({ initial: false, label: "DAGGERHEART.ACTIONS.Settings.consumeOnSuccess.label" }) + consumeOnSuccess: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.ACTIONS.Settings.consumeOnSuccess.label' + }) }; super(usesFields, options, context); } @@ -30,6 +33,7 @@ export default class UsesField extends fields.SchemaField { if (!uses) return null; return { ...uses, + remaining: this.remainingUses, enabled: uses.hasOwnProperty('enabled') ? uses.enabled : true }; } diff --git a/module/data/fields/actionField.mjs b/module/data/fields/actionField.mjs index 00948f40..c3bdcaaa 100644 --- a/module/data/fields/actionField.mjs +++ b/module/data/fields/actionField.mjs @@ -1,4 +1,5 @@ import DHActionConfig from '../../applications/sheets-configs/action-config.mjs'; +import { itemAbleRollParse } from '../../helpers/utils.mjs'; import MappingField from './mappingField.mjs'; /** @@ -164,6 +165,15 @@ export function ActionMixin(Base) { return foundry.utils.getProperty(this.parent, this.systemPath) instanceof Collection; } + get remainingUses() { + if (!this.uses) return null; + + return Math.max( + (this.uses.max ? itemAbleRollParse(this.uses.max, this.actor) : 0) - (this.uses.value ?? 0), + 0 + ); + } + static async create(data, operation = {}) { const { parent, renderSheet } = operation; let { type } = data; diff --git a/module/data/item/beastform.mjs b/module/data/item/beastform.mjs index 4ebcfade..68c934ed 100644 --- a/module/data/item/beastform.mjs +++ b/module/data/item/beastform.mjs @@ -88,6 +88,26 @@ export default class DHBeastform extends BaseDataItem { /* -------------------------------------------- */ + get beastformAttackData() { + const effect = this.parent.effects.find(x => x.type === 'beastform'); + if (!effect) return null; + + const traitBonus = effect.changes.find(x => x.key === `system.traits.${this.mainTrait}.value`)?.value ?? 0; + const evasionBonus = effect.changes.find(x => x.key === 'system.evasion')?.value ?? 0; + + const damageDiceIndex = effect.changes.find(x => x.key === 'system.rules.attack.damage.diceIndex'); + const damageDice = damageDiceIndex ? Object.keys(CONFIG.DH.GENERAL.diceTypes)[damageDiceIndex.value] : null; + const damageBonus = effect.changes.find(x => x.key === 'system.rules.attack.damage.bonus')?.value ?? 0; + + return { + trait: game.i18n.localize(CONFIG.DH.ACTOR.abilities[this.mainTrait].label), + traitBonus: traitBonus ? Number(traitBonus).signedString() : '', + evasionBonus: evasionBonus ? Number(evasionBonus).signedString() : '', + damageDice: damageDice, + damageBonus: damageBonus ? `${Number(damageBonus).signedString()}` : '' + }; + } + async _preCreate() { if (!this.actor) return; diff --git a/module/data/settings/Automation.mjs b/module/data/settings/Automation.mjs index d2842148..facaec17 100644 --- a/module/data/settings/Automation.mjs +++ b/module/data/settings/Automation.mjs @@ -45,6 +45,11 @@ export default class DhAutomation extends foundry.abstract.DataModel { required: true, initial: true, label: 'DAGGERHEART.SETTINGS.Automation.FIELDS.resourceScrollTexts.label' + }), + playerCanEditSheet: new fields.BooleanField({ + required: true, + initial: false, + label: 'DAGGERHEART.SETTINGS.Automation.FIELDS.playerCanEditSheet.label' }) }; } diff --git a/module/data/settings/Homebrew.mjs b/module/data/settings/Homebrew.mjs index d2296dc6..e18fee39 100644 --- a/module/data/settings/Homebrew.mjs +++ b/module/data/settings/Homebrew.mjs @@ -45,10 +45,10 @@ export default class DhHomebrew extends foundry.abstract.DataModel { initial: 'Coins', label: 'DAGGERHEART.SETTINGS.Homebrew.currency.coinName' }), - handfulls: new fields.StringField({ + handfuls: new fields.StringField({ required: true, - initial: 'Handfulls', - label: 'DAGGERHEART.SETTINGS.Homebrew.currency.handfullName' + initial: 'Handfuls', + label: 'DAGGERHEART.SETTINGS.Homebrew.currency.handfulName' }), bags: new fields.StringField({ required: true, diff --git a/module/data/settings/RangeMeasurement.mjs b/module/data/settings/RangeMeasurement.mjs deleted file mode 100644 index 552963f0..00000000 --- a/module/data/settings/RangeMeasurement.mjs +++ /dev/null @@ -1,25 +0,0 @@ -export default class DhRangeMeasurement extends foundry.abstract.DataModel { - static defineSchema() { - const fields = foundry.data.fields; - return { - enabled: new fields.BooleanField({ required: true, initial: true, label: 'DAGGERHEART.GENERAL.enabled' }), - melee: new fields.NumberField({ required: true, initial: 5, label: 'DAGGERHEART.CONFIG.Range.melee.name' }), - veryClose: new fields.NumberField({ - required: true, - initial: 15, - label: 'DAGGERHEART.CONFIG.Range.veryClose.name' - }), - close: new fields.NumberField({ - required: true, - initial: 30, - label: 'DAGGERHEART.CONFIG.Range.close.name' - }), - far: new fields.NumberField({ required: true, initial: 60, label: 'DAGGERHEART.CONFIG.Range.far.name' }), - veryFar: new fields.NumberField({ - required: true, - initial: 120, - label: 'DAGGERHEART.CONFIG.Range.veryFar.name' - }) - }; - } -} diff --git a/module/data/settings/VariantRules.mjs b/module/data/settings/VariantRules.mjs index 4428ae75..ad7d707a 100644 --- a/module/data/settings/VariantRules.mjs +++ b/module/data/settings/VariantRules.mjs @@ -17,9 +17,28 @@ export default class DhVariantRules extends foundry.abstract.DataModel { label: 'DAGGERHEART.SETTINGS.VariantRules.FIELDS.actionTokens.tokens.label' }) }), - useCoins: new fields.BooleanField({ - initial: false, - label: 'DAGGERHEART.SETTINGS.VariantRules.FIELDS.useCoins.label' + rangeMeasurement: new fields.SchemaField({ + enabled: new fields.BooleanField({ + required: true, + initial: true, + label: 'DAGGERHEART.GENERAL.enabled' + }), + melee: new fields.NumberField({ + required: true, + initial: 5, + label: 'DAGGERHEART.CONFIG.Range.melee.name' + }), + veryClose: new fields.NumberField({ + required: true, + initial: 15, + label: 'DAGGERHEART.CONFIG.Range.veryClose.name' + }), + close: new fields.NumberField({ + required: true, + initial: 30, + label: 'DAGGERHEART.CONFIG.Range.close.name' + }), + far: new fields.NumberField({ required: true, initial: 60, label: 'DAGGERHEART.CONFIG.Range.far.name' }) }) }; } diff --git a/module/data/settings/_module.mjs b/module/data/settings/_module.mjs index 032974a9..db1fbfec 100644 --- a/module/data/settings/_module.mjs +++ b/module/data/settings/_module.mjs @@ -1,5 +1,4 @@ export { default as DhAppearance } from './Appearance.mjs'; export { default as DhAutomation } from './Automation.mjs'; export { default as DhHomebrew } from './Homebrew.mjs'; -export { default as DhRangeMeasurement } from './RangeMeasurement.mjs'; export { default as DhVariantRules } from './VariantRules.mjs'; diff --git a/module/dice/d20Roll.mjs b/module/dice/d20Roll.mjs index b30bafbf..45471532 100644 --- a/module/dice/d20Roll.mjs +++ b/module/dice/d20Roll.mjs @@ -18,9 +18,7 @@ export default class D20Roll extends DHRoll { static DefaultDialog = D20RollDialog; get title() { - return game.i18n.localize( - "DAGGERHEART.GENERAL.d20Roll" - ); + return game.i18n.localize('DAGGERHEART.GENERAL.d20Roll'); } get d20() { @@ -145,9 +143,9 @@ export default class D20Roll extends DHRoll { config.targetSelection = true; config.targets.forEach(target => { const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion; - target.hit = this.isCritical || roll.total >= difficulty; + target.hit = roll.isCritical || roll.total >= difficulty; }); - data.success = config.targets.some(target => target.hit) + data.success = config.targets.some(target => target.hit); } else if (config.roll.difficulty) { data.difficulty = config.roll.difficulty; data.success = roll.isCritical || roll.total >= config.roll.difficulty; diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs index be49d685..999a4bb8 100644 --- a/module/dice/damageRoll.mjs +++ b/module/dice/damageRoll.mjs @@ -9,9 +9,8 @@ export default class DamageRoll extends DHRoll { static DefaultDialog = DamageDialog; static async buildEvaluate(roll, config = {}, message = {}) { - if (config.evaluate !== false) - for (const roll of config.roll) await roll.roll.evaluate(); - + if (config.evaluate !== false) for (const roll of config.roll) await roll.roll.evaluate(); + roll._evaluated = true; const parts = config.roll.map(r => this.postEvaluate(r)); @@ -42,7 +41,7 @@ export default class DamageRoll extends DHRoll { if (config.source?.message) { const chatMessage = ui.chat.collection.get(config.source.message); chatMessage.update({ 'system.damage': config.damage }); - } + } } static unifyDamageRoll(rolls) { @@ -84,11 +83,11 @@ export default class DamageRoll extends DHRoll { applyBaseBonus(part) { const modifiers = [], - type = this.options.messageType ?? (this.options.isHealing ? 'healing' : 'damage'), + type = this.options.messageType ?? (this.options.hasHealing ? 'healing' : 'damage'), options = part ?? this.options; modifiers.push(...this.getBonus(`${type}`, `${type.capitalize()} Bonus`)); - if (!this.options.isHealing) { + if (!this.options.hasHealing) { options.damageTypes?.forEach(t => { modifiers.push(...this.getBonus(`${type}.${t}`, `${t.capitalize()} ${type.capitalize()} Bonus`)); }); diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index 337805a7..3aced0bf 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -75,7 +75,8 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { if (isOriginTarget && change.effect.origin) { change.value = change.value.replaceAll(/origin\.@/gi, '@'); try { - const doc = foundry.utils.fromUuidSync(change.effect.origin); + const effect = foundry.utils.fromUuidSync(change.effect.origin); + const doc = effect.parent?.parent; if (doc) parseModel = doc; } catch (_) {} } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index ce9ffc89..910ec4f1 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -202,7 +202,8 @@ export default class DhpActor extends Actor { await this.update({ [`system.experiences.${experienceKey}`]: { name: experience.name, - value: experience.modifier + value: experience.modifier, + core: true } }); @@ -210,7 +211,8 @@ export default class DhpActor extends Actor { await this.system.companion.update({ [`system.experiences.${experienceKey}`]: { name: '', - value: experience.modifier + value: experience.modifier, + core: true } }); } @@ -559,8 +561,8 @@ export default class DhpActor extends Actor { updates.forEach( u => - (u.value = - u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false ? u.value * -1 : u.value) + (u.value = + u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false ? u.value * -1 : u.value) ); await this.modifyResource(updates); @@ -606,9 +608,9 @@ export default class DhpActor extends Actor { updates.forEach( u => - (u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false) - ? u.value * -1 - : u.value) + (u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false) + ? u.value * -1 + : u.value) ); await this.modifyResource(updates); diff --git a/module/documents/item.mjs b/module/documents/item.mjs index 96d4596b..a261677a 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -74,8 +74,8 @@ export default class DHItem extends foundry.documents.Item { isInventoryItem === true ? 'Inventory Items' //TODO localize : isInventoryItem === false - ? 'Character Items' //TODO localize - : 'Other'; //TODO localize + ? 'Character Items' //TODO localize + : 'Other'; //TODO localize return { value: type, label, group }; } @@ -130,7 +130,6 @@ export default class DHItem extends foundry.documents.Item { /* -------------------------------------------- */ - async use(event) { const actions = new Set(this.system.actionsList); if (actions?.size) { @@ -152,10 +151,10 @@ export default class DHItem extends foundry.documents.Item { this.type === 'ancestry' ? game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.ancestryTitle') : this.type === 'community' - ? game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.communityTitle') - : this.type === 'feature' - ? game.i18n.localize('TYPES.Item.feature') - : game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.subclassFeatureTitle'), + ? game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.communityTitle') + : this.type === 'feature' + ? game.i18n.localize('TYPES.Item.feature') + : game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.subclassFeatureTitle'), origin: origin, img: this.img, item: { @@ -163,7 +162,7 @@ export default class DHItem extends foundry.documents.Item { img: this.img, tags: this._getTags() }, - actions: item.system.actions, + actions: item.system.actionsList, description: this.system.description }; diff --git a/module/documents/tooltipManager.mjs b/module/documents/tooltipManager.mjs index 974f5596..ec6c8d9e 100644 --- a/module/documents/tooltipManager.mjs +++ b/module/documents/tooltipManager.mjs @@ -161,7 +161,7 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti for (const [index, itemValue] of pathValue.entries()) { const itemIsAction = itemValue instanceof game.system.api.models.actions.actionsTypes.base; const value = itemIsAction || !itemValue?.item ? itemValue : itemValue.item; - const enrichedValue = await TextEditor.enrichHTML(value.description); + const enrichedValue = await TextEditor.enrichHTML(value.system?.description ?? value.description); if (itemIsAction) value.enrichedDescription = enrichedValue; else foundry.utils.setProperty(item, `${basePath}.${index}.enrichedDescription`, enrichedValue); } diff --git a/module/enrichers/TemplateEnricher.mjs b/module/enrichers/TemplateEnricher.mjs index 7f45b266..93dd6b96 100644 --- a/module/enrichers/TemplateEnricher.mjs +++ b/module/enrichers/TemplateEnricher.mjs @@ -1,5 +1,3 @@ -import { range as configRange } from '../config/generalConfig.mjs'; - export default function DhTemplateEnricher(match, _options) { const parts = match[1].split('|').map(x => x.trim()); @@ -17,7 +15,7 @@ export default function DhTemplateEnricher(match, _options) { type = matchedType; break; case 'range': - const matchedRange = Object.values(configRange).find( + const matchedRange = Object.values(CONFIG.DH.GENERAL.templateRanges).find( x => x.id.toLowerCase() === split[1] || x.short === split[1] ); range = matchedRange?.id; @@ -55,7 +53,9 @@ export const renderMeasuredTemplate = async event => { ? '180' : undefined; - const baseDistance = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.RangeMeasurement)[range]; + const baseDistance = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).rangeMeasurement[ + range + ]; const distance = type === CONFIG.DH.GENERAL.templateTypes.EMANATION ? baseDistance + 2.5 : baseDistance; const { width, height } = game.canvas.scene.dimensions; diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index f1df4723..7b588fc7 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -313,8 +313,10 @@ export const itemAbleRollParse = (value, actor, item) => { const isItemTarget = value.toLowerCase().includes('item.@'); const slicedValue = isItemTarget ? value.replaceAll(/item\.@/gi, '@') : value; + const model = isItemTarget ? item : actor; + try { - return Roll.replaceFormulaData(slicedValue, isItemTarget ? item : actor); + return Roll.replaceFormulaData(slicedValue, model?.getRollData?.() ?? model); } catch (_) { return ''; } @@ -362,6 +364,7 @@ export async function createEmbeddedItemWithEffects(actor, baseData, update) { const [doc] = await actor.createEmbeddedDocuments('Item', [ { ...(update ?? data), + ...baseData, id: data.id, uuid: data.uuid, effects: data.effects?.map(effect => effect.toObject()) @@ -371,6 +374,21 @@ export async function createEmbeddedItemWithEffects(actor, baseData, update) { return doc; } +export async function createEmbeddedItemsWithEffects(actor, baseData) { + const effectData = []; + for (let d of baseData) { + const data = d.uuid.startsWith('Compendium') ? await foundry.utils.fromUuid(d.uuid) : d; + effectData.push({ + ...data, + id: data.id, + uuid: data.uuid, + effects: data.effects?.map(effect => effect.toObject()) + }); + } + + await actor.createEmbeddedDocuments('Item', effectData); +} + export const slugify = name => { return name.toLowerCase().replaceAll(' ', '-').replaceAll('.', ''); }; diff --git a/module/systemRegistration/settings.mjs b/module/systemRegistration/settings.mjs index fea12acd..d100bcc0 100644 --- a/module/systemRegistration/settings.mjs +++ b/module/systemRegistration/settings.mjs @@ -1,17 +1,10 @@ import { defaultLevelTiers, DhLevelTiers } from '../data/levelTier.mjs'; import DhCountdowns from '../data/countdowns.mjs'; -import { - DhAppearance, - DhAutomation, - DhHomebrew, - DhRangeMeasurement, - DhVariantRules -} from '../data/settings/_module.mjs'; +import { DhAppearance, DhAutomation, DhHomebrew, DhVariantRules } from '../data/settings/_module.mjs'; import { DhAppearanceSettings, DhAutomationSettings, DhHomebrewSettings, - DhRangeMeasurementSettings, DhVariantRuleSettings } from '../applications/settings/_module.mjs'; @@ -58,12 +51,6 @@ const registerMenuSettings = () => { } } }); - - game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.RangeMeasurement, { - scope: 'world', - config: false, - type: DhRangeMeasurement - }); }; const registerMenus = () => { @@ -83,14 +70,6 @@ const registerMenus = () => { type: DhHomebrewSettings, restricted: true }); - game.settings.registerMenu(CONFIG.DH.id, CONFIG.DH.SETTINGS.menu.Range.Name, { - name: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.range.name'), - label: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.range.label'), - hint: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.range.hint'), - icon: CONFIG.DH.SETTINGS.menu.Range.Icon, - type: DhRangeMeasurementSettings, - restricted: true - }); game.settings.registerMenu(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance, { name: game.i18n.localize('DAGGERHEART.SETTINGS.Menu.appearance.title'), diff --git a/package.json b/package.json index af5adfd6..023ccff2 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "readline": "^1.3.0", "pushLDBtoYML": "node ./tools/pushLDBtoYML.mjs", "pullYMLtoLDB": "node ./tools/pullYMLtoLDB.mjs", + "pullYMLtoLDBBuild": "node ./tools/pullYMLtoLDBBuild.mjs", "createSymlink": "node ./tools/create-symlink.mjs" }, "devDependencies": { diff --git a/src/packs/adversaries/adversary_Conscript_99TqczuQipBmaB8i.json b/src/packs/adversaries/adversary_Conscript_99TqczuQipBmaB8i.json index 347f4e09..88ca68b5 100644 --- a/src/packs/adversaries/adversary_Conscript_99TqczuQipBmaB8i.json +++ b/src/packs/adversaries/adversary_Conscript_99TqczuQipBmaB8i.json @@ -60,6 +60,7 @@ }, "attack": { "name": "Spears", + "img": "icons/weapons/polearms/spear-flared-worn.webp", "range": "veryClose", "roll": { "bonus": 0, diff --git a/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json b/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json index d8f2376b..1e94b256 100644 --- a/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json +++ b/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json @@ -74,6 +74,7 @@ "description": "

An undead figure wearing a heavy leather coat, with searching eyes and a casually cruel demeanor.

", "attack": { "name": "Tear at Flesh", + "img": "icons/skills/melee/strike-slashes-red.webp", "roll": { "bonus": 5, "type": "attack" diff --git a/src/packs/adversaries/adversary_Spectral_Captain_65cSO3EQEh6ZH6Xk.json b/src/packs/adversaries/adversary_Spectral_Captain_65cSO3EQEh6ZH6Xk.json index 65344f5e..318c51a6 100644 --- a/src/packs/adversaries/adversary_Spectral_Captain_65cSO3EQEh6ZH6Xk.json +++ b/src/packs/adversaries/adversary_Spectral_Captain_65cSO3EQEh6ZH6Xk.json @@ -74,6 +74,7 @@ "motivesAndTactics": "Move through solid objects, rally troops, rehash old battles", "attack": { "name": "Longbow", + "img": "icons/weapons/bows/longbow-recurve-skull-brown.webp", "damage": { "parts": [ { diff --git a/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json b/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json index 6c01352d..743ada61 100644 --- a/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json +++ b/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json @@ -68,6 +68,7 @@ "description": "

A dust-covered golden construct with boxy limbs and a huge mace for a hand.

", "attack": { "name": "Charged Mace", + "img": "icons/weapons/maces/shortmace-ornate-gold.webp", "range": "veryClose", "roll": { "bonus": 3, diff --git a/src/packs/ancestries/feature_Danger_Sense_AXqcoxnRoWBbbKpK.json b/src/packs/ancestries/feature_Danger_Sense_AXqcoxnRoWBbbKpK.json index a9dd34f4..e8152918 100644 --- a/src/packs/ancestries/feature_Danger_Sense_AXqcoxnRoWBbbKpK.json +++ b/src/packs/ancestries/feature_Danger_Sense_AXqcoxnRoWBbbKpK.json @@ -26,8 +26,8 @@ ], "uses": { "value": null, - "max": "", - "recovery": null + "max": "1", + "recovery": "shortRest" }, "effects": [], "target": { @@ -58,7 +58,7 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753997061290, - "modifiedTime": 1753997114091, + "modifiedTime": 1754498245294, "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!items!AXqcoxnRoWBbbKpK" diff --git a/src/packs/ancestries/feature_Luckbender_U6iFjZgLYawlOlQZ.json b/src/packs/ancestries/feature_Luckbender_U6iFjZgLYawlOlQZ.json index 3319eee8..51b33024 100644 --- a/src/packs/ancestries/feature_Luckbender_U6iFjZgLYawlOlQZ.json +++ b/src/packs/ancestries/feature_Luckbender_U6iFjZgLYawlOlQZ.json @@ -26,8 +26,8 @@ ], "uses": { "value": null, - "max": "", - "recovery": null + "max": "1", + "recovery": "session" }, "effects": [], "target": { @@ -58,7 +58,7 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753994658436, - "modifiedTime": 1753994711690, + "modifiedTime": 1754498186961, "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!items!U6iFjZgLYawlOlQZ" diff --git a/src/packs/classes/class_Rogue_CvHlkHZfpMiCz5uT.json b/src/packs/classes/class_Rogue_CvHlkHZfpMiCz5uT.json index 307fd7b2..617ea0f0 100644 --- a/src/packs/classes/class_Rogue_CvHlkHZfpMiCz5uT.json +++ b/src/packs/classes/class_Rogue_CvHlkHZfpMiCz5uT.json @@ -49,8 +49,8 @@ "suggestedTraits": { "agility": 1, "strength": -1, - "finesse": 0, - "instinct": 2, + "finesse": 2, + "instinct": 0, "presence": 1, "knowledge": 0 }, @@ -76,8 +76,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754325275832, - "modifiedTime": 1754325686143, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754500637635, + "lastModifiedBy": "Q9NoTaEarn3VMS6Z" }, "_key": "!items!CvHlkHZfpMiCz5uT" } diff --git a/src/packs/classes/feature_Channel_Raw_Power_P02cbN50LIoD662z.json b/src/packs/classes/feature_Channel_Raw_Power_P02cbN50LIoD662z.json index b4f79450..f01b29b1 100644 --- a/src/packs/classes/feature_Channel_Raw_Power_P02cbN50LIoD662z.json +++ b/src/packs/classes/feature_Channel_Raw_Power_P02cbN50LIoD662z.json @@ -6,15 +6,7 @@ "img": "icons/magic/unholy/strike-body-explode-disintegrate.webp", "system": { "description": "

Once per long rest, you can place a domain card from your loadout into your vault and choose to either:

", - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "icon": "", - "recovery": "longRest", - "diceStates": {}, - "dieFaces": "d4" - }, + "resource": null, "actions": { "YFmqnbMx540su2Ni": { "type": "effect", @@ -26,17 +18,17 @@ "cost": [ { "scalable": false, - "key": "P02cbN50LIoD662z", + "key": "hitPoints", "value": 1, - "keyIsID": true, + "keyIsID": false, "step": null, "consumeOnSuccess": false } ], "uses": { "value": null, - "max": "", - "recovery": null, + "max": "1", + "recovery": "longRest", "consumeOnSuccess": false }, "effects": [], @@ -67,8 +59,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754349703843, - "modifiedTime": 1754349703843, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754498040342, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!items!P02cbN50LIoD662z" } diff --git a/src/packs/classes/feature_Rally_PydiMnNCKpd44SGS.json b/src/packs/classes/feature_Rally_PydiMnNCKpd44SGS.json index cd9fe232..4b509228 100644 --- a/src/packs/classes/feature_Rally_PydiMnNCKpd44SGS.json +++ b/src/packs/classes/feature_Rally_PydiMnNCKpd44SGS.json @@ -5,15 +5,7 @@ "img": "icons/tools/instruments/drum-hand-tan.webp", "system": { "description": "

Once per session, describe how you rally the party and give yourself and each of your allies a Rally Die. At level 1, your Rally Die is a d6. A PC can spend their Rally Die to roll it, adding the result to their action roll, reaction roll, damage roll, or to clear a number of Stress equal to the result. At the end of each session, clear all unspent Rally Dice. At level 5, your Rally Die increases to a d8.

", - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "icon": "", - "recovery": "session", - "diceStates": {}, - "dieFaces": "d4" - }, + "resource": null, "actions": { "vI4Fph3y9ygsya9e": { "type": "effect", @@ -25,15 +17,16 @@ "cost": [ { "scalable": false, - "key": "Y7waM3ljoRLyk38N", + "key": "hitPoints", "value": 1, - "keyIsID": true, - "step": null + "keyIsID": false, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, - "max": "", + "max": "1", "recovery": "session" }, "effects": [ @@ -114,8 +107,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754174497668, - "modifiedTime": 1754246215191, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754494820213, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "ownership": { "default": 0, diff --git a/src/packs/classes/feature_Rally__Level_5__TVeEyqmPPiRa2r3i.json b/src/packs/classes/feature_Rally__Level_5__TVeEyqmPPiRa2r3i.json index 1f85310e..bba20558 100644 --- a/src/packs/classes/feature_Rally__Level_5__TVeEyqmPPiRa2r3i.json +++ b/src/packs/classes/feature_Rally__Level_5__TVeEyqmPPiRa2r3i.json @@ -5,15 +5,7 @@ "img": "icons/tools/instruments/drum-hand-tan.webp", "system": { "description": "

Once per session, describe how you rally the party and give yourself and each of your allies a Rally Die. At level 1, your Rally Die is a d6. A PC can spend their Rally Die to roll it, adding the result to their action roll, reaction roll, damage roll, or to clear a number of Stress equal to the result. At the end of each session, clear all unspent Rally Dice. At level 5, your Rally Die increases to a d8.

", - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "icon": "", - "recovery": "session", - "diceStates": {}, - "dieFaces": "d4" - }, + "resource": null, "actions": { "Z1KWFrpXOqZWuZD1": { "type": "effect", @@ -25,15 +17,16 @@ "cost": [ { "scalable": false, - "key": "oxv0m8AFUQVFKtZ4", + "key": "hitPoints", "value": 1, - "keyIsID": true, - "step": null + "keyIsID": false, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, - "max": "", + "max": "1", "recovery": "session" }, "effects": [ @@ -114,8 +107,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754174499893, - "modifiedTime": 1754246215922, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754494835723, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "ownership": { "default": 0, diff --git a/src/packs/classes/feature_Strange_Patterns_6YsfFjmCGuFYVhT4.json b/src/packs/classes/feature_Strange_Patterns_6YsfFjmCGuFYVhT4.json index c9bac1eb..afe896de 100644 --- a/src/packs/classes/feature_Strange_Patterns_6YsfFjmCGuFYVhT4.json +++ b/src/packs/classes/feature_Strange_Patterns_6YsfFjmCGuFYVhT4.json @@ -7,10 +7,11 @@ "system": { "description": "

Choose a number between 1 and 12. When you roll that number on a Duality Die, gain a Hope or clear a Stress.

You can change this number when you take a long rest.

", "resource": { - "type": "simple", + "type": "diceValue", "value": 1, - "max": "", - "icon": "fa-solid fa-hashtag" + "max": "1", + "icon": "fa-solid fa-hashtag", + "dieFaces": "d12" }, "actions": { "RkqPzF1bdWzPPMml": { @@ -100,7 +101,7 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754254942995, - "modifiedTime": 1754255067467, + "modifiedTime": 1754498121727, "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!items!6YsfFjmCGuFYVhT4" diff --git a/src/packs/communities/feature_Know_the_Tide_07x6Qe6qMzDw2xN4.json b/src/packs/communities/feature_Know_the_Tide_07x6Qe6qMzDw2xN4.json index cab7e54d..d2c1c314 100644 --- a/src/packs/communities/feature_Know_the_Tide_07x6Qe6qMzDw2xN4.json +++ b/src/packs/communities/feature_Know_the_Tide_07x6Qe6qMzDw2xN4.json @@ -30,8 +30,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754010247432, - "modifiedTime": 1754010247432, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754498464092, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "sort": 0, "ownership": { diff --git a/src/packs/domains/domainCard_Cinder_Grasp_5EP2Lgf7ojfrc0Is.json b/src/packs/domains/domainCard_Cinder_Grasp_5EP2Lgf7ojfrc0Is.json index 5630c6bb..ce88eb60 100644 --- a/src/packs/domains/domainCard_Cinder_Grasp_5EP2Lgf7ojfrc0Is.json +++ b/src/packs/domains/domainCard_Cinder_Grasp_5EP2Lgf7ojfrc0Is.json @@ -66,7 +66,7 @@ } ], "roll": { - "type": null, + "type": "spellcast", "trait": null, "difficulty": null, "bonus": null, @@ -154,8 +154,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784434, - "modifiedTime": 1754253433766, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754475145346, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "5EP2Lgf7ojfrc0Is", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Confusing_Aura_R8NDiJXJWmC48WSr.json b/src/packs/domains/domainCard_Confusing_Aura_R8NDiJXJWmC48WSr.json index 36dec337..ee91b2fc 100644 --- a/src/packs/domains/domainCard_Confusing_Aura_R8NDiJXJWmC48WSr.json +++ b/src/packs/domains/domainCard_Confusing_Aura_R8NDiJXJWmC48WSr.json @@ -20,9 +20,9 @@ "cost": [], "uses": { "value": null, - "max": "", - "recovery": null, - "consumeOnSuccess": false + "max": "1", + "recovery": "longRest", + "consumeOnSuccess": true }, "damage": { "parts": [], @@ -128,8 +128,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784437, - "modifiedTime": 1754254161910, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754501480068, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "R8NDiJXJWmC48WSr", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Copycat_3A7LZ1xmDEMGa165.json b/src/packs/domains/domainCard_Copycat_3A7LZ1xmDEMGa165.json index edb22494..6e9762c6 100644 --- a/src/packs/domains/domainCard_Copycat_3A7LZ1xmDEMGa165.json +++ b/src/packs/domains/domainCard_Copycat_3A7LZ1xmDEMGa165.json @@ -9,12 +9,31 @@ "recallCost": 3, "level": 9, "type": "spell", - "resource": { - "type": "simple", - "value": 1, - "recovery": "longRest", - "max": "1", - "icon": "" + "resource": null, + "actions": { + "RKEceNKiQirYwN45": { + "type": "effect", + "_id": "RKEceNKiQirYwN45", + "systemPath": "actions", + "description": "

Once per long rest, this card can mimic the features of another domain card of level 8 or lower in another player’s loadout. Spend Hope equal to half the card’s level to gain access to the feature. It lasts until your next rest or they place the card in their vault.

", + "chatDisplay": true, + "actionType": "action", + "cost": [], + "uses": { + "value": null, + "max": "1", + "recovery": "longRest", + "consumeOnSuccess": false + }, + "effects": [], + "target": { + "type": "any", + "amount": null + }, + "name": "Mimic", + "img": "icons/magic/perception/hand-eye-black.webp", + "range": "" + } } }, "flags": {}, @@ -26,8 +45,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784439, - "modifiedTime": 1754329311656, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499898585, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "3A7LZ1xmDEMGa165", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Earthquake_C0qLOwSSvZ6PG3Ws.json b/src/packs/domains/domainCard_Earthquake_C0qLOwSSvZ6PG3Ws.json index 0b88d8ce..6b8cc8b1 100644 --- a/src/packs/domains/domainCard_Earthquake_C0qLOwSSvZ6PG3Ws.json +++ b/src/packs/domains/domainCard_Earthquake_C0qLOwSSvZ6PG3Ws.json @@ -29,9 +29,9 @@ ], "uses": { "value": null, - "max": "", - "recovery": null, - "consumeOnSuccess": false + "max": "1", + "recovery": "shortRest", + "consumeOnSuccess": true }, "damage": { "parts": [ @@ -99,13 +99,7 @@ "range": "veryFar" } }, - "resource": { - "type": "simple", - "value": 1, - "recovery": "shortRest", - "max": "1", - "icon": "" - } + "resource": null }, "flags": {}, "_stats": { @@ -116,8 +110,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784449, - "modifiedTime": 1754254262215, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754501560924, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "C0qLOwSSvZ6PG3Ws", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Enrapture_a8lFiKX1o8T924ze.json b/src/packs/domains/domainCard_Enrapture_a8lFiKX1o8T924ze.json index 145e63b5..fc87d922 100644 --- a/src/packs/domains/domainCard_Enrapture_a8lFiKX1o8T924ze.json +++ b/src/packs/domains/domainCard_Enrapture_a8lFiKX1o8T924ze.json @@ -31,7 +31,12 @@ "type": "any", "amount": null }, - "effects": [], + "effects": [ + { + "_id": "EYG5dLImk6GkmfRd", + "onSave": false + } + ], "roll": { "type": "spellcast", "trait": null, @@ -127,7 +132,7 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784451, - "modifiedTime": 1754340901029, + "modifiedTime": 1754500747453, "lastModifiedBy": "Q9NoTaEarn3VMS6Z" }, "_id": "a8lFiKX1o8T924ze", @@ -135,6 +140,10 @@ "effects": [ { "name": "Enraptured", + "img": "icons/magic/control/hypnosis-mesmerism-eye.webp", + "origin": "Compendium.daggerheart.domains.Item.a8lFiKX1o8T924ze", + "transfer": false, + "_id": "EYG5dLImk6GkmfRd", "type": "base", "system": { "rangeDependence": { @@ -144,8 +153,6 @@ "range": "melee" } }, - "_id": "FOQ2yqrpl2TPVxvt", - "img": "icons/magic/control/hypnosis-mesmerism-eye.webp", "changes": [], "disabled": false, "duration": { @@ -157,10 +164,8 @@ "startRound": null, "startTurn": null }, - "description": "

While Enraptured, a target’s attention is fixed on you, narrowing their field of view and drowning out any sound but your voice.

", - "origin": null, + "description": "

While Enraptured, a target’s attention is fixed on you, narrowing their field of view and drowning out any sound but your voice.

", "tint": "#ffffff", - "transfer": true, "statuses": [], "sort": 0, "flags": {}, @@ -171,11 +176,11 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "createdTime": 1754106690796, - "modifiedTime": 1754340886910, + "createdTime": 1754500747406, + "modifiedTime": 1754500810477, "lastModifiedBy": "Q9NoTaEarn3VMS6Z" }, - "_key": "!items.effects!a8lFiKX1o8T924ze.FOQ2yqrpl2TPVxvt" + "_key": "!items.effects!a8lFiKX1o8T924ze.EYG5dLImk6GkmfRd" } ], "ownership": { diff --git a/src/packs/domains/domainCard_Falling_Sky_hZJp9mdkMnqKDROe.json b/src/packs/domains/domainCard_Falling_Sky_hZJp9mdkMnqKDROe.json index d047c737..fd032d37 100644 --- a/src/packs/domains/domainCard_Falling_Sky_hZJp9mdkMnqKDROe.json +++ b/src/packs/domains/domainCard_Falling_Sky_hZJp9mdkMnqKDROe.json @@ -4,7 +4,7 @@ "type": "domainCard", "folder": "7Cs44YADBTmmtCw6", "system": { - "description": "

Make a Spellcast Roll against all adversaries within Far range. Mark any number of Stress to make shards of arcana rain down from above. Targets you succeed against take 1d20+2 magic damage for each Stress marked.

", + "description": "

Make a Spellcast Roll against all adversaries within Far range. Mark any number of Stress to make shards of arcana rain down from above. Targets you succeed against take 1d20+2 magic damage for each Stress marked.

@Template[type:emanation|range:f]

", "domain": "arcana", "recallCost": 1, "level": 10, @@ -14,7 +14,7 @@ "type": "attack", "_id": "xJfXJDVsBayGaqkr", "systemPath": "actions", - "description": "

Make a Spellcast Roll against all adversaries within Far range. Mark any number of Stress to make shards of arcana rain down from above. Targets you succeed against take 1d20+2 magic damage for each Stress marked.

", + "description": "

Make a Spellcast Roll against all adversaries within Far range. Mark any number of Stress to make shards of arcana rain down from above. Targets you succeed against take 1d20+2 magic damage for each Stress marked.

@Template[type:emanation|range:f]

", "chatDisplay": true, "actionType": "action", "cost": [ @@ -103,8 +103,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784452, - "modifiedTime": 1754254370187, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754501517016, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "hZJp9mdkMnqKDROe", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Full_Surge_SgvjJfMyubZowPxS.json b/src/packs/domains/domainCard_Full_Surge_SgvjJfMyubZowPxS.json index b27dda2c..ca10655c 100644 --- a/src/packs/domains/domainCard_Full_Surge_SgvjJfMyubZowPxS.json +++ b/src/packs/domains/domainCard_Full_Surge_SgvjJfMyubZowPxS.json @@ -28,8 +28,8 @@ ], "uses": { "value": null, - "max": "", - "recovery": null + "max": "1", + "recovery": "longRest" }, "effects": [ { @@ -56,7 +56,7 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784460, - "modifiedTime": 1754242182536, + "modifiedTime": 1754498928489, "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "SgvjJfMyubZowPxS", diff --git a/src/packs/domains/domainCard_Healing_Field_GlRm1Dxlc0Z1b04o.json b/src/packs/domains/domainCard_Healing_Field_GlRm1Dxlc0Z1b04o.json index 6cf1c52c..a9b0561d 100644 --- a/src/packs/domains/domainCard_Healing_Field_GlRm1Dxlc0Z1b04o.json +++ b/src/packs/domains/domainCard_Healing_Field_GlRm1Dxlc0Z1b04o.json @@ -173,7 +173,8 @@ "value": 1, "recovery": "longRest", "max": "1", - "icon": "" + "icon": "", + "progression": "decreasing" } }, "flags": {}, @@ -185,8 +186,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784466, - "modifiedTime": 1754338717920, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499077474, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "GlRm1Dxlc0Z1b04o", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Inspirational_Words_cWu1o82ZF7GvnbXc.json b/src/packs/domains/domainCard_Inspirational_Words_cWu1o82ZF7GvnbXc.json index eac0b208..424b08b7 100644 --- a/src/packs/domains/domainCard_Inspirational_Words_cWu1o82ZF7GvnbXc.json +++ b/src/packs/domains/domainCard_Inspirational_Words_cWu1o82ZF7GvnbXc.json @@ -14,7 +14,8 @@ "value": 0, "recovery": "longRest", "max": "@system.traits.presence.value", - "icon": "" + "icon": "", + "progression": "decreasing" }, "actions": { "5sGMd6m6Ltahit4h": { @@ -253,8 +254,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784473, - "modifiedTime": 1754340989544, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499693699, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "cWu1o82ZF7GvnbXc", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Mass_Enrapture_ubpixIgZrJXKyM3b.json b/src/packs/domains/domainCard_Mass_Enrapture_ubpixIgZrJXKyM3b.json index 952e478c..2713e2c7 100644 --- a/src/packs/domains/domainCard_Mass_Enrapture_ubpixIgZrJXKyM3b.json +++ b/src/packs/domains/domainCard_Mass_Enrapture_ubpixIgZrJXKyM3b.json @@ -4,7 +4,7 @@ "type": "domainCard", "folder": "7O1tTswJMNdPgLsx", "system": { - "description": "

Make a Spellcast Roll against all targets within Far range. Targets you succeed against become temporarily Enraptured. While Enraptured, a target’s attention is fixed on you, narrowing their field of view and drowning out any sound but your voice. Mark a Stress to force all Enraptured targets to mark a Stress, ending this spell.

", + "description": "

Make a Spellcast Roll against all targets within Far range. Targets you succeed against become temporarily Enraptured. While Enraptured, a target’s attention is fixed on you, narrowing their field of view and drowning out any sound but your voice. Mark a Stress to force all Enraptured targets to mark a Stress, ending this spell.

@Template[type:emanation|range:f]

", "domain": "grace", "recallCost": 3, "level": 8, @@ -14,7 +14,7 @@ "type": "attack", "_id": "r5eA3tAH7EplOQCP", "systemPath": "actions", - "description": "

Make a Spellcast Roll against all targets within Far range. Targets you succeed against become temporarily Enraptured. While Enraptured, a target’s attention is fixed on you, narrowing their field of view and drowning out any sound but your voice.

", + "description": "

Make a Spellcast Roll against all targets within Far range. Targets you succeed against become temporarily Enraptured. While Enraptured, a target’s attention is fixed on you, narrowing their field of view and drowning out any sound but your voice. Mark a Stress to force all Enraptured targets to mark a Stress, ending this spell.

@Template[type:emanation|range:f]

", "chatDisplay": true, "actionType": "action", "cost": [], @@ -132,8 +132,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784481, - "modifiedTime": 1754342040215, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499825008, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "ubpixIgZrJXKyM3b", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Mending_Touch_TGjR4vJVNbQRV8zr.json b/src/packs/domains/domainCard_Mending_Touch_TGjR4vJVNbQRV8zr.json index bbe13819..437adffc 100644 --- a/src/packs/domains/domainCard_Mending_Touch_TGjR4vJVNbQRV8zr.json +++ b/src/packs/domains/domainCard_Mending_Touch_TGjR4vJVNbQRV8zr.json @@ -338,9 +338,10 @@ "resource": { "type": "simple", "value": 1, - "recovery": "longRest", + "progression": "decreasing", "max": "1", - "icon": "" + "icon": "fa-solid fa-hands-praying", + "recovery": "longRest" } }, "flags": {}, @@ -352,8 +353,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784482, - "modifiedTime": 1754269394280, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754498631054, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "TGjR4vJVNbQRV8zr", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Night_Terror_zcldCuqOg3dphUVI.json b/src/packs/domains/domainCard_Night_Terror_zcldCuqOg3dphUVI.json index 89d5fe1a..cb538eb1 100644 --- a/src/packs/domains/domainCard_Night_Terror_zcldCuqOg3dphUVI.json +++ b/src/packs/domains/domainCard_Night_Terror_zcldCuqOg3dphUVI.json @@ -4,7 +4,7 @@ "type": "domainCard", "folder": "2rqOUxEglhhPKk2j", "system": { - "description": "

Once per long rest, choose any targets within Very Close range to perceive you as a nightmarish horror. The targets must succeed on a Reaction Roll (16) or become temporarily Horrified. While Horrified, they’re Vulnerable. Steal a number of Fear from the GM equal to the number of targets that are Horrified (up to the number of Fear in the GM’s pool). Roll a number of d6s equal to the number of stolen Fear and deal the total damage to each Horrified target. Discard the stolen Fear.

", + "description": "

Once per long rest, choose any targets within Very Close range to perceive you as a nightmarish horror. The targets must succeed on a Reaction Roll (16) or become temporarily Horrified. While Horrified, they’re Vulnerable. Steal a number of Fear from the GM equal to the number of targets that are Horrified (up to the number of Fear in the GM’s pool). Roll a number of d6s equal to the number of stolen Fear and deal the total damage to each Horrified target. Discard the stolen Fear.

@Template[type:emanation|range:vc]

", "domain": "midnight", "recallCost": 2, "level": 9, @@ -14,14 +14,14 @@ "type": "attack", "_id": "e4A6GQERsn08IBby", "systemPath": "actions", - "description": "

Once per long rest, choose any targets within Very Close range to perceive you as a nightmarish horror. The targets must succeed on a Reaction Roll (16) or become temporarily Horrified. While Horrified, they’re Vulnerable. Steal a number of Fear from the GM equal to the number of targets that are Horrified (up to the number of Fear in the GM’s pool). Roll a number of d6s equal to the number of stolen Fear and deal the total damage to each Horrified target. Discard the stolen Fear.

", + "description": "

Once per long rest, choose any targets within Very Close range to perceive you as a nightmarish horror. The targets must succeed on a Reaction Roll (16) or become temporarily Horrified. While Horrified, they’re Vulnerable. Steal a number of Fear from the GM equal to the number of targets that are Horrified (up to the number of Fear in the GM’s pool). Roll a number of d6s equal to the number of stolen Fear and deal the total damage to each Horrified target. Discard the stolen Fear.

@Template[type:emanation|range:vc]

", "chatDisplay": true, "actionType": "action", "cost": [], "uses": { "value": null, - "max": "", - "recovery": null + "max": "1", + "recovery": "longRest" }, "damage": { "parts": [], @@ -121,12 +121,7 @@ "range": "" } }, - "resource": { - "type": "simple", - "value": 0, - "max": "", - "icon": "" - } + "resource": null }, "flags": {}, "_stats": { @@ -137,8 +132,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784487, - "modifiedTime": 1754331219352, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499654051, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "zcldCuqOg3dphUVI", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Plant_Dominion_9a6xP5pxhVvdugk9.json b/src/packs/domains/domainCard_Plant_Dominion_9a6xP5pxhVvdugk9.json index c8f3272e..8176850e 100644 --- a/src/packs/domains/domainCard_Plant_Dominion_9a6xP5pxhVvdugk9.json +++ b/src/packs/domains/domainCard_Plant_Dominion_9a6xP5pxhVvdugk9.json @@ -21,7 +21,8 @@ "uses": { "value": null, "max": "1", - "recovery": "longRest" + "recovery": "longRest", + "consumeOnSuccess": true }, "damage": { "parts": [], @@ -67,8 +68,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784493, - "modifiedTime": 1754340285152, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499238543, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "9a6xP5pxhVvdugk9", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Reassurance_iYNVTB7uAD1FTCZu.json b/src/packs/domains/domainCard_Reassurance_iYNVTB7uAD1FTCZu.json index c55cd75b..43c17e96 100644 --- a/src/packs/domains/domainCard_Reassurance_iYNVTB7uAD1FTCZu.json +++ b/src/packs/domains/domainCard_Reassurance_iYNVTB7uAD1FTCZu.json @@ -19,7 +19,7 @@ "actionType": "action", "cost": [], "uses": { - "value": 1, + "value": 0, "max": "1", "recovery": "shortRest", "consumeOnSuccess": false @@ -44,8 +44,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784499, - "modifiedTime": 1754269219077, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754498645559, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "iYNVTB7uAD1FTCZu", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Rejuvenation_Barrier_HtWx5IIemCoorMj2.json b/src/packs/domains/domainCard_Rejuvenation_Barrier_HtWx5IIemCoorMj2.json index 2cc41796..4d910604 100644 --- a/src/packs/domains/domainCard_Rejuvenation_Barrier_HtWx5IIemCoorMj2.json +++ b/src/packs/domains/domainCard_Rejuvenation_Barrier_HtWx5IIemCoorMj2.json @@ -4,7 +4,7 @@ "type": "domainCard", "folder": "qY4Zqc1Ch6p317uK", "system": { - "description": "

Make a Spellcast Roll (15). Once per rest on a success, create a temporary barrier of protective energy around you at Very Close range. You and all allies within the barrier when this spell is cast clear 1d4 Hit Points. While the barrier is up, you and all allies within have resistance to physical damage from outside the barrier.

When you move, the barrier follows you.

", + "description": "

Make a Spellcast Roll (15). Once per rest on a success, create a temporary barrier of protective energy around you at Very Close range. You and all allies within the barrier when this spell is cast clear 1d4 Hit Points. While the barrier is up, you and all allies within have resistance to physical damage from outside the barrier.

When you move, the barrier follows you.

@Template[type:emanation|range:vc]

", "domain": "sage", "recallCost": 1, "level": 8, @@ -14,7 +14,7 @@ "type": "healing", "_id": "XdAwXl2uWNinInFe", "systemPath": "actions", - "description": "

Make a Spellcast Roll (15). Once per rest on a success, create a temporary barrier of protective energy around you at Very Close range. You and all allies within the barrier when this spell is cast clear 1d4 Hit Points. While the barrier is up, you and all allies within have resistance to physical damage from outside the barrier.

When you move, the barrier follows you.

", + "description": "

Make a Spellcast Roll (15). Once per rest on a success, create a temporary barrier of protective energy around you at Very Close range. You and all allies within the barrier when this spell is cast clear 1d4 Hit Points. While the barrier is up, you and all allies within have resistance to physical damage from outside the barrier.

When you move, the barrier follows you.

@Template[type:emanation|range:vc]

", "chatDisplay": true, "actionType": "action", "cost": [], @@ -22,7 +22,7 @@ "value": null, "max": "1", "recovery": "shortRest", - "consumeOnSuccess": false + "consumeOnSuccess": true }, "damage": { "parts": [ @@ -93,8 +93,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784502, - "modifiedTime": 1754339870857, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499308449, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "HtWx5IIemCoorMj2", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Restoration_wUQFsRtww18naYaq.json b/src/packs/domains/domainCard_Restoration_wUQFsRtww18naYaq.json index e0d05dd3..c75e8ca6 100644 --- a/src/packs/domains/domainCard_Restoration_wUQFsRtww18naYaq.json +++ b/src/packs/domains/domainCard_Restoration_wUQFsRtww18naYaq.json @@ -14,7 +14,8 @@ "value": 0, "recovery": "longRest", "max": "@cast", - "icon": "" + "icon": "", + "progression": "decreasing" }, "actions": { "udmHKUtCDClxeB4h": { @@ -214,8 +215,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784502, - "modifiedTime": 1754269768509, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754498742091, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "wUQFsRtww18naYaq", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Shadowbind_kguhWlidhxe2GbT0.json b/src/packs/domains/domainCard_Shadowbind_kguhWlidhxe2GbT0.json index 73608be0..000a1b1f 100644 --- a/src/packs/domains/domainCard_Shadowbind_kguhWlidhxe2GbT0.json +++ b/src/packs/domains/domainCard_Shadowbind_kguhWlidhxe2GbT0.json @@ -4,7 +4,7 @@ "type": "domainCard", "folder": "Abn46nCQst6kpGeA", "system": { - "description": "

Make a Spellcast Roll against all adversaries within Very Close range. Targets you succeed against are temporarily Restrained as their shadow binds them in place.

", + "description": "

Make a Spellcast Roll against all adversaries within Very Close range. Targets you succeed against are temporarily Restrained as their shadow binds them in place.

@Template[type:emanation|range:vc]

", "domain": "midnight", "recallCost": 0, "level": 2, @@ -14,7 +14,7 @@ "type": "attack", "_id": "Llr9uIDUCrfsiZNn", "systemPath": "actions", - "description": "

Make a Spellcast Roll against all adversaries within Very Close range. Targets you succeed against are temporarily Restrained as their shadow binds them in place.

", + "description": "

Make a Spellcast Roll against all adversaries within Very Close range. Targets you succeed against are temporarily Restrained as their shadow binds them in place.

@Template[type:emanation|range:vc]

", "chatDisplay": true, "actionType": "action", "cost": [], @@ -72,8 +72,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784512, - "modifiedTime": 1754330643864, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499502570, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "kguhWlidhxe2GbT0", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Share_the_Burden_8nRle10pw1HO8QVu.json b/src/packs/domains/domainCard_Share_the_Burden_8nRle10pw1HO8QVu.json index ec17d233..62c4de86 100644 --- a/src/packs/domains/domainCard_Share_the_Burden_8nRle10pw1HO8QVu.json +++ b/src/packs/domains/domainCard_Share_the_Burden_8nRle10pw1HO8QVu.json @@ -9,7 +9,31 @@ "recallCost": 0, "level": 6, "type": "spell", - "actions": {} + "actions": { + "MjSx44ovuKBGVKGs": { + "type": "effect", + "_id": "MjSx44ovuKBGVKGs", + "systemPath": "actions", + "description": "

Once per rest, take on the Stress from a willing creature within Melee range. The target describes what intimate knowledge or emotions telepathically leak from their mind in this moment between you. Transfer any number of their marked Stress to you, then gain a Hope for each Stress transferred.

", + "chatDisplay": true, + "actionType": "action", + "cost": [], + "uses": { + "value": null, + "max": "1", + "recovery": "shortRest", + "consumeOnSuccess": false + }, + "effects": [], + "target": { + "type": "any", + "amount": null + }, + "name": "Take Stress", + "img": "systems/daggerheart/assets/icons/domains/domain-card/grace.png", + "range": "" + } + } }, "flags": {}, "_stats": { @@ -20,8 +44,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784515, - "modifiedTime": 1754327488946, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499760780, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "8nRle10pw1HO8QVu", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Smite_U1uWJE94HZVudujz.json b/src/packs/domains/domainCard_Smite_U1uWJE94HZVudujz.json index 8a67261a..939fff19 100644 --- a/src/packs/domains/domainCard_Smite_U1uWJE94HZVudujz.json +++ b/src/packs/domains/domainCard_Smite_U1uWJE94HZVudujz.json @@ -29,8 +29,8 @@ ], "uses": { "value": null, - "max": "", - "recovery": null, + "max": "1", + "recovery": "shortRest", "consumeOnSuccess": false }, "effects": [ @@ -58,8 +58,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784519, - "modifiedTime": 1754269704377, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754498725946, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "U1uWJE94HZVudujz", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Splintering_Strike_TYKfM3H9vBXyWiH4.json b/src/packs/domains/domainCard_Splintering_Strike_TYKfM3H9vBXyWiH4.json index e5354c04..ed3d5f4c 100644 --- a/src/packs/domains/domainCard_Splintering_Strike_TYKfM3H9vBXyWiH4.json +++ b/src/packs/domains/domainCard_Splintering_Strike_TYKfM3H9vBXyWiH4.json @@ -10,9 +10,9 @@ "level": 9, "type": "ability", "actions": { - "B4vyaTibK0GiRBCW": { - "type": "effect", - "_id": "B4vyaTibK0GiRBCW", + "yjEcSlzsWGX79gpB": { + "type": "attack", + "_id": "yjEcSlzsWGX79gpB", "systemPath": "actions", "description": "

Spend a Hope and make an attack against all adversaries within your weapon’s range. Once per long rest, on a success against any targets, add up the damage dealt, then redistribute that damage however you wish between the targets you succeeded against. When you deal damage to a target, roll an additional damage die and add its result to the damage you deal to that target.

", "chatDisplay": true, @@ -29,15 +29,39 @@ ], "uses": { "value": null, - "max": "", - "recovery": null, - "consumeOnSuccess": false + "max": "1", + "recovery": "longRest", + "consumeOnSuccess": true + }, + "damage": { + "parts": [], + "includeBase": false }, - "effects": [], "target": { "type": "any", "amount": null }, + "effects": [], + "roll": { + "type": "attack", + "trait": null, + "difficulty": null, + "bonus": null, + "advState": "neutral", + "diceRolling": { + "multiplier": "prof", + "flatMultiplier": 1, + "dice": "d6", + "compare": null, + "treshold": null + }, + "useDefault": false + }, + "save": { + "trait": null, + "difficulty": null, + "damageMod": "none" + }, "name": "Spend Hope", "img": "icons/skills/melee/strike-sword-steel-yellow.webp", "range": "" @@ -53,7 +77,7 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784522, - "modifiedTime": 1754252510860, + "modifiedTime": 1754501075258, "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "TYKfM3H9vBXyWiH4", diff --git a/src/packs/domains/domainCard_Strategic_Approach_5b1awkgTmMp3FVrm.json b/src/packs/domains/domainCard_Strategic_Approach_5b1awkgTmMp3FVrm.json index 19f05212..ae4ab09d 100644 --- a/src/packs/domains/domainCard_Strategic_Approach_5b1awkgTmMp3FVrm.json +++ b/src/packs/domains/domainCard_Strategic_Approach_5b1awkgTmMp3FVrm.json @@ -11,10 +11,11 @@ "type": "ability", "resource": { "type": "simple", - "value": 1, - "max": "", + "value": 0, + "max": "max(@system.traits.knowledge.value, 1)", "icon": "fa-solid fa-bullseye", - "recovery": "longRest" + "recovery": "longRest", + "progression": "decreasing" }, "actions": { "jTC0GbsBpGmaQLi7": { @@ -60,7 +61,7 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784523, - "modifiedTime": 1754249661976, + "modifiedTime": 1754501630846, "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "5b1awkgTmMp3FVrm", diff --git a/src/packs/domains/domainCard_Towering_Stalk_n0P3VS1WfxvmXbB6.json b/src/packs/domains/domainCard_Towering_Stalk_n0P3VS1WfxvmXbB6.json index d632315f..124144a8 100644 --- a/src/packs/domains/domainCard_Towering_Stalk_n0P3VS1WfxvmXbB6.json +++ b/src/packs/domains/domainCard_Towering_Stalk_n0P3VS1WfxvmXbB6.json @@ -108,16 +108,17 @@ "cost": [ { "scalable": false, - "key": "n0P3VS1WfxvmXbB6", + "key": "hitPoints", "value": 1, - "keyIsID": true, - "step": null + "keyIsID": false, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, - "max": "", - "recovery": null + "max": "1", + "recovery": "shortRest" }, "effects": [], "target": { @@ -129,13 +130,7 @@ "range": "" } }, - "resource": { - "type": "simple", - "value": 1, - "recovery": "shortRest", - "max": "1", - "icon": "" - } + "resource": null }, "flags": {}, "_stats": { @@ -146,8 +141,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784534, - "modifiedTime": 1754338673637, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499113867, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "n0P3VS1WfxvmXbB6", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Unleash_Chaos_o62i0QdbUDIiAhSq.json b/src/packs/domains/domainCard_Unleash_Chaos_o62i0QdbUDIiAhSq.json index cca1f984..17f934d6 100644 --- a/src/packs/domains/domainCard_Unleash_Chaos_o62i0QdbUDIiAhSq.json +++ b/src/packs/domains/domainCard_Unleash_Chaos_o62i0QdbUDIiAhSq.json @@ -14,7 +14,8 @@ "value": 0, "max": "@cast", "icon": "", - "recovery": "session" + "recovery": "session", + "progression": "decreasing" }, "actions": { "MWvrKuwejWcQm7N1": { @@ -143,8 +144,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784537, - "modifiedTime": 1754253370819, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754501257508, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "o62i0QdbUDIiAhSq", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Wild_Surge_DjnKlZQYaWdQGKcK.json b/src/packs/domains/domainCard_Wild_Surge_DjnKlZQYaWdQGKcK.json index 10062194..269139cf 100644 --- a/src/packs/domains/domainCard_Wild_Surge_DjnKlZQYaWdQGKcK.json +++ b/src/packs/domains/domainCard_Wild_Surge_DjnKlZQYaWdQGKcK.json @@ -20,7 +20,7 @@ "type": "effect", "_id": "nYu6LRNVDKfWUJhx", "systemPath": "actions", - "description": "", + "description": "

Once per long rest, mark a Stress to channel the natural world around you and enhance yourself. Describe how your appearance changes, then place a d6 on this card with the 1 value facing up.

While the Wild Surge Die is active, you add its value to every action roll you make. After you add its value to a roll, increase the Wild Surge Die’s value by one. When the die’s value would exceed 6 or you take a rest, this form drops and you must mark an additional Stress.

", "chatDisplay": true, "actionType": "action", "cost": [ @@ -34,8 +34,8 @@ ], "uses": { "value": null, - "max": "", - "recovery": null + "max": "1", + "recovery": "longRest" }, "effects": [], "target": { @@ -57,8 +57,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784547, - "modifiedTime": 1754340095871, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754499199811, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "DjnKlZQYaWdQGKcK", "sort": 3400000, diff --git a/src/packs/domains/domainCard_Zone_of_Protection_lOZaRb4fCVgQsWB5.json b/src/packs/domains/domainCard_Zone_of_Protection_lOZaRb4fCVgQsWB5.json index f94f270c..c712284d 100644 --- a/src/packs/domains/domainCard_Zone_of_Protection_lOZaRb4fCVgQsWB5.json +++ b/src/packs/domains/domainCard_Zone_of_Protection_lOZaRb4fCVgQsWB5.json @@ -4,7 +4,7 @@ "type": "domainCard", "folder": "OwsbTSWzKq2WJmQN", "system": { - "description": "

Make a Spellcast Roll (16). Once per long rest on a success, choose a point within Far range and create a visible zone of protection there for all allies within Very Close range of that point. When you do, place a d6 on this card with the 1 value facing up. When an ally in this zone takes damage, they reduce it by the die’s value. You then increase the die’s value by one. When the die’s value would exceed 6, this effect ends.

@Template[type:emanation|range:vc]

", + "description": "

Make a Spellcast Roll (16). Once per long rest on a success, choose a point within Far range and create a visible zone of protection there for all allies within Very Close range of that point. When you do, place a d6 on this card with the 1 value facing up. When an ally in this zone takes damage, they reduce it by the die’s value. You then increase the die’s value by one. When the die’s value would exceed 6, this effect ends.

@Template[type:emanation|range:vc]

", "domain": "splendor", "recallCost": 2, "level": 6, @@ -58,13 +58,7 @@ "range": "far" } }, - "resource": { - "type": "simple", - "value": 0, - "max": "6", - "icon": "", - "recovery": "longRest" - } + "resource": null }, "flags": {}, "_stats": { @@ -75,8 +69,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1753922784549, - "modifiedTime": 1754269795161, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754498786877, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_id": "lOZaRb4fCVgQsWB5", "sort": 3400000, diff --git a/src/packs/domains/folders_Level_10_pPzU9WOQNv3ckO1w.json b/src/packs/domains/folders_Level_10_pPzU9WOQNv3ckO1w.json index 3862d063..1f1931b2 100644 --- a/src/packs/domains/folders_Level_10_pPzU9WOQNv3ckO1w.json +++ b/src/packs/domains/folders_Level_10_pPzU9WOQNv3ckO1w.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "pPzU9WOQNv3ckO1w", "description": "", - "sort": 1000000, + "sort": 2000000, "flags": {}, "_stats": { "compendiumSource": null, @@ -15,8 +15,8 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "lastModifiedBy": "YNJ4HgHtFrTI89mx", - "modifiedTime": 1752681545540 + "lastModifiedBy": "MQSznptE5yLT7kj8", + "modifiedTime": 1754499337594 }, "_key": "!folders!pPzU9WOQNv3ckO1w" } diff --git a/src/packs/domains/folders_Level_1_EJoXzO85rG5EiZsh.json b/src/packs/domains/folders_Level_1_EJoXzO85rG5EiZsh.json index 9217a20b..9423f226 100644 --- a/src/packs/domains/folders_Level_1_EJoXzO85rG5EiZsh.json +++ b/src/packs/domains/folders_Level_1_EJoXzO85rG5EiZsh.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "EJoXzO85rG5EiZsh", "description": "", - "sort": 100000, + "sort": 1100000, "flags": {}, "_stats": { "compendiumSource": null, @@ -15,8 +15,8 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "lastModifiedBy": "YNJ4HgHtFrTI89mx", - "modifiedTime": 1752681545540 + "lastModifiedBy": "MQSznptE5yLT7kj8", + "modifiedTime": 1754499330683 }, "_key": "!folders!EJoXzO85rG5EiZsh" } diff --git a/src/packs/domains/folders_Level_2_xZrCYAd05ayNu1yW.json b/src/packs/domains/folders_Level_2_xZrCYAd05ayNu1yW.json index e9a40501..7a56682e 100644 --- a/src/packs/domains/folders_Level_2_xZrCYAd05ayNu1yW.json +++ b/src/packs/domains/folders_Level_2_xZrCYAd05ayNu1yW.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "xZrCYAd05ayNu1yW", "description": "", - "sort": 200000, + "sort": 1200000, "flags": {}, "_stats": { "compendiumSource": null, @@ -15,8 +15,8 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "lastModifiedBy": "YNJ4HgHtFrTI89mx", - "modifiedTime": 1752681545540 + "lastModifiedBy": "MQSznptE5yLT7kj8", + "modifiedTime": 1754499331503 }, "_key": "!folders!xZrCYAd05ayNu1yW" } diff --git a/src/packs/domains/folders_Level_3_uXGugK72AffddFdH.json b/src/packs/domains/folders_Level_3_uXGugK72AffddFdH.json index c57e63f7..63c28dc7 100644 --- a/src/packs/domains/folders_Level_3_uXGugK72AffddFdH.json +++ b/src/packs/domains/folders_Level_3_uXGugK72AffddFdH.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "uXGugK72AffddFdH", "description": "", - "sort": 300000, + "sort": 1300000, "flags": {}, "_stats": { "compendiumSource": null, @@ -15,8 +15,8 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "lastModifiedBy": "YNJ4HgHtFrTI89mx", - "modifiedTime": 1752681545540 + "lastModifiedBy": "MQSznptE5yLT7kj8", + "modifiedTime": 1754499332151 }, "_key": "!folders!uXGugK72AffddFdH" } diff --git a/src/packs/domains/folders_Level_4_BJIiOIWAQUz5zuqo.json b/src/packs/domains/folders_Level_4_BJIiOIWAQUz5zuqo.json index 51cc633d..7a709b1b 100644 --- a/src/packs/domains/folders_Level_4_BJIiOIWAQUz5zuqo.json +++ b/src/packs/domains/folders_Level_4_BJIiOIWAQUz5zuqo.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "BJIiOIWAQUz5zuqo", "description": "", - "sort": 400000, + "sort": 1400000, "flags": {}, "_stats": { "compendiumSource": null, @@ -15,8 +15,8 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "lastModifiedBy": "YNJ4HgHtFrTI89mx", - "modifiedTime": 1752681545540 + "lastModifiedBy": "MQSznptE5yLT7kj8", + "modifiedTime": 1754499332813 }, "_key": "!folders!BJIiOIWAQUz5zuqo" } diff --git a/src/packs/domains/folders_Level_5_ZZHIbaynhzVArA1p.json b/src/packs/domains/folders_Level_5_ZZHIbaynhzVArA1p.json index 979c57cb..ae30d6cf 100644 --- a/src/packs/domains/folders_Level_5_ZZHIbaynhzVArA1p.json +++ b/src/packs/domains/folders_Level_5_ZZHIbaynhzVArA1p.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "ZZHIbaynhzVArA1p", "description": "", - "sort": 500000, + "sort": 1500000, "flags": {}, "_stats": { "compendiumSource": null, @@ -15,8 +15,8 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "lastModifiedBy": "YNJ4HgHtFrTI89mx", - "modifiedTime": 1752681545540 + "lastModifiedBy": "MQSznptE5yLT7kj8", + "modifiedTime": 1754499333460 }, "_key": "!folders!ZZHIbaynhzVArA1p" } diff --git a/src/packs/domains/folders_Level_6_u5Lq2kfC8LlDAGDC.json b/src/packs/domains/folders_Level_6_u5Lq2kfC8LlDAGDC.json index 8227afb8..cf8ffd59 100644 --- a/src/packs/domains/folders_Level_6_u5Lq2kfC8LlDAGDC.json +++ b/src/packs/domains/folders_Level_6_u5Lq2kfC8LlDAGDC.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "u5Lq2kfC8LlDAGDC", "description": "", - "sort": 550000, + "sort": 1600000, "flags": {}, "_stats": { "compendiumSource": null, @@ -15,8 +15,8 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "lastModifiedBy": "YNJ4HgHtFrTI89mx", - "modifiedTime": 1752681547474 + "lastModifiedBy": "MQSznptE5yLT7kj8", + "modifiedTime": 1754499335115 }, "_key": "!folders!u5Lq2kfC8LlDAGDC" } diff --git a/src/packs/domains/folders_Level_7_gEVGjjPrjqxxZkb5.json b/src/packs/domains/folders_Level_7_gEVGjjPrjqxxZkb5.json index 7cc2eb64..1b10b32e 100644 --- a/src/packs/domains/folders_Level_7_gEVGjjPrjqxxZkb5.json +++ b/src/packs/domains/folders_Level_7_gEVGjjPrjqxxZkb5.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "gEVGjjPrjqxxZkb5", "description": "", - "sort": 575000, + "sort": 1700000, "flags": {}, "_stats": { "compendiumSource": null, @@ -15,8 +15,8 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "lastModifiedBy": "YNJ4HgHtFrTI89mx", - "modifiedTime": 1752681548701 + "lastModifiedBy": "MQSznptE5yLT7kj8", + "modifiedTime": 1754499335821 }, "_key": "!folders!gEVGjjPrjqxxZkb5" } diff --git a/src/packs/domains/folders_Level_8_qY4Zqc1Ch6p317uK.json b/src/packs/domains/folders_Level_8_qY4Zqc1Ch6p317uK.json index f33373f3..6b91dfe3 100644 --- a/src/packs/domains/folders_Level_8_qY4Zqc1Ch6p317uK.json +++ b/src/packs/domains/folders_Level_8_qY4Zqc1Ch6p317uK.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "qY4Zqc1Ch6p317uK", "description": "", - "sort": 587500, + "sort": 1800000, "flags": {}, "_stats": { "compendiumSource": null, @@ -15,8 +15,8 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "lastModifiedBy": "YNJ4HgHtFrTI89mx", - "modifiedTime": 1752681549490 + "lastModifiedBy": "MQSznptE5yLT7kj8", + "modifiedTime": 1754499336356 }, "_key": "!folders!qY4Zqc1Ch6p317uK" } diff --git a/src/packs/domains/folders_Level_9_R5afi5bhq9ccnYY2.json b/src/packs/domains/folders_Level_9_R5afi5bhq9ccnYY2.json index cbf3f378..6e3657b4 100644 --- a/src/packs/domains/folders_Level_9_R5afi5bhq9ccnYY2.json +++ b/src/packs/domains/folders_Level_9_R5afi5bhq9ccnYY2.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "R5afi5bhq9ccnYY2", "description": "", - "sort": 600000, + "sort": 1900000, "flags": {}, "_stats": { "compendiumSource": null, @@ -15,8 +15,8 @@ "coreVersion": "13.346", "systemId": "daggerheart", "systemVersion": "0.0.1", - "lastModifiedBy": "YNJ4HgHtFrTI89mx", - "modifiedTime": 1752681545540 + "lastModifiedBy": "MQSznptE5yLT7kj8", + "modifiedTime": 1754499336949 }, "_key": "!folders!R5afi5bhq9ccnYY2" } diff --git a/src/packs/subclasses/feature_Clarity_of_Nature_etaQ01yGJhBLDUqZ.json b/src/packs/subclasses/feature_Clarity_of_Nature_etaQ01yGJhBLDUqZ.json index 7906daf6..752fee05 100644 --- a/src/packs/subclasses/feature_Clarity_of_Nature_etaQ01yGJhBLDUqZ.json +++ b/src/packs/subclasses/feature_Clarity_of_Nature_etaQ01yGJhBLDUqZ.json @@ -6,13 +6,7 @@ "img": "icons/magic/nature/tree-twisted-glow-yellow.webp", "system": { "description": "

Once per long rest, you can create a space of natural serenity within Close range. When you spend a few minutes resting within the space, clear Stress equal to your Instinct, distributed as you choose between you and your allies.

", - "resource": { - "type": "simple", - "value": 1, - "recovery": "longRest", - "max": "1", - "icon": "" - }, + "resource": null, "actions": { "az7YUpxy1ysn12tO": { "type": "healing", @@ -108,7 +102,7 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754179740310, - "modifiedTime": 1754353339637, + "modifiedTime": 1754496518048, "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!items!etaQ01yGJhBLDUqZ" diff --git a/src/packs/subclasses/feature_Contacts_Everywhere_cXbRm744mW6UXGam.json b/src/packs/subclasses/feature_Contacts_Everywhere_cXbRm744mW6UXGam.json index 84425f80..3c8fa5b5 100644 --- a/src/packs/subclasses/feature_Contacts_Everywhere_cXbRm744mW6UXGam.json +++ b/src/packs/subclasses/feature_Contacts_Everywhere_cXbRm744mW6UXGam.json @@ -6,13 +6,7 @@ "img": "icons/skills/social/theft-pickpocket-bribery-brown.webp", "system": { "description": "

Once per session, you can briefly call on a shady contact. Choose one of the following benefits and describe what brought them here to help you in this moment:

", - "resource": { - "type": "simple", - "value": 1, - "max": "", - "icon": "", - "recovery": "session" - }, + "resource": null, "actions": { "GZDYjtPh0lCJ5VNq": { "type": "effect", @@ -24,16 +18,17 @@ "cost": [ { "scalable": false, - "key": "cXbRm744mW6UXGam", + "key": "hitPoints", "value": 1, - "keyIsID": true, - "step": null + "keyIsID": false, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, - "max": "", - "recovery": null + "max": "1", + "recovery": "session" }, "effects": [], "target": { @@ -63,8 +58,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754320389008, - "modifiedTime": 1754322535699, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754496752362, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!items!cXbRm744mW6UXGam" } diff --git a/src/packs/subclasses/feature_Eloquent_5bmB1YcxiJVNVXDM.json b/src/packs/subclasses/feature_Eloquent_5bmB1YcxiJVNVXDM.json index 0d80a6f6..daca1154 100644 --- a/src/packs/subclasses/feature_Eloquent_5bmB1YcxiJVNVXDM.json +++ b/src/packs/subclasses/feature_Eloquent_5bmB1YcxiJVNVXDM.json @@ -5,15 +5,7 @@ "img": "icons/skills/social/diplomacy-writing-letter.webp", "system": { "description": "

Your moving words boost morale. Once per session, when you encourage an ally, you can do one of the following:

", - "resource": { - "type": "simple", - "value": 1, - "recovery": "session", - "max": "1", - "icon": "", - "diceStates": {}, - "dieFaces": "d4" - }, + "resource": null, "actions": { "o1MWnafbLsXnvSUl": { "type": "effect", @@ -25,8 +17,8 @@ "cost": [], "uses": { "value": null, - "max": "", - "recovery": null + "max": "1", + "recovery": "session" }, "effects": [], "target": { @@ -51,8 +43,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754174646194, - "modifiedTime": 1754236474581, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754494786779, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "ownership": { "default": 0, diff --git a/src/packs/subclasses/feature_Gifted_Performer_99U7YWNCxFZHCiT0.json b/src/packs/subclasses/feature_Gifted_Performer_99U7YWNCxFZHCiT0.json index 5319981f..57cbdc0c 100644 --- a/src/packs/subclasses/feature_Gifted_Performer_99U7YWNCxFZHCiT0.json +++ b/src/packs/subclasses/feature_Gifted_Performer_99U7YWNCxFZHCiT0.json @@ -16,9 +16,9 @@ "actionType": "action", "cost": [], "uses": { - "value": null, - "max": "", - "recovery": null + "value": 0, + "max": "1", + "recovery": "longRest" }, "damage": { "parts": [ @@ -83,9 +83,9 @@ "actionType": "action", "cost": [], "uses": { - "value": null, - "max": "", - "recovery": null + "value": 0, + "max": "1", + "recovery": "longRest" }, "effects": [ { @@ -110,8 +110,8 @@ "actionType": "action", "cost": [], "uses": { - "value": null, - "max": "", + "value": 0, + "max": "1", "recovery": "longRest" }, "damage": { @@ -228,8 +228,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754174646194, - "modifiedTime": 1754236401349, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754475491670, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "ownership": { "default": 0, diff --git a/src/packs/subclasses/feature_Loyal_Friend_xjZHD5Yo3Tu26rLm.json b/src/packs/subclasses/feature_Loyal_Friend_xjZHD5Yo3Tu26rLm.json index 55d09063..5f8c3ed7 100644 --- a/src/packs/subclasses/feature_Loyal_Friend_xjZHD5Yo3Tu26rLm.json +++ b/src/packs/subclasses/feature_Loyal_Friend_xjZHD5Yo3Tu26rLm.json @@ -7,7 +7,31 @@ "system": { "description": "

Once per long rest, when the damage from an attack would mark your companion’s last Stress or your last Hit Point and you’re within Close range of each other, you or your companion can rush to the other’s side and take that damage instead.

", "resource": null, - "actions": {}, + "actions": { + "Z82YQzYWo4eektMa": { + "type": "effect", + "_id": "Z82YQzYWo4eektMa", + "systemPath": "actions", + "description": "

Once per long rest, when the damage from an attack would mark your companion’s last Stress or your last Hit Point and you’re within Close range of each other, you or your companion can rush to the other’s side and take that damage instead.

", + "chatDisplay": true, + "actionType": "action", + "cost": [], + "uses": { + "value": null, + "max": "1", + "recovery": "longRest", + "consumeOnSuccess": false + }, + "effects": [], + "target": { + "type": "any", + "amount": null + }, + "name": "Rush", + "img": "icons/creatures/mammals/humanoid-wolf-dog-blue.webp", + "range": "close" + } + }, "originItemType": null, "originId": null }, @@ -26,8 +50,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754267956703, - "modifiedTime": 1754267994139, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754496703770, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!items!xjZHD5Yo3Tu26rLm" } diff --git a/src/packs/subclasses/feature_Rousing_Speech_PCmYTX02JLzBpgml.json b/src/packs/subclasses/feature_Rousing_Speech_PCmYTX02JLzBpgml.json index b9f7dab7..312e055b 100644 --- a/src/packs/subclasses/feature_Rousing_Speech_PCmYTX02JLzBpgml.json +++ b/src/packs/subclasses/feature_Rousing_Speech_PCmYTX02JLzBpgml.json @@ -5,15 +5,7 @@ "img": "icons/tools/instruments/megaphone.webp", "system": { "description": "

Once per long rest, you can give a heartfelt, inspiring speech. All allies within Far range clear 2 Stress.

", - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "icon": "", - "recovery": "longRest", - "diceStates": {}, - "dieFaces": "d4" - }, + "resource": null, "actions": { "WNtHiko4DRGbxKnm": { "type": "healing", @@ -25,15 +17,16 @@ "cost": [ { "scalable": false, - "key": "iLytX899psvrPRnG", + "key": "hitPoints", "value": 1, - "keyIsID": true, - "step": null + "keyIsID": false, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, - "max": "", + "max": "1", "recovery": "longRest" }, "damage": { @@ -104,8 +97,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754174646194, - "modifiedTime": 1754236406644, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754494763682, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "ownership": { "default": 0, diff --git a/src/packs/subclasses/feature_Sparing_Touch_GfOSgVJW8bS1OjNq.json b/src/packs/subclasses/feature_Sparing_Touch_GfOSgVJW8bS1OjNq.json index 832b5532..cf0a8f93 100644 --- a/src/packs/subclasses/feature_Sparing_Touch_GfOSgVJW8bS1OjNq.json +++ b/src/packs/subclasses/feature_Sparing_Touch_GfOSgVJW8bS1OjNq.json @@ -8,9 +8,10 @@ "description": "

Once per long rest, touch a creature and clear 2 Hit Points or 2 Stress from them.

", "resource": { "type": "simple", - "value": 0, + "value": 1, + "progression": "decreasing", "max": "1", - "icon": "", + "icon": "fa-solid fa-hands-praying", "recovery": "longRest" }, "actions": { @@ -69,7 +70,7 @@ }, "target": { "type": "any", - "amount": null + "amount": 1 }, "effects": [], "roll": { @@ -98,7 +99,16 @@ "description": "

Once per long rest, touch a creature and clear 2 Hit Points or 2 Stress from them.

", "chatDisplay": true, "actionType": "action", - "cost": [], + "cost": [ + { + "scalable": false, + "key": "GfOSgVJW8bS1OjNq", + "value": 1, + "keyIsID": true, + "step": null, + "consumeOnSuccess": false + } + ], "uses": { "value": null, "max": "", @@ -137,7 +147,7 @@ }, "target": { "type": "any", - "amount": null + "amount": 1 }, "effects": [], "roll": { @@ -178,7 +188,7 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754353243691, - "modifiedTime": 1754353387422, + "modifiedTime": 1754500973073, "lastModifiedBy": "Q9NoTaEarn3VMS6Z" }, "_key": "!items!GfOSgVJW8bS1OjNq" diff --git a/src/packs/subclasses/feature_Transcendence_th6HZwEFnVBjUtqm.json b/src/packs/subclasses/feature_Transcendence_th6HZwEFnVBjUtqm.json index cffaba38..cf2c658d 100644 --- a/src/packs/subclasses/feature_Transcendence_th6HZwEFnVBjUtqm.json +++ b/src/packs/subclasses/feature_Transcendence_th6HZwEFnVBjUtqm.json @@ -6,15 +6,7 @@ "img": "icons/magic/fire/elemental-fire-flying.webp", "system": { "description": "

Once per long rest, you can transform into a physical manifestation of your element. When you do, describe your transformation and choose two of the following benefits to gain until your next rest:

", - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "icon": "", - "recovery": "longRest", - "diceStates": {}, - "dieFaces": "d4" - }, + "resource": null, "actions": { "RIbyJjEkCgqoDmyn": { "type": "effect", @@ -26,17 +18,17 @@ "cost": [ { "scalable": false, - "key": "th6HZwEFnVBjUtqm", + "key": "hitPoints", "value": 1, - "keyIsID": true, + "keyIsID": false, "step": null, "consumeOnSuccess": false } ], "uses": { "value": null, - "max": "", - "recovery": null, + "max": "1", + "recovery": "longRest", "consumeOnSuccess": false }, "effects": [], @@ -250,8 +242,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754349515898, - "modifiedTime": 1754349515898, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754497438787, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!items!th6HZwEFnVBjUtqm" } diff --git a/src/packs/subclasses/feature_Warden_s_Protection_2F1bUFY80oce97C9.json b/src/packs/subclasses/feature_Warden_s_Protection_2F1bUFY80oce97C9.json index b681d64e..3d6055d2 100644 --- a/src/packs/subclasses/feature_Warden_s_Protection_2F1bUFY80oce97C9.json +++ b/src/packs/subclasses/feature_Warden_s_Protection_2F1bUFY80oce97C9.json @@ -6,13 +6,7 @@ "img": "icons/magic/nature/barrier-shield-wood-vines.webp", "system": { "description": "

Once per long rest, spend 2 Hope to clear 2 Hit Points on 1d4 allies within Close range.

", - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "icon": "", - "recovery": "longRest" - }, + "resource": null, "actions": { "ozYzhQfRt5sp19di": { "type": "healing", @@ -23,7 +17,7 @@ "actionType": "action", "cost": [], "uses": { - "value": null, + "value": 0, "max": "1", "recovery": "longRest", "consumeOnSuccess": false @@ -101,7 +95,7 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754183079986, - "modifiedTime": 1754353582707, + "modifiedTime": 1754496541966, "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!items!2F1bUFY80oce97C9" diff --git a/src/packs/subclasses/folders_Bard_0DMzpFZB8A6vwpRX.json b/src/packs/subclasses/folders_Bard_0DMzpFZB8A6vwpRX.json index 1c1e3286..f325dd28 100644 --- a/src/packs/subclasses/folders_Bard_0DMzpFZB8A6vwpRX.json +++ b/src/packs/subclasses/folders_Bard_0DMzpFZB8A6vwpRX.json @@ -6,7 +6,7 @@ "sorting": "m", "_id": "0DMzpFZB8A6vwpRX", "description": "", - "sort": 200000, + "sort": 1000000, "flags": {}, "_stats": { "compendiumSource": null, @@ -16,8 +16,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754236641265, - "modifiedTime": 1754268224220, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754501841544, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!folders!0DMzpFZB8A6vwpRX" } diff --git a/src/packs/subclasses/folders_Druid_AZWrSJzGXltzQhAJ.json b/src/packs/subclasses/folders_Druid_AZWrSJzGXltzQhAJ.json index 6be0ee6d..325060e7 100644 --- a/src/packs/subclasses/folders_Druid_AZWrSJzGXltzQhAJ.json +++ b/src/packs/subclasses/folders_Druid_AZWrSJzGXltzQhAJ.json @@ -6,7 +6,7 @@ "sorting": "m", "_id": "AZWrSJzGXltzQhAJ", "description": "", - "sort": 300000, + "sort": 1100000, "flags": {}, "_stats": { "compendiumSource": null, @@ -16,8 +16,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754236669632, - "modifiedTime": 1754268224220, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754501843662, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!folders!AZWrSJzGXltzQhAJ" } diff --git a/src/packs/subclasses/folders_Guardian_WMlU3baiUdMgfuak.json b/src/packs/subclasses/folders_Guardian_WMlU3baiUdMgfuak.json index 21134aa6..daf366db 100644 --- a/src/packs/subclasses/folders_Guardian_WMlU3baiUdMgfuak.json +++ b/src/packs/subclasses/folders_Guardian_WMlU3baiUdMgfuak.json @@ -6,7 +6,7 @@ "sorting": "m", "_id": "WMlU3baiUdMgfuak", "description": "", - "sort": 400000, + "sort": 1200000, "flags": {}, "_stats": { "compendiumSource": null, @@ -16,8 +16,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754245852289, - "modifiedTime": 1754268224220, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754501845702, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!folders!WMlU3baiUdMgfuak" } diff --git a/src/packs/subclasses/folders_Ranger_ArVAtkgkm5bYpKHL.json b/src/packs/subclasses/folders_Ranger_ArVAtkgkm5bYpKHL.json index 2c8fd45e..658ddf81 100644 --- a/src/packs/subclasses/folders_Ranger_ArVAtkgkm5bYpKHL.json +++ b/src/packs/subclasses/folders_Ranger_ArVAtkgkm5bYpKHL.json @@ -6,7 +6,7 @@ "sorting": "m", "_id": "ArVAtkgkm5bYpKHL", "description": "", - "sort": 500000, + "sort": 1300000, "flags": {}, "_stats": { "compendiumSource": null, @@ -16,8 +16,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754268221221, - "modifiedTime": 1754268224220, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754501849009, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!folders!ArVAtkgkm5bYpKHL" } diff --git a/src/packs/subclasses/folders_Rogue_36dtJE1CPjPt76pP.json b/src/packs/subclasses/folders_Rogue_36dtJE1CPjPt76pP.json index 9209901b..6593650d 100644 --- a/src/packs/subclasses/folders_Rogue_36dtJE1CPjPt76pP.json +++ b/src/packs/subclasses/folders_Rogue_36dtJE1CPjPt76pP.json @@ -6,7 +6,7 @@ "sorting": "m", "_id": "36dtJE1CPjPt76pP", "description": "", - "sort": 550000, + "sort": 1400000, "flags": {}, "_stats": { "compendiumSource": null, @@ -16,8 +16,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754322803534, - "modifiedTime": 1754322806911, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754501852870, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!folders!36dtJE1CPjPt76pP" } diff --git a/src/packs/subclasses/folders_Seraph_RZOEu0ZYQNPs6O2c.json b/src/packs/subclasses/folders_Seraph_RZOEu0ZYQNPs6O2c.json index 8fac588e..3854caa2 100644 --- a/src/packs/subclasses/folders_Seraph_RZOEu0ZYQNPs6O2c.json +++ b/src/packs/subclasses/folders_Seraph_RZOEu0ZYQNPs6O2c.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "RZOEu0ZYQNPs6O2c", "description": "", - "sort": 0, + "sort": 1500000, "flags": {}, "_stats": { "compendiumSource": null, @@ -16,8 +16,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754352793139, - "modifiedTime": 1754352793139, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754501855742, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!folders!RZOEu0ZYQNPs6O2c" } diff --git a/src/packs/subclasses/folders_Sorcerer_F0mW5ofdyyfE2hHo.json b/src/packs/subclasses/folders_Sorcerer_F0mW5ofdyyfE2hHo.json index 8358cbaf..5aaa1502 100644 --- a/src/packs/subclasses/folders_Sorcerer_F0mW5ofdyyfE2hHo.json +++ b/src/packs/subclasses/folders_Sorcerer_F0mW5ofdyyfE2hHo.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "F0mW5ofdyyfE2hHo", "description": "", - "sort": 800000, + "sort": 1600000, "flags": {}, "_stats": { "compendiumSource": null, @@ -16,8 +16,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754349604935, - "modifiedTime": 1754349604956, - "lastModifiedBy": "Q9NoTaEarn3VMS6Z" + "modifiedTime": 1754501856827, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!folders!F0mW5ofdyyfE2hHo" } diff --git a/src/packs/subclasses/folders_Subclass_Features_Sfpr4iK1cGrmncok.json b/src/packs/subclasses/folders_Subclass_Features_Sfpr4iK1cGrmncok.json index a4f97fbe..dbbb6ee9 100644 --- a/src/packs/subclasses/folders_Subclass_Features_Sfpr4iK1cGrmncok.json +++ b/src/packs/subclasses/folders_Subclass_Features_Sfpr4iK1cGrmncok.json @@ -6,7 +6,7 @@ "sorting": "m", "_id": "Sfpr4iK1cGrmncok", "description": "", - "sort": 100000, + "sort": 900000, "flags": {}, "_stats": { "compendiumSource": null, @@ -16,8 +16,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754174646170, - "modifiedTime": 1754268224220, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754501800511, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!folders!Sfpr4iK1cGrmncok" } diff --git a/src/packs/subclasses/folders_Warrior_aTyhcJgENR9uI7u4.json b/src/packs/subclasses/folders_Warrior_aTyhcJgENR9uI7u4.json index 631be023..d9f88587 100644 --- a/src/packs/subclasses/folders_Warrior_aTyhcJgENR9uI7u4.json +++ b/src/packs/subclasses/folders_Warrior_aTyhcJgENR9uI7u4.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "aTyhcJgENR9uI7u4", "description": "", - "sort": 600000, + "sort": 1700000, "flags": {}, "_stats": { "compendiumSource": null, @@ -16,8 +16,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754256060634, - "modifiedTime": 1754268224220, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754501859285, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!folders!aTyhcJgENR9uI7u4" } diff --git a/src/packs/subclasses/folders_Wizard_Bb9SLVpYHGBrOB59.json b/src/packs/subclasses/folders_Wizard_Bb9SLVpYHGBrOB59.json index 46fe527d..744a1230 100644 --- a/src/packs/subclasses/folders_Wizard_Bb9SLVpYHGBrOB59.json +++ b/src/packs/subclasses/folders_Wizard_Bb9SLVpYHGBrOB59.json @@ -6,7 +6,7 @@ "sorting": "a", "_id": "Bb9SLVpYHGBrOB59", "description": "", - "sort": 700000, + "sort": 1800000, "flags": {}, "_stats": { "compendiumSource": null, @@ -16,8 +16,8 @@ "systemId": "daggerheart", "systemVersion": "0.0.1", "createdTime": 1754253525540, - "modifiedTime": 1754268224220, - "lastModifiedBy": "LgnbNMLaxandgMQq" + "modifiedTime": 1754501860252, + "lastModifiedBy": "MQSznptE5yLT7kj8" }, "_key": "!folders!Bb9SLVpYHGBrOB59" } diff --git a/styles/less/dialog/character-creation/selections-container.less b/styles/less/dialog/character-creation/selections-container.less index 9f81f93b..bc7a6987 100644 --- a/styles/less/dialog/character-creation/selections-container.less +++ b/styles/less/dialog/character-creation/selections-container.less @@ -112,6 +112,10 @@ flex-direction: column; text-align: center; + .card-preview-container { + flex: 1; + } + .card-preview-container { border-color: light-dark(@dark-blue, @golden); } @@ -157,7 +161,10 @@ .selections-outer-container { display: flex; justify-content: space-evenly; - height: 210px; + + &.enlarged { + height: 240px; + } } .section-container { diff --git a/styles/less/dialog/level-up/selections-container.less b/styles/less/dialog/level-up/selections-container.less index 843fead0..a13c9ff3 100644 --- a/styles/less/dialog/level-up/selections-container.less +++ b/styles/less/dialog/level-up/selections-container.less @@ -83,10 +83,15 @@ background: grey; padding: 0 12px; border-radius: 6px; + z-index: 2; } img { height: 124px; + + &.svg { + filter: @beige-filter; + } } .levelup-domain-selected { @@ -138,6 +143,11 @@ padding: 0 12px; } + .levelup-trait-increases, + .levelup-experience-increases { + width: 100%; + } + .levelup-radio-choices { display: flex; gap: 8px; diff --git a/styles/less/dialog/level-up/tiers-container.less b/styles/less/dialog/level-up/tiers-container.less index 1149ede3..225c31fb 100644 --- a/styles/less/dialog/level-up/tiers-container.less +++ b/styles/less/dialog/level-up/tiers-container.less @@ -27,6 +27,7 @@ } .checkbox-group-container { + width: 100%; display: grid; grid-template-columns: 1fr 3fr; gap: 4px; diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index 35262b3b..7f8cdd94 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -486,8 +486,42 @@ flex-wrap: wrap; margin-top: 2px; - button { - white-space: nowrap; + .item-button { + display: flex; + border: 1px solid light-dark(#18162e, #18162e); + color: light-dark(#18162e, #18162e); + outline: none; + box-shadow: none; + border-radius: 6px; + + button { + border-radius: 3px 0px 0px 3px; + color: light-dark(@dark-blue, @dark-blue); + white-space: nowrap; + border: 0; + font-family: @font-body; + + &:hover { + color: light-dark(@dark-blue, @golden); + } + + &:not(:first-child) { + padding: 6px; + background: light-dark(@dark-blue-10, @golden-secondary); + border-radius: 0px 3px 3px 0px; + color: light-dark(@dark-blue, @dark-golden); + + &:hover { + background: light-dark(@light-black, @dark-blue); + color: light-dark(@dark-blue, @golden-secondary); + } + } + } + + .spacer { + border-right: 1px solid black; + content: ''; + } } } } @@ -644,6 +678,12 @@ } &.theme-light { + .tagify { + tag div img { + filter: @beige-filter; + } + } + .tagify__dropdown { .tagify__dropdown__wrapper { background-image: url(../assets/parchments/dh-parchment-light.png); diff --git a/styles/less/global/inventory-item.less b/styles/less/global/inventory-item.less index 0ca383d5..e79a88c7 100644 --- a/styles/less/global/inventory-item.less +++ b/styles/less/global/inventory-item.less @@ -24,13 +24,15 @@ width: 100%; list-style-type: none; - &:not(.single-img):hover { - .inventory-item-header .img-portait { - .roll-img { - opacity: 1; - } - .item-img { - opacity: 0; + &:not(.single-img) { + .inventory-item-header:hover { + .img-portait { + .roll-img { + opacity: 1; + } + .item-img { + opacity: 0; + } } } } diff --git a/styles/less/global/tab-navigation.less b/styles/less/global/tab-navigation.less index 014da89f..53295b63 100755 --- a/styles/less/global/tab-navigation.less +++ b/styles/less/global/tab-navigation.less @@ -17,6 +17,7 @@ .feature-tab { border: none; + white-space: nowrap; a { color: light-dark(@dark-blue, @golden); diff --git a/styles/less/sheets-settings/adversary-settings/experiences.less b/styles/less/sheets-settings/adversary-settings/experiences.less index dab261a6..da5e750d 100644 --- a/styles/less/sheets-settings/adversary-settings/experiences.less +++ b/styles/less/sheets-settings/adversary-settings/experiences.less @@ -26,12 +26,19 @@ align-items: center; gap: 5px; - &.no-controls { - grid-template-columns: 3fr 1fr; - } + span { + display: flex; + justify-content: center; - a { - text-align: center; + a { + text-align: center; + + &.disabled { + i { + opacity: 0.4; + } + } + } } } diff --git a/styles/less/utils/colors.less b/styles/less/utils/colors.less index aed3b7dc..64edfc6f 100755 --- a/styles/less/utils/colors.less +++ b/styles/less/utils/colors.less @@ -5,6 +5,7 @@ @golden-10: #f3c26710; @golden-40: #f3c26740; @golden-bg: #f3c2671a; +@golden-secondary: #eaaf42; @golden-filter: brightness(0) saturate(100%) invert(89%) sepia(13%) saturate(2008%) hue-rotate(332deg) brightness(99%) contrast(92%); diff --git a/styles/less/ux/tooltip/tooltip.less b/styles/less/ux/tooltip/tooltip.less index 44f8ce1a..43f47da5 100644 --- a/styles/less/ux/tooltip/tooltip.less +++ b/styles/less/ux/tooltip/tooltip.less @@ -34,6 +34,10 @@ text-align: start; } + .simple-info { + font-style: italic; + } + .tooltip-sub-title { margin: 0; color: light-dark(@dark-blue, @beige); @@ -45,6 +49,10 @@ grid-template-columns: 1fr 1fr; gap: 4px; + &.spaced { + margin-top: 8px; + } + &.triple { grid-template-columns: 1fr 1fr 1fr; } diff --git a/system.json b/system.json index 05d12975..7501cfa7 100644 --- a/system.json +++ b/system.json @@ -2,10 +2,10 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "0.0.1", + "version": "1.0.0", "compatibility": { "minimum": "13", - "verified": "13.346", + "verified": "13.347", "maximum": "13" }, "authors": [ @@ -169,7 +169,7 @@ ], "packFolders": [ { - "name": "Daggerheart", + "name": "Daggerheart SRD", "sorting": "m", "color": "#08718c", "packs": ["adversaries", "environments", "journals"], diff --git a/templates/actionTypes/beastform.hbs b/templates/actionTypes/beastform.hbs index d7ddba7a..b2710208 100644 --- a/templates/actionTypes/beastform.hbs +++ b/templates/actionTypes/beastform.hbs @@ -4,14 +4,6 @@
-
-
- - -
-

{{localize "DAGGERHEART.ACTIONS.Config.beastform.exactHint"}}

-
+ {{formGroup fields.tierAccess.fields.exact value=beastform.tierAccess.exact labelAttr="label" valueAttr="key" localize=true blank=""}}
\ No newline at end of file diff --git a/templates/characterCreation/setupTabs/ancestry.hbs b/templates/characterCreation/setupTabs/ancestry.hbs index 1c87ca47..c5895472 100644 --- a/templates/characterCreation/setupTabs/ancestry.hbs +++ b/templates/characterCreation/setupTabs/ancestry.hbs @@ -19,7 +19,7 @@ -
+
{{#> "systems/daggerheart/templates/components/card-preview.hbs" primaryAncestry altPartialBlock=true secondaryDisabled=secondaryAncestry.uuid mixedAncestry=mixedAncestry }} {{#if uuid}} diff --git a/templates/dialogs/dice-roll/costSelection.hbs b/templates/dialogs/dice-roll/costSelection.hbs index cf906538..765fbaf9 100644 --- a/templates/dialogs/dice-roll/costSelection.hbs +++ b/templates/dialogs/dice-roll/costSelection.hbs @@ -9,7 +9,7 @@
- + {{/if}} {{#each costs as | cost index |}} diff --git a/templates/dialogs/dice-roll/damageSelection.hbs b/templates/dialogs/dice-roll/damageSelection.hbs index b5b316e7..2967b675 100644 --- a/templates/dialogs/dice-roll/damageSelection.hbs +++ b/templates/dialogs/dice-roll/damageSelection.hbs @@ -9,7 +9,7 @@ {{#with (lookup @root.config.GENERAL.healingTypes applyTo)}} {{localize label}} {{/with}} - {{#unless @root.isHealing}} + {{#unless @root.hasHealing}} {{#if damageTypes}} {{#each damageTypes as | type | }} {{#with (lookup @root.config.GENERAL.damageTypes type)}} diff --git a/templates/dialogs/dice-roll/header.hbs b/templates/dialogs/dice-roll/header.hbs index cea07209..f61a86b3 100644 --- a/templates/dialogs/dice-roll/header.hbs +++ b/templates/dialogs/dice-roll/header.hbs @@ -1,6 +1,10 @@

- {{ifThen rollConfig.headerTitle rollConfig.headerTitle rollConfig.title}} + {{#if reactionOverride}} + {{localize "DAGGERHEART.CONFIG.ActionType.reaction"}} + {{else}} + {{ifThen rollConfig.headerTitle rollConfig.headerTitle rollConfig.title}} + {{/if}} {{#if showReaction}} - - -

- \ No newline at end of file diff --git a/templates/settings/variant-rules.hbs b/templates/settings/variant-rules.hbs index 75a5534b..03027f69 100644 --- a/templates/settings/variant-rules.hbs +++ b/templates/settings/variant-rules.hbs @@ -3,6 +3,17 @@

{{localize 'DAGGERHEART.SETTINGS.Menu.variantRules.name'}}

+
+ {{localize 'DAGGERHEART.SETTINGS.Menu.range.name'}} + + {{formGroup settingFields.schema.fields.rangeMeasurement.fields.enabled value=settingFields._source.rangeMeasurement.enabled localize=true}} + {{formGroup settingFields.schema.fields.rangeMeasurement.fields.melee value=settingFields._source.rangeMeasurement.melee localize=true}} + {{formGroup settingFields.schema.fields.rangeMeasurement.fields.veryClose value=settingFields._source.rangeMeasurement.veryClose localize=true}} + {{formGroup settingFields.schema.fields.rangeMeasurement.fields.close value=settingFields._source.rangeMeasurement.close localize=true}} + {{formGroup settingFields.schema.fields.rangeMeasurement.fields.far value=settingFields._source.rangeMeasurement.far localize=true}} + {{formGroup settingFields.schema.fields.rangeMeasurement.fields.veryFar value=settingFields._source.rangeMeasurement.veryFar localize=true}} +
+
@@ -12,8 +23,6 @@
- {{formGroup settingFields.schema.fields.useCoins value=settingFields._source.useCoins localize=true }} - \ No newline at end of file diff --git a/templates/ui/tooltip/beastform.hbs b/templates/ui/tooltip/beastform.hbs index fb07d895..96a77b9c 100644 --- a/templates/ui/tooltip/beastform.hbs +++ b/templates/ui/tooltip/beastform.hbs @@ -2,4 +2,30 @@

{{item.name}}

{{{description}}}
+ +
{{item.system.examples}}
+ {{> "systems/daggerheart/templates/ui/tooltip/parts/tooltipChips.hbs" chips=item.system.advantageOn label=(localize "DAGGERHEART.ITEMS.Beastform.FIELDS.advantageOn.label")}} + +
+ {{#with item.system.beastformAttackData}} +
+ +
{{this.trait}}
+
+
+ +
{{this.traitBonus}}
+
+
+ +
{{this.evasionBonus}}
+
+
+ +
{{concat this.damageDice ' ' this.damageBonus}}
+
+ {{/with}} +
+ + {{> "systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs" features=item.system.features label=(localize "DAGGERHEART.GENERAL.features")}} \ No newline at end of file diff --git a/tools/pullYMLtoLDBBuild.mjs b/tools/pullYMLtoLDBBuild.mjs new file mode 100644 index 00000000..6c2b8c79 --- /dev/null +++ b/tools/pullYMLtoLDBBuild.mjs @@ -0,0 +1,31 @@ +import { compilePack } from '@foundryvtt/foundryvtt-cli'; +import { promises as fs } from 'fs'; + +const MODULE_ID = process.cwd(); +const yaml = false; + +const packs = await deepGetDirectories('./packs'); +console.log(packs); +for (const pack of packs) { + if (pack === '.gitattributes') continue; + console.log('Packing ' + pack); + await compilePack(`${MODULE_ID}/src/${pack}`, `${MODULE_ID}/${pack}`, { yaml }); +} + +async function deepGetDirectories(distPath) { + const dirr = await fs.readdir('src/' + distPath); + const dirrsWithSub = []; + for (let file of dirr) { + const stat = await fs.stat('src/' + distPath + '/' + file); + if (stat.isDirectory()) { + const deeper = await deepGetDirectories(distPath + '/' + file); + if (deeper.length > 0) { + dirrsWithSub.push(...deeper); + } else { + dirrsWithSub.push(distPath + '/' + file); + } + } + } + + return dirrsWithSub; +}