diff --git a/gulpfile.js b/gulpfile.js index 1a81f5ae..45479a5c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -3,7 +3,7 @@ var gulp = require('gulp'); var less = require('gulp-less'); gulp.task('less', function (cb) { - gulp.src('styles/daggerheart.less').pipe(less()).on('error', console.error.bind(console)).pipe(gulp.dest('styles')); + gulp.src('styles/daggerheart.less').pipe(less()).pipe(gulp.dest('styles')); cb(); }); diff --git a/lang/en.json b/lang/en.json index b4b1410e..99a75f83 100755 --- a/lang/en.json +++ b/lang/en.json @@ -758,20 +758,15 @@ } }, "GroupRollSelect": { - "cancelConfirmText": "Are you sure you want to cancel the Group Roll? This will close it for all other players too.", - "cancelConfirmTitle": "Cancel Group Roll", - "initializationTitle": "Character Selection", - "finishGroupRoll": "Finish Group Roll", + "title": "Group Roll", + "aidingCharacters": "Aiding Characters", "leader": "Leader", "leaderRoll": "Leader Roll", - "members": "Members", "openDialogForAll": "Open Dialog For All", - "removeRoll": "Remove Roll", - "resultsHint": "Results will appear when characters roll", - "selectLeaderHint": "Select one Character to be the leader", - "selectParticipantsHint": "Select one Character to be the leader", "startGroupRoll": "Start Group Roll", - "title": "Group Roll" + "finishGroupRoll": "Finish Group Roll", + "cancelConfirmTitle": "Cancel Group Roll", + "cancelConfirmText": "Are you sure you want to cancel the Group Roll? This will close it for all other players too." }, "TokenConfig": { "actorSizeUsed": "Actor size is set, determining the dimensions" diff --git a/module/applications/dialogs/groupRollDialog.mjs b/module/applications/dialogs/groupRollDialog.mjs index df03a061..a47dd0a8 100644 --- a/module/applications/dialogs/groupRollDialog.mjs +++ b/module/applications/dialogs/groupRollDialog.mjs @@ -37,17 +37,17 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat tag: 'form', id: 'GroupRollDialog', classes: ['daggerheart', 'views', 'dh-style', 'dialog', 'group-roll-dialog'], - position: { width: 390, height: 'auto' }, - window: { - icon: 'fa-solid fa-users' - }, + position: { width: 550, height: 'auto' }, actions: { toggleSelectMember: this.#toggleSelectMember, startGroupRoll: this.#startGroupRoll, makeRoll: this.#makeRoll, removeRoll: this.#removeRoll, rerollDice: this.#rerollDice, - markSuccessful: this.#markSuccessful, + makeLeaderRoll: this.#makeLeaderRoll, + removeLeaderRoll: this.#removeLeaderRoll, + rerollLeaderDice: this.#rerollLeaderDice, + markSuccessfull: this.#markSuccessfull, cancelRoll: this.#onCancelRoll, finishRoll: this.#finishRoll }, @@ -59,21 +59,17 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat id: 'initialization', template: 'systems/daggerheart/templates/dialogs/groupRollDialog/initialization.hbs' }, - main: { - id: 'main', - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/main.hbs' - }, leader: { id: 'leader', - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/member.hbs' + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/leader.hbs' }, - result: { - id: 'result', - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/result.hbs' + groupRoll: { + id: 'groupRoll', + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/groupRoll.hbs' }, footer: { id: 'footer', - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/footer.hbs' + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/footer.hbs' } }; @@ -93,14 +89,40 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat } _configureRenderParts(options) { - const parts = super._configureRenderParts(options); + const { initialization, leader, groupRoll, footer } = super._configureRenderParts(options); + const augmentedParts = { initialization }; for (const memberKey of Object.keys(this.party.system.groupRoll.aidingCharacters)) { - parts[memberKey] = { + augmentedParts[memberKey] = { id: memberKey, - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/member.hbs' + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/groupRollMember.hbs' }; } - return parts; + + augmentedParts.leader = leader; + augmentedParts.groupRoll = groupRoll; + augmentedParts.footer = footer; + + return augmentedParts; + } + + /**@inheritdoc */ + async _onRender(context, options) { + await super._onRender(context, options); + + if (this.element.querySelector('.team-container')) return; + + if (this.tabGroups.application !== this.constructor.PARTS.initialization.id) { + const initializationPart = this.element.querySelector('.initialization-container'); + initializationPart.insertAdjacentHTML('afterend', '
'); + initializationPart.insertAdjacentHTML( + 'afterend', + `
${game.i18n.localize('DAGGERHEART.APPLICATIONS.GroupRollSelect.aidingCharacters')}
` + ); + + const teamContainer = this.element.querySelector('.team-container'); + for (const memberContainer of this.element.querySelectorAll('.team-member-container')) + teamContainer.appendChild(memberContainer); + } } async _prepareContext(_options) { @@ -112,7 +134,6 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat context.data = this.party.system.groupRoll; context.traitOptions = CONFIG.DH.ACTOR.abilities; context.members = {}; - context.aidKeys = Object.keys(this.party.system.groupRoll.aidingCharacters); context.allHaveRolled = Object.keys(context.data.participants).every(key => { const data = context.data.participants[key]; return Boolean(data.rollData); @@ -124,7 +145,6 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat async _preparePartContext(partId, context, options) { const partContext = await super._preparePartContext(partId, context, options); partContext.partId = partId; - partContext.leader = this.getRollCharacterData(this.party.system.groupRoll.leader); switch (partId) { case 'initialization': @@ -142,14 +162,19 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat partContext.canStartGroupRoll = selectedMembers.length > 1 && this.leader?.memberId; partContext.openForAllPlayers = this.openForAllPlayers; break; - case 'result': + case 'leader': + partContext.leader = this.getRollCharacterData(this.party.system.groupRoll.leader); + break; + case 'groupRoll': const leader = this.party.system.groupRoll.leader; partContext.hasRolled = leader?.rollData || - Object.values(this.party.system.groupRoll?.aidingCharacters ?? {}).some(x => x.successful !== null); + Object.values(this.party.system.groupRoll?.aidingCharacters ?? {}).some( + x => x.successfull !== null + ); const { modifierTotal, modifiers } = Object.values(this.party.system.groupRoll.aidingCharacters).reduce( (acc, curr) => { - const modifier = curr.successful === true ? 1 : curr.successful === false ? -1 : null; + const modifier = curr.successfull === true ? 1 : curr.successfull === false ? -1 : null; if (modifier) { acc.modifierTotal += modifier; acc.modifiers.push(modifier); @@ -175,7 +200,7 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat case 'footer': partContext.canFinishRoll = Boolean(this.party.system.groupRoll.leader?.rollData) && - Object.values(this.party.system.groupRoll.aidingCharacters).every(x => x.successful !== null); + Object.values(this.party.system.groupRoll.aidingCharacters).every(x => x.successfull !== null); break; } @@ -191,42 +216,20 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat if (!data) return {}; const actor = game.actors.get(data.id); - const isLeader = data === this.party.system.groupRoll.leader; - - const roll = data.roll; - const withTypeSuffix = !roll ? null : roll.isCritical ? 'criticalShort' : roll.withHope ? 'hope' : 'fear'; - const thing = withTypeSuffix ? _loc(`DAGGERHEART.GENERAL.${withTypeSuffix}`) : null; return { ...data, - type: isLeader ? 'leader' : 'aid', - basePath: isLeader ? 'system.groupRoll.leader' : `system.groupRoll.aidingCharacters.${data.id}`, - rollChoiceLabel: _loc(CONFIG.DH.ACTOR.abilities[data.rollChoice]?.label), roll: data.roll, - isEditable: actor?.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER), + isEditable: actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER), key: partId, readyToRoll: Boolean(data.rollChoice), - hasRolled: Boolean(data.rollData), - modifier: data.successful ? 1 : data.successful === false ? -1 : 0, - withLabelShort: thing ? _loc('DAGGERHEART.GENERAL.withThing', { thing }) : null + hasRolled: Boolean(data.rollData) }; } - #getCharacterDataById(id) { - if (!id) return null; - - const groupRoll = this.party.system.groupRoll; - if (id === 'leader' || id === groupRoll.leader?.id) { - return { data: groupRoll.leader, basePath: 'system.groupRoll.leader' }; - } else if (id in groupRoll.aidingCharacters) { - return { data: groupRoll.aidingCharacters[id], basePath: `system.groupRoll.aidingCharacters.${id}` }; - } - - return null; - } - static async updateData(event, _, formData) { const partyData = foundry.utils.expandObject(formData.object); + this.updatePartyData(partyData, this.getUpdatingParts(event.target)); } @@ -253,16 +256,16 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat } getUpdatingParts(target) { - const { initialization, leader, result, footer } = this.constructor.PARTS; + const { initialization, leader, groupRoll, footer } = this.constructor.PARTS; const isInitialization = this.tabGroups.application === initialization.id; - const updatingMember = target.closest('.member-roll-container.aid')?.dataset?.memberKey; - const updatingLeader = target.closest('.member-roll-container.leader'); + const updatingMember = target.closest('.team-member-container')?.dataset?.memberKey; + const updatingLeader = target.closest('.main-character-outer-container'); return [ ...(isInitialization ? [initialization.id] : []), ...(updatingMember ? [updatingMember] : []), ...(updatingLeader ? [leader.id] : []), - ...(!isInitialization ? [result.id, footer.id] : []) + ...(!isInitialization ? [groupRoll.id, footer.id] : []) ]; } @@ -301,9 +304,6 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat static #toggleSelectMember(_, button) { const member = this.partyMembers.find(x => x.id === button.dataset.id); member.selected = !member.selected; - if (this.leader?.memberId === member.id) { - this.leader = null; - } this.render(); } @@ -343,14 +343,11 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat } //#endregion - /** @this GroupRollDialog */ - static async #makeRoll(_event, button) { - const member = button.closest('[data-member-key]').dataset.memberKey; - const { data, basePath } = this.#getCharacterDataById(member); - const actor = game.actors.find(x => x.id === data.id); + async makeRoll(button, characterData, path) { + const actor = game.actors.find(x => x.id === characterData.id); if (!actor) return; - const result = await actor.rollTrait(data.rollChoice, { + const result = await actor.rollTrait(characterData.rollChoice, { skips: { createMessage: true, resources: true, @@ -359,40 +356,53 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat }); if (!result) return; - // todo: move logic to actor.rollTrait() or actor.diceRoll() if (!game.modules.get('dice-so-nice')?.active) foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice }); const rollData = result.messageRoll.toJSON(); delete rollData.options.messageRoll; this.updatePartyData( { - [basePath]: { rollData, successful: null } + [path]: rollData }, this.getUpdatingParts(button) ); } - /** @this GroupRollDialog */ - static async #removeRoll(_event, button) { - const member = button.closest('[data-member-key]').dataset.memberKey; - const { basePath } = this.#getCharacterDataById(member); + static async #makeRoll(_event, button) { + const { member } = button.dataset; + const character = this.party.system.groupRoll.aidingCharacters[member]; + this.makeRoll(button, character, `system.groupRoll.aidingCharacters.${member}.rollData`); + } + + static async #makeLeaderRoll(_event, button) { + const character = this.party.system.groupRoll.leader; + this.makeRoll(button, character, 'system.groupRoll.leader.rollData'); + } + + async removeRoll(button, path) { this.updatePartyData( { - [basePath]: { + [path]: { rollData: null, rollChoice: null, selected: false, - successful: null + successfull: null } }, this.getUpdatingParts(button) ); } - /** @this GroupRollDialog */ - static async #rerollDice(_, button) { + static async #removeRoll(_event, button) { + this.removeRoll(button, `system.groupRoll.aidingCharacters.${button.dataset.member}`); + } + + static async #removeLeaderRoll(_event, button) { + this.removeRoll(button, 'system.groupRoll.leader'); + } + + async rerollDice(button, data, path) { const { diceType } = button.dataset; - const { data, basePath } = this.#getCharacterDataById(button.dataset.member); const dieIndex = diceType === 'hope' ? 0 : diceType === 'fear' ? 1 : 2; const newRoll = game.system.api.dice.DualityRoll.fromData(data.rollData); @@ -406,19 +416,31 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat const rollData = newRoll.toJSON(); this.updatePartyData( { - [`${basePath}.rollData`]: rollData + [path]: rollData }, this.getUpdatingParts(button) ); } - static #markSuccessful(_event, button) { - const memberKey = button.closest('[data-member-key]').dataset.memberKey; - const previousValue = this.party.system.groupRoll.aidingCharacters[memberKey].successful; - const newValue = Boolean(button.dataset.success === 'true'); + static async #rerollDice(_, button) { + const { member } = button.dataset; + this.rerollDice( + button, + this.party.system.groupRoll.aidingCharacters[member], + `system.groupRoll.aidingCharacters.${member}.rollData` + ); + } + + static async #rerollLeaderDice(_, button) { + this.rerollDice(button, this.party.system.groupRoll.leader, `system.groupRoll.leader.rollData`); + } + + static #markSuccessfull(_event, button) { + const previousValue = this.party.system.groupRoll.aidingCharacters[button.dataset.member].successfull; + const newValue = Boolean(button.dataset.successfull === 'true'); this.updatePartyData( { - [`system.groupRoll.aidingCharacters.${memberKey}.successful`]: + [`system.groupRoll.aidingCharacters.${button.dataset.member}.successfull`]: previousValue === newValue ? null : newValue }, this.getUpdatingParts(button) @@ -462,7 +484,7 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat static async #finishRoll() { const totalRoll = this.party.system.groupRoll.leader.roll; for (const character of Object.values(this.party.system.groupRoll.aidingCharacters)) { - totalRoll.terms.push(new foundry.dice.terms.OperatorTerm({ operator: character.successful ? '+' : '-' })); + totalRoll.terms.push(new foundry.dice.terms.OperatorTerm({ operator: character.successfull ? '+' : '-' })); totalRoll.terms.push(new foundry.dice.terms.NumericTerm({ number: 1 })); } diff --git a/module/applications/sheets-configs/setting-feature-config.mjs b/module/applications/sheets-configs/setting-feature-config.mjs index a5bcc4f9..f90bb52f 100644 --- a/module/applications/sheets-configs/setting-feature-config.mjs +++ b/module/applications/sheets-configs/setting-feature-config.mjs @@ -188,9 +188,8 @@ export default class SettingFeatureConfig extends HandlebarsApplicationMixin(App if (type === 'effect') { const move = foundry.utils.getProperty(this.settings, this.movePath); for (const action of move.actions) { - const actionEffects = action.effects ?? []; - const remainingEffects = actionEffects.filter(x => x._id !== id); - if (actionEffects.length !== remainingEffects.length) { + const remainingEffects = action.effects.filter(x => x._id !== id); + if (action.effects.length !== remainingEffects.length) { await action.update({ effects: remainingEffects.map(x => { const { _id, ...rest } = x; diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 513ad3f3..c59dd64e 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -3,7 +3,7 @@ import DhDeathMove from '../../dialogs/deathMove.mjs'; import { CharacterLevelup, LevelupViewMode } from '../../levelup/_module.mjs'; import DhCharacterCreation from '../../characterCreation/characterCreation.mjs'; import FilterMenu from '../../ux/filter-menu.mjs'; -import { getArmorSources, getDocFromElement, getDocFromElementSync, sortBy } from '../../../helpers/utils.mjs'; +import { getArmorSources, getDocFromElement, getDocFromElementSync } from '../../../helpers/utils.mjs'; /**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ @@ -226,11 +226,6 @@ export default class CharacterSheet extends DHBaseActorSheet { context.resources.stress.emptyPips = context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0; - context.equippedItems = sortBy( - this.document.items.filter(i => i.system.equipped), - i => (i.type === 'weapon' ? (i.system.secondary ? 1 : 0) : 2) - ); - context.beastformActive = this.document.effects.find(x => x.type === 'beastform'); return context; diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index e941931a..5faa5d5c 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -725,7 +725,7 @@ export default function DHApplicationMixin(Base) { : null : this.document; - let systemData = null; + let systemData = {}; if (featureOnCharacter) { systemData = { originItemType: this.document.type, @@ -738,11 +738,10 @@ export default function DHApplicationMixin(Base) { const data = { name: cls.defaultName({ type, parent }), - type + type, + system: systemData }; - if (systemData) data.system = systemData; - if (inVault) data['system.inVault'] = true; if (disabled) data.disabled = true; if (type === 'domainCard' && parent?.system.domains?.length) { diff --git a/module/config/itemBrowserConfig.mjs b/module/config/itemBrowserConfig.mjs index 04b387cb..5c0a219b 100644 --- a/module/config/itemBrowserConfig.mjs +++ b/module/config/itemBrowserConfig.mjs @@ -177,8 +177,8 @@ export const typeConfig = { key: 'system.secondary', label: 'DAGGERHEART.UI.ItemBrowser.subtype', choices: [ - { value: false, label: 'DAGGERHEART.ITEMS.Weapon.primaryWeapon.full' }, - { value: true, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.full' } + { value: false, label: 'DAGGERHEART.ITEMS.Weapon.primaryWeapon' }, + { value: true, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon' } ] }, { diff --git a/module/config/itemConfig.mjs b/module/config/itemConfig.mjs index 43054ec5..a3e785c3 100644 --- a/module/config/itemConfig.mjs +++ b/module/config/itemConfig.mjs @@ -453,7 +453,7 @@ export const allArmorFeatures = () => { const feature = homebrewFeatures[key]; const actions = feature.actions.map(action => ({ ...action, - effects: action.effects?.map(effect => feature.effects.find(x => x.id === effect._id)) ?? [], + effects: action.effects.map(effect => feature.effects.find(x => x.id === effect._id)), type: action.type })); const actionEffects = actions.flatMap(a => a.effects); @@ -1407,7 +1407,7 @@ export const allWeaponFeatures = () => { const actions = feature.actions.map(action => ({ ...action, - effects: action.effects?.map(effect => feature.effects.find(x => x.id === effect._id)) ?? [], + effects: action.effects.map(effect => feature.effects.find(x => x.id === effect._id)), type: action.type })); const actionEffects = actions.flatMap(a => a.effects); diff --git a/module/config/resourceConfig.mjs b/module/config/resourceConfig.mjs index d33d7ab3..56ef6cd5 100644 --- a/module/config/resourceConfig.mjs +++ b/module/config/resourceConfig.mjs @@ -57,9 +57,15 @@ const companionBaseResources = Object.freeze({ stress: { id: 'stress', initial: 0, - max: 3, + max: 0, reverse: true, label: 'DAGGERHEART.GENERAL.stress' + }, + hope: { + id: 'hope', + initial: 0, + reverse: false, + label: 'DAGGERHEART.GENERAL.hope' } }); diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs index d69e17ad..d30e090a 100644 --- a/module/data/actor/adversary.mjs +++ b/module/data/actor/adversary.mjs @@ -189,9 +189,6 @@ export default class DhpAdversary extends DhCreature { prepareDerivedData() { super.prepareDerivedData(); this.attack.roll.isStandardAttack = true; - - // Clamp resources (must be done last to ensure all updates occur) - this.resources.clamp(); } _getTags() { diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index 9efbe7d7..13ff0a38 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -1,6 +1,6 @@ import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs'; import DHItem from '../../documents/item.mjs'; -import { createShallowProxy, getScrollTextData } from '../../helpers/utils.mjs'; +import { getScrollTextData } from '../../helpers/utils.mjs'; const fields = foundry.data.fields; @@ -180,7 +180,8 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel { * @returns {object} */ getRollData() { - return createShallowProxy(this); + const data = { ...this }; + return data; } /** diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index d42f2f64..1bb3560f 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -391,9 +391,8 @@ export default class DhCharacter extends DhCreature { return this.domains.map(key => { const domain = allDomainData[key]; return { - id: key, ...domain, - label: game.i18n.localize(domain?.label) ?? key + label: game.i18n.localize(domain.label) }; }); } @@ -411,11 +410,14 @@ export default class DhCharacter extends DhCreature { } get loadoutSlot() { - const loadoutCount = this.domainCards.loadout?.length ?? 0; - const worldSetting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxLoadout; + const loadoutCount = this.domainCards.loadout?.length ?? 0, + worldSetting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxLoadout, + max = !worldSetting ? null : worldSetting + this.bonuses.maxLoadout; + return { current: loadoutCount, - available: loadoutCount < worldSetting + available: !max ? true : Math.max(max - loadoutCount, 0), + max }; } @@ -778,8 +780,6 @@ export default class DhCharacter extends DhCreature { prepareDerivedData() { super.prepareDerivedData(); - - this.resources.hope.max -= this.scars; if (this.companion) { for (let levelKey in this.companion.system.levelData.levelups) { const level = this.companion.system.levelData.levelups[levelKey]; @@ -793,6 +793,7 @@ export default class DhCharacter extends DhCreature { } } + this.resources.hope.max -= this.scars; this.attack.roll.trait = this.rules.attack.roll.trait ?? this.attack.roll.trait; this.resources.armor = { @@ -802,9 +803,6 @@ export default class DhCharacter extends DhCreature { }; this.attack.damage.parts.hitPoints.value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`; - - // Clamp resources (must be done last to ensure all updates occur) - this.resources.clamp(); } getRollData() { diff --git a/module/data/actor/companion.mjs b/module/data/actor/companion.mjs index 300bd698..538031fb 100644 --- a/module/data/actor/companion.mjs +++ b/module/data/actor/companion.mjs @@ -144,6 +144,9 @@ export default class DhCompanion extends DhCreature { const level = this.levelData.levelups[levelKey]; for (let selection of level.selections) { switch (selection.type) { + case 'hope': + this.resources.hope += selection.value; + break; case 'vicious': if (selection.data[0] === 'damage') { this.attack.damage.parts.hitPoints.value.dice = adjustDice( @@ -180,9 +183,6 @@ export default class DhCompanion extends DhCreature { return acc; }, this.partner.system.companionData.levelupChoices); } - - // Clamp resources (must be done last to ensure all updates occur) - this.resources.clamp(); } async _preUpdate(changes, options, userId) { diff --git a/module/data/actor/creature.mjs b/module/data/actor/creature.mjs index 601068ad..88646301 100644 --- a/module/data/actor/creature.mjs +++ b/module/data/actor/creature.mjs @@ -60,4 +60,14 @@ export default class DhCreature extends BaseDataActor { } } } + + prepareDerivedData() { + const minLimitResource = resource => { + if (resource) resource.value = Math.min(resource.value, resource.max); + }; + + minLimitResource(this.resources.stress); + minLimitResource(this.resources.hitPoints); + minLimitResource(this.resources.hope); + } } diff --git a/module/data/actor/party.mjs b/module/data/actor/party.mjs index 5b9cccab..93596cda 100644 --- a/module/data/actor/party.mjs +++ b/module/data/actor/party.mjs @@ -18,7 +18,7 @@ export default class DhParty extends BaseDataActor { const fields = foundry.data.fields; return { ...super.defineSchema(), - partyMembers: new ForeignDocumentUUIDArrayField({ type: 'Actor' }), + partyMembers: new ForeignDocumentUUIDArrayField({ type: 'Actor' }, { prune: true }), notes: new fields.HTMLField(), gold: new GoldField(), tagTeam: new fields.EmbeddedDataField(TagTeamData), diff --git a/module/data/fields/actorField.mjs b/module/data/fields/actorField.mjs index a5f6f379..d6b58675 100644 --- a/module/data/fields/actorField.mjs +++ b/module/data/fields/actorField.mjs @@ -80,18 +80,6 @@ class ResourcesField extends fields.TypedObjectField { value.isReversed = resources[key].reverse; value.max = typeof resource.max === 'number' ? (value.max ?? resource.max) : null; } - Object.defineProperty(data, 'clamp', { - value: function () { - for (const key of Object.keys(this)) { - const resource = this[key]; - if (typeof resource?.max === 'number') { - resource.value = Math.clamp(resource.value, 0, resource.max); - } - } - }, - enumerable: false - }); - return data; } diff --git a/module/data/fields/foreignDocumentUUIDArrayField.mjs b/module/data/fields/foreignDocumentUUIDArrayField.mjs index f8969d33..456c0593 100644 --- a/module/data/fields/foreignDocumentUUIDArrayField.mjs +++ b/module/data/fields/foreignDocumentUUIDArrayField.mjs @@ -10,7 +10,6 @@ export default class ForeignDocumentUUIDArrayField extends foundry.data.fields.A */ constructor(fieldOption = {}, options = {}, context = {}) { super(new ForeignDocumentUUIDField(fieldOption), options, context); - this.options.prune ??= true; } /** @inheritdoc */ diff --git a/module/data/groupRollData.mjs b/module/data/groupRollData.mjs index 10123152..78a06b13 100644 --- a/module/data/groupRollData.mjs +++ b/module/data/groupRollData.mjs @@ -30,7 +30,7 @@ export class CharacterData extends foundry.abstract.DataModel { }), rollData: new fields.JSONField({ nullable: true, initial: null }), selected: new fields.BooleanField({ initial: false }), - successful: new fields.BooleanField({ nullable: true, initial: null }) + successfull: new fields.BooleanField({ nullable: true, initial: null }) }; } diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs index aebf33bf..f6c794f1 100644 --- a/module/data/item/base.mjs +++ b/module/data/item/base.mjs @@ -7,12 +7,7 @@ * @property {boolean} isInventoryItem- Indicates whether items of this type is a Inventory Item */ -import { - addLinkedItemsDiff, - getScrollTextData, - createShallowProxy, - updateLinkedItemApps -} from '../../helpers/utils.mjs'; +import { addLinkedItemsDiff, getScrollTextData, updateLinkedItemApps } from '../../helpers/utils.mjs'; import { ActionsField } from '../fields/actionField.mjs'; import FormulaField from '../fields/formulaField.mjs'; @@ -164,8 +159,8 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { * @returns {object} */ getRollData(options = {}) { - const data = this.actor?.getRollData() ?? {}; - data.item = createShallowProxy(this); + const actorRollData = this.actor?.getRollData() ?? {}; + const data = { ...actorRollData, item: { ...this } }; return data; } diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index 84e4de7f..75e6dc8e 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -28,10 +28,7 @@ export default class DHWeapon extends AttachableItem { equipped: new fields.BooleanField({ initial: false }), //SETTINGS - secondary: new fields.BooleanField({ - initial: false, - label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.full' - }), + secondary: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon' }), burden: new fields.StringField({ required: true, choices: CONFIG.DH.GENERAL.burden, diff --git a/module/data/scene/scene.mjs b/module/data/scene/scene.mjs index 50416573..f2a24308 100644 --- a/module/data/scene/scene.mjs +++ b/module/data/scene/scene.mjs @@ -19,7 +19,7 @@ export default class DHScene extends foundry.abstract.DataModel { close: new fields.NumberField({ integer: true, label: 'DAGGERHEART.CONFIG.Range.close.name' }), far: new fields.NumberField({ integer: true, label: 'DAGGERHEART.CONFIG.Range.far.name' }) }), - sceneEnvironments: new ForeignDocumentUUIDArrayField({ type: 'Actor' }) + sceneEnvironments: new ForeignDocumentUUIDArrayField({ type: 'Actor', prune: true }) }; } } diff --git a/module/data/settings/Homebrew.mjs b/module/data/settings/Homebrew.mjs index b5e02675..d4b7b03f 100644 --- a/module/data/settings/Homebrew.mjs +++ b/module/data/settings/Homebrew.mjs @@ -54,7 +54,7 @@ export default class DhHomebrew extends foundry.abstract.DataModel { maxDomains: new fields.NumberField({ required: true, integer: true, - min: 0, + min: 1, initial: 2, label: 'DAGGERHEART.SETTINGS.Homebrew.FIELDS.maxDomains.label' }), @@ -196,12 +196,6 @@ export default class DhHomebrew extends foundry.abstract.DataModel { return source; } - _initialize(options) { - super._initialize(options); - this.maxDomains ||= Infinity; - this.maxLoadout ||= Infinity; - } - /** Invoked by the setting when data changes */ handleChange() { if (this.maxFear) { diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index 08463818..227e2613 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -169,36 +169,27 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { super._applyChangeUnguided(actor, change, changes, options); } - /** Recursively finds the first parent document of the given object */ - static #resolveParentDocument(model, documentClass) { - return model instanceof documentClass - ? model - : model.parent - ? this.#resolveParentDocument(model.parent, documentClass) - : null; - } - static getChangeValue(model, change, effect) { - let value = change.value.toString(); - const useOrigin = value.toLowerCase().includes('origin.@') && effect.origin; - let origin = null; - if (effect.origin) { - if (useOrigin) value = value.replaceAll(/origin\.@/gi, '@'); - const originEffect = foundry.utils.fromUuidSync(effect.origin); - origin = this.#resolveParentDocument(originEffect, Item); + let key = change.value.toString(); + const isOriginTarget = key.toLowerCase().includes('origin.@'); + let parseModel = model; + if (isOriginTarget && effect.origin) { + key = change.key.replaceAll(/origin\.@/gi, '@'); + try { + const originEffect = foundry.utils.fromUuidSync(effect.origin); + const doc = + originEffect.parent?.parent instanceof game.system.api.documents.DhpActor + ? originEffect.parent + : originEffect.parent.parent; + if (doc) parseModel = doc; + } catch (_) {} } - // Get the actor and item documents. Note that actor roll data is inclusive of system roll data - const actor = this.#resolveParentDocument(model, Actor); - const item = - (useOrigin ? origin : null) ?? - this.#resolveParentDocument(effect.parent, Item) ?? - (origin?.actor === actor ? origin : null); const stackingParsedValue = effect.system.stacking - ? Roll.replaceFormulaData(value, { stacks: effect.system.stacking.value }) - : value; - const evalValue = this.effectSafeEval(itemAbleRollParse(stackingParsedValue, actor, item)); - return evalValue ?? value; + ? Roll.replaceFormulaData(key, { stacks: effect.system.stacking.value }) + : key; + const evalValue = itemAbleRollParse(stackingParsedValue, parseModel, effect.parent); + return evalValue ?? key; } /** diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index eb57a186..db249033 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -1,7 +1,7 @@ import { emitAsGM, GMUpdateEvent } from '../systemRegistration/socket.mjs'; import { LevelOptionType } from '../data/levelTier.mjs'; import DHFeature from '../data/item/feature.mjs'; -import { createScrollText, damageKeyToNumber, getDamageKey, createShallowProxy } from '../helpers/utils.mjs'; +import { createScrollText, damageKeyToNumber, getDamageKey } from '../helpers/utils.mjs'; import DhCompanionLevelUp from '../applications/levelup/companionLevelup.mjs'; import { ResourceUpdateMap } from '../data/action/baseAction.mjs'; import { abilities } from '../config/actorConfig.mjs'; @@ -99,7 +99,7 @@ export default class DhpActor extends Actor { } // Configure prototype token settings - if (['character', 'companion', 'party'].includes(this.type)) { + if (['character', 'companion', 'party'].includes(this.type)) Object.assign(update, { prototypeToken: { sight: { enabled: true }, @@ -107,8 +107,6 @@ export default class DhpActor extends Actor { disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY } }); - } - this.updateSource(update); } @@ -595,7 +593,10 @@ export default class DhpActor extends Actor { /**@inheritdoc */ getRollData() { - const rollData = createShallowProxy(super.getRollData()); + const rollData = foundry.utils.deepClone(super.getRollData()); + /* system gets repeated infinately which causes issues when trying to use the data for document creation */ + delete rollData.system; + rollData.id = this.id; rollData.name = this.name; rollData.system = this.system.getRollData(); diff --git a/module/documents/item.mjs b/module/documents/item.mjs index 93aa3b28..8ece56fa 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -54,7 +54,13 @@ export default class DHItem extends foundry.documents.Item { * @returns */ getRollData(options = {}) { - let data = this.system.getRollData(options); + let data; + if (this.system.getRollData) data = this.system.getRollData(options); + else { + const actorRollData = this.actor?.getRollData(options) ?? {}; + data = { ...actorRollData, item: { ...this.system } }; + } + if (data?.item) { data.item.flags = { ...this.flags }; data.item.name = this.name; diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index 1650b505..4527da1a 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -189,14 +189,17 @@ export const getDeleteKeys = (property, innerProperty, innerPropertyDefaultValue // Fix on Foundry native formula replacement for DH const nativeReplaceFormulaData = Roll.replaceFormulaData; -Roll.replaceFormulaData = function (formula, data = {}, { missing, warn = false } = {}) { +Roll.replaceFormulaData = function (formula, baseData = {}, { missing, warn = false } = {}) { /* Inserting global data */ - const defaultingTypes = [ - ...Object.keys(CONFIG.DH.GENERAL.multiplierTypes).map(x => ({ term: x, default: 1 })), - { term: 'partySize', default: game.actors?.party?.system.partyMembers.length ?? 0 } - ]; + const data = { + ...baseData, + partySize: game.actors?.party?.system.partyMembers.length ?? 0 + }; - formula = defaultingTypes.reduce((a, c) => a.replaceAll(`@${c.term}`, data[c.term] ?? c.default), formula); + const terms = Object.keys(CONFIG.DH.GENERAL.multiplierTypes).map(type => { + return { term: type, default: 1 }; + }); + formula = terms.reduce((a, c) => a.replaceAll(`@${c.term}`, data[c.term] ?? c.default), formula); return nativeReplaceFormulaData(formula, data, { missing, warn }); }; @@ -372,11 +375,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 instanceof Item ? item : actor; - const rollData = isItemTarget || !model?.getRollData ? model : model.getRollData(); + const model = isItemTarget ? item : actor; try { - return Roll.replaceFormulaData(slicedValue, rollData); + return Roll.replaceFormulaData(slicedValue, isItemTarget || !model?.getRollData ? model : model.getRollData()); } catch (_) { return ''; } @@ -810,31 +812,3 @@ export function sortBy(arr, fn) { }; return arr.sort(cmp); } - -/** - * Creates a proxy that allows retrieval of top data but diverts updates to a different object. - * Generally used for roll data - */ -export function createShallowProxy(obj) { - if (obj._isShallowProxy) return obj; - - const overrides = {}; - return new Proxy(obj, { - get(target, prop, receiver) { - if (prop === '_isShallowProxy') return true; - if (prop in overrides) return overrides[prop]; - return Reflect.get(target, prop, receiver); - }, - set(_target, prop, newValue) { - overrides[prop] = newValue; - return true; - }, - deleteProperty(_target, prop) { - delete overrides[prop]; - return true; - }, - has(target, key) { - return key in overrides || key in target; - } - }); -} diff --git a/package-lock.json b/package-lock.json index 47c5dede..b8fef1cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,8 +19,8 @@ "eslint": "^10.2.1", "eslint-plugin-prettier": "^5.5.5", "globals": "^17.5.0", - "husky": "^9.1.7", - "lint-staged": "^16.4.0", + "husky": "^9.1.5", + "lint-staged": "^15.2.10", "postcss": "^8.4.32", "prettier": "^3.5.3", "rollup-plugin-postcss": "^4.0.2" @@ -752,11 +752,10 @@ } }, "node_modules/ansi-escapes": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", - "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, - "license": "MIT", "dependencies": { "environment": "^1.0.0" }, @@ -768,11 +767,10 @@ } }, "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -781,11 +779,10 @@ } }, "node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -1210,7 +1207,6 @@ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, - "license": "MIT", "dependencies": { "restore-cursor": "^5.0.0" }, @@ -1222,34 +1218,39 @@ } }, "node_modules/cli-truncate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", - "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, - "license": "MIT", "dependencies": { - "slice-ansi": "^8.0.0", - "string-width": "^8.2.0" + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" }, "engines": { - "node": ">=20" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, "node_modules/cli-truncate/node_modules/string-width": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz", - "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, - "license": "MIT", "dependencies": { - "get-east-asian-width": "^1.5.0", - "strip-ansi": "^7.1.2" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=20" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1356,17 +1357,15 @@ "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/commander": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", - "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", "dev": true, - "license": "MIT", "engines": { - "node": ">=20" + "node": ">=18" } }, "node_modules/commondir": { @@ -1855,7 +1854,6 @@ "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -2177,11 +2175,33 @@ } }, "node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, - "license": "MIT" + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } }, "node_modules/expand-tilde": { "version": "2.0.2", @@ -2451,11 +2471,10 @@ } }, "node_modules/get-east-asian-width": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", - "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -2500,6 +2519,18 @@ "node": ">= 0.4" } }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -2900,12 +2931,20 @@ "node": ">=0.10.0" } }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, "node_modules/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, - "license": "MIT", "bin": { "husky": "bin.js" }, @@ -3174,16 +3213,12 @@ } }, "node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.1" - }, "engines": { - "node": ">=18" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3286,6 +3321,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-typed-array": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", @@ -3498,38 +3545,52 @@ "node": ">=10.13.0" } }, - "node_modules/lint-staged": { - "version": "16.4.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.4.0.tgz", - "integrity": "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==", + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lint-staged": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", + "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", "dev": true, - "license": "MIT", "dependencies": { - "commander": "^14.0.3", - "listr2": "^9.0.5", - "picomatch": "^4.0.3", + "chalk": "^5.4.1", + "commander": "^13.1.0", + "debug": "^4.4.0", + "execa": "^8.0.1", + "lilconfig": "^3.1.3", + "listr2": "^8.2.5", + "micromatch": "^4.0.8", + "pidtree": "^0.6.0", "string-argv": "^0.3.2", - "tinyexec": "^1.0.4", - "yaml": "^2.8.2" + "yaml": "^2.7.0" }, "bin": { "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=20.17" + "node": ">=18.12.0" }, "funding": { "url": "https://opencollective.com/lint-staged" } }, "node_modules/listr2": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", - "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", "dev": true, - "license": "MIT", "dependencies": { - "cli-truncate": "^5.0.0", + "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", @@ -3537,7 +3598,7 @@ "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=20.0.0" + "node": ">=18.0.0" } }, "node_modules/loader-utils": { @@ -3603,7 +3664,6 @@ "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, - "license": "MIT", "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", @@ -3618,12 +3678,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" @@ -3692,6 +3766,12 @@ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", "dev": true }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -3727,12 +3807,23 @@ "node": ">=4" } }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-function": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -3894,6 +3985,33 @@ "node": ">= 10.13.0" } }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -3948,16 +4066,15 @@ } }, "node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, - "license": "MIT", "dependencies": { - "mimic-function": "^5.0.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4142,11 +4259,10 @@ "dev": true }, "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -4154,6 +4270,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -5041,7 +5169,6 @@ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, - "license": "MIT", "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" @@ -5053,6 +5180,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -5066,8 +5208,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/rollup": { "version": "4.44.0", @@ -5347,7 +5488,6 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "ISC", "engines": { "node": ">=14" }, @@ -5356,17 +5496,16 @@ } }, "node_modules/slice-ansi": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", - "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.3", - "is-fullwidth-code-point": "^5.1.0" + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" }, "engines": { - "node": ">=20" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" @@ -5500,13 +5639,12 @@ } }, "node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-regex": "^6.2.2" + "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" @@ -5515,6 +5653,18 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/style-inject": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", @@ -5650,16 +5800,6 @@ "readable-stream": "3" } }, - "node_modules/tinyexec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", - "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5942,11 +6082,10 @@ } }, "node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -5960,18 +6099,16 @@ } }, "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true }, "node_modules/wrap-ansi/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -5998,19 +6135,15 @@ } }, "node_modules/yaml": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", "dev": true, - "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yargs": { diff --git a/package.json b/package.json index 52bb4ce7..28c83549 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,7 @@ "createSymlink": "node ./tools/create-symlink.mjs", "setup:dev": "node ./tools/dev-setup.mjs", "lint": "eslint", - "lint:fix": "eslint --fix", - "prepare": "husky" + "lint:fix": "eslint --fix" }, "devDependencies": { "@foundryvtt/foundryvtt-cli": "^1.0.2", @@ -30,13 +29,13 @@ "eslint": "^10.2.1", "eslint-plugin-prettier": "^5.5.5", "globals": "^17.5.0", - "husky": "^9.1.7", - "lint-staged": "^16.4.0", + "husky": "^9.1.5", + "lint-staged": "^15.2.10", "postcss": "^8.4.32", "prettier": "^3.5.3", "rollup-plugin-postcss": "^4.0.2" }, "lint-staged": { - "**/*": "eslint --fix" + "**/*": "prettier --write --ignore-unknown" } } diff --git a/styles/less/dialog/group-roll-dialog/_common.less b/styles/less/dialog/group-roll-dialog/_common.less deleted file mode 100644 index 41573718..00000000 --- a/styles/less/dialog/group-roll-dialog/_common.less +++ /dev/null @@ -1,46 +0,0 @@ -h1 { - color: light-dark(@dark-blue, @golden); - font-family: var(--dh-font-subtitle); - font-size: var(--font-size-24); - text-align: center; - font-weight: 700; -} - -header { - --bar-color: light-dark(@dark-blue, @golden); - color: light-dark(@dark, @beige); - display: flex; - justify-content: center; - align-items: center; - - &:not(:first-child) { - margin-top: var(--spacer-8); - } - - span { - padding: 0 10px; - } - - &:before { - content: ' '; - flex: 1; - height: 1px; - background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, var(--bar-color) 100%); - } - - &:after { - content: ' '; - flex: 1; - height: 1px; - background: linear-gradient(90deg, var(--bar-color) 0%, rgba(0, 0, 0, 0) 100%); - } -} - -img.portrait { - border-radius: 50%; - border: none; - object-fit: cover; - object-position: center top; - width: 2.5rem; - height: 2.5rem; -} diff --git a/styles/less/dialog/group-roll-dialog/index.less b/styles/less/dialog/group-roll-dialog/index.less deleted file mode 100644 index 27925fa2..00000000 --- a/styles/less/dialog/group-roll-dialog/index.less +++ /dev/null @@ -1,8 +0,0 @@ -.daggerheart.dialog.dh-style.views.group-roll-dialog { - .window-content { - @import "./_common.less"; - } -} - -@import "./initialization.less"; -@import "./main.less"; diff --git a/styles/less/dialog/group-roll-dialog/initialization.less b/styles/less/dialog/group-roll-dialog/initialization.less index b32f4756..b2e7e021 100644 --- a/styles/less/dialog/group-roll-dialog/initialization.less +++ b/styles/less/dialog/group-roll-dialog/initialization.less @@ -1,59 +1,62 @@ +.theme-light .daggerheart.dialog.dh-style.views.group-roll-dialog { + .initialization-container .members-container .member-container { + .member-name { + background-image: url('../assets/parchments/dh-parchment-light.png'); + } + } +} + .daggerheart.dialog.dh-style.views.group-roll-dialog { - .initialization-container.active { - display: flex; - flex-direction: column; - overflow: hidden; + .initialization-container { + h2 { + text-align: center; + } + + .members-container { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + gap: 8px; + + .member-container { + position: relative; + display: flex; + justify-content: center; + + &.inactive { + opacity: 0.4; + } + + .member-name { + position: absolute; + padding: 0 2px; + border: 1px solid; + border-radius: 6px; + margin-top: 4px; + color: light-dark(@dark, @beige); + background-image: url('../assets/parchments/dh-parchment-dark.png'); + text-align: center; + } + + img { + border-radius: 6px; + border: 1px solid light-dark(@dark-blue, @golden); + } + } + } .main-roll { - display: flex; - flex-direction: column; - text-align: center; - padding-bottom: 4px; + margin-top: 8px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; &.inactive { opacity: 0.4; } } - .hint { - color: var(--color-form-hint); - line-height: 1; - padding: var(--spacer-8) 0; - font-family: var(--dh-font-body); - font-size: var(--font-size-12); - font-weight: 300; - } - - .members-container { - display: flex; - flex-direction: column; - gap: 8px; - overflow-y: auto; - - .member-container { - display: flex; - position: relative; - justify-content: center; - height: unset; - padding: 4px 8px; - gap: var(--spacer-8); - flex: 0 0 auto; - - &:not(.inactive) { - background: @golden-bg; - } - - .name { - flex: 1; - color: light-dark(@dark, @beige); - font-weight: 500; - text-align: left; - } - } - } - footer { - margin-top: 12px; + margin-top: 8px; display: flex; gap: 8px; diff --git a/styles/less/dialog/group-roll-dialog/leader.less b/styles/less/dialog/group-roll-dialog/leader.less new file mode 100644 index 00000000..b3fa3a3b --- /dev/null +++ b/styles/less/dialog/group-roll-dialog/leader.less @@ -0,0 +1,35 @@ +.daggerheart.dialog.dh-style.views.group-roll-dialog { + .main-character-outer-container { + &.inactive { + opacity: 0.3; + pointer-events: none; + } + + .main-character-container { + .character-info { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + height: 64px; + + img { + height: 64px; + border-radius: 6px; + border: 1px solid light-dark(@dark-blue, @golden); + } + + .character-data { + padding-left: 0.75rem; + flex: 1; + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + text-align: left; + font-size: var(--font-size-18); + } + } + } + } +} diff --git a/styles/less/dialog/group-roll-dialog/main.less b/styles/less/dialog/group-roll-dialog/main.less deleted file mode 100644 index f266dcc7..00000000 --- a/styles/less/dialog/group-roll-dialog/main.less +++ /dev/null @@ -1,273 +0,0 @@ -.daggerheart.dialog.dh-style.views.group-roll-dialog { - .group-roll.active { - display: flex; - flex-direction: column; - overflow: hidden; - - a.roll-button { - &:hover { - text-shadow: none; - filter: drop-shadow(0 0 3px @golden-90); - } - } - - .aiding-members { - display: flex; - flex-direction: column; - gap: 6px; - overflow-y: auto; - } - - .item-tags { - gap: 6px; - .tag.failure, - .tag.success { - font-weight: 600; - justify-content: center; - min-width: 3ch; - } - - .tag.success { - border-color: @green; - background: @green-10; - color: @green; - } - - .tag.failure { - border-color: @red; - background: @red-10; - color: @red; - } - - .tag { - padding-top: 0; - padding-bottom: 0; - line-height: 1.1875rem; - } - } - - .with-result { - border-radius: 5px; - background: var(--duality-bg); - color: var(--color-light-2); - - &.hope { - --duality-text-color: @golden; - --duality-bg: url(../assets/parchments/dh-parchment-hope.png); - } - - &.fear { - --duality-text-color: @chat-blue; - --duality-bg: url(../assets/parchments/dh-parchment-fear.png); - } - - &.critical { - --duality-text-color: @chat-purple; - --duality-bg: url(../assets/parchments/dh-parchment-critical.png); - } - - .duality-label { - font-family: var(--dh-font-subtitle); - color: var(--duality-text-color); - font-weight: 700; - } - } - - .member-roll-container { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - min-height: 3.375rem; - - &.inactive { - pointer-events: none; - } - - .name-area { - display: flex; - flex-direction: column; - flex: 1; - justify-content: center; - .name { - font-weight: 500; - } - .trait { - display: flex; - align-items: center; - gap: 6px; - select { - --input-height: 2em; - width: auto; - } - } - .item-tags { - align-items: stretch; - } - } - - .buttons { - display: flex; - flex-direction: row; - button { - --button-text-color: var(--color-text-primary); - --button-size: 1.5em; - padding: 0 var(--spacer-4); - img { - width: 100%; - height: 100%; - object-fit: contain; - } - } - } - - a.roll-button.initial-roll { - width: 1.875rem; - height: 1.875rem; - margin-right: 2px; /** makes hover look a bit nicer */ - } - - .with-result { - display: flex; - justify-content: end; - align-items: center; - gap: 6px; - - .roll-data { - display: flex; - flex-direction: column; - align-items: end; - justify-content: center; - padding: 0 4px; - min-height: 3rem; - - .duality-label { - font-size: var(--font-size-15); - - .unused-damage { - text-decoration: line-through; - } - - .with { - font-size: var(--font-size-10); - } - } - - .roll-dice-container { - display: flex; - align-items: center; - justify-content: center; - flex-wrap: wrap; - gap: 2px; - - .roll-dice { - position: relative; - display: flex; - align-items: center; - justify-content: center; - - .dice-label { - position: absolute; - color: white; - font-size: 1rem; - paint-order: stroke fill; - -webkit-text-stroke: 2px black; - } - - img { - height: 1.3125rem; - } - } - - .roll-operator { - font-size: var(--font-size-18); - padding: 0 1px; - } - - .roll-value { - font-size: var(--font-size-16); - padding: 0 1px; - } - } - } - - .buttons { - flex-direction: column; - button { - color: var(--medium-red); - &[data-success=true] { - color: var(--green); - } - &.active { - text-shadow: 0 0 1px light-dark(@dark-80, @beige-80); - } - &.inactive { - opacity: 0.35; - } - } - } - } - } - } - - .group-roll-results { - display: flex; - flex-direction: column; - align-items: stretch; - gap: 4px; - font-size: var(--font-size-12); - padding: 6px 12px; - margin-top: 8px; - - &.empty { - color: light-dark(@dark-blue-90, @beige-80); - border-radius: 3px; - justify-content: center; - border: 1px dashed light-dark(@dark-blue-90, @beige-80); - text-align: center; - height: 3.25rem; - font-family: @font-body; - } - - .row { - display: flex; - align-items: center; - justify-content: space-between; - } - - .divider { - height: 1px; - background-image: linear-gradient(90deg, transparent 0%, var(--duality-text-color) 50%, transparent 100%); - margin-block: var(--spacer-4); - } - - .modifiers .item-tags { - min-height: calc(2px + 1.1875rem); - } - - .total { - .label { - font-size: var(--font-size-14); - } - .duality-label { - display: flex; - align-items: center; - gap: var(--spacer-4); - .value { - font-size: 20px; - } - } - } - } - - .finish-container { - margin-top: 16px; - gap: 16px; - display: grid; - grid-template-columns: 1fr 1fr 1fr; - - .finish-button { - grid-column: span 2; - } - } -} diff --git a/styles/less/dialog/group-roll-dialog/sheet.less b/styles/less/dialog/group-roll-dialog/sheet.less new file mode 100644 index 00000000..70afc1fe --- /dev/null +++ b/styles/less/dialog/group-roll-dialog/sheet.less @@ -0,0 +1,265 @@ +.daggerheart.dialog.dh-style.views.group-roll-dialog { + .team-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + margin-bottom: 16px; + + .team-member-container { + display: flex; + flex-direction: column; + justify-content: space-between; + gap: 8px; + flex: 1; + + &.inactive { + opacity: 0.3; + pointer-events: none; + } + + .data-container { + display: flex; + flex-direction: column; + gap: 8px; + width: 100%; + } + + .member-info { + display: flex; + align-items: start; + width: 100%; + + img { + height: 64px; + border-radius: 6px; + border: 1px solid light-dark(@dark-blue, @golden); + } + + .member-data { + padding-left: 0.75rem; + flex: 1; + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + text-align: left; + font-size: var(--font-size-18); + } + } + } + } + + .roll-container { + display: flex; + flex-direction: column; + } + + .roll-title { + font-size: var(--font-size-20); + font-weight: bold; + color: light-dark(@dark-blue, @golden); + text-align: center; + display: flex; + align-items: center; + gap: 8px; + + &.hope, + &.fear, + &.critical { + color: var(--text-color); + } + + &.hope { + --text-color: @golden; + } + + &.fear { + --text-color: @chat-blue; + } + + &.critical { + --text-color: @chat-purple; + } + + &::before, + &::after { + color: var(--text-color); + content: ''; + flex: 1; + height: 2px; + } + + &::before { + background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, light-dark(@dark-blue, @golden) 100%); + } + + &::after { + background: linear-gradient(90deg, light-dark(@dark-blue, @golden) 0%, rgba(0, 0, 0, 0) 100%); + } + } + + .roll-tools { + display: flex; + gap: 4px; + align-items: center; + + img { + height: 16px; + } + + a { + display: flex; + font-size: 16px; + + &:hover { + text-shadow: none; + filter: drop-shadow(0 0 8px var(--golden)); + } + } + } + + .roll-data { + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + + &.hope { + --text-color: @golden; + --bg-color: @golden-40; + } + + &.fear { + --text-color: @chat-blue; + --bg-color: @chat-blue-40; + } + + &.critical { + --text-color: @chat-purple; + --bg-color: @chat-purple-40; + } + + .duality-label { + color: var(--text-color); + font-size: var(--font-size-20); + font-weight: bold; + text-align: center; + + .unused-damage { + text-decoration: line-through; + } + } + + .roll-dice-container { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + gap: 8px; + + .roll-dice { + position: relative; + display: flex; + align-items: center; + justify-content: center; + + .dice-label { + position: absolute; + color: white; + font-size: 1rem; + paint-order: stroke fill; + -webkit-text-stroke: 2px black; + } + + img { + height: 32px; + } + } + + .roll-operator { + font-size: var(--font-size-24); + } + + .roll-value { + font-size: 18px; + } + } + + .roll-total { + background: var(--bg-color); + color: var(--text-color); + border-radius: 4px; + padding: 3px; + } + } + + .roll-success-container { + display: flex; + align-items: center; + justify-content: space-around; + + .roll-success-tools { + display: flex; + align-items: center; + gap: 4px; + color: light-dark(@dark-blue, @golden); + + i { + font-size: 24px; + } + } + + .roll-success-modifier { + display: flex; + align-items: center; + justify-content: right; + gap: 2px; + font-size: var(--font-size-20); + padding: 0px 4px; + + &.success { + background: @green-10; + color: @green; + } + + &.failure { + background: @red-10; + color: @red; + } + } + } + + .section-title { + font-size: var(--font-size-18); + font-weight: bold; + } + + .group-roll-results { + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + font-size: var(--font-size-20); + + .group-roll-container { + display: flex; + align-items: center; + gap: 2px; + } + } + + .finish-container { + margin-top: 16px; + gap: 16px; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + + .finish-button { + grid-column: span 2; + } + } + + .hint { + text-align: center; + } +} diff --git a/styles/less/dialog/group-roll/group-roll.less b/styles/less/dialog/group-roll/group-roll.less new file mode 100644 index 00000000..f2895d31 --- /dev/null +++ b/styles/less/dialog/group-roll/group-roll.less @@ -0,0 +1,50 @@ +@import '../../utils/colors.less'; + +.application.daggerheart.group-roll { + fieldset.one-column { + min-width: 500px; + margin-bottom: 10px; + } + .actor-item { + display: flex; + align-items: center; + gap: 15px; + width: 100%; + + img { + height: 40px; + width: 40px; + border-radius: 50%; + object-fit: cover; + } + + .actor-info { + display: flex; + flex-direction: column; + gap: 10px; + + .actor-check-info { + display: flex; + gap: 10px; + + .form-fields { + display: flex; + gap: 5px; + align-items: center; + + input { + max-width: 40px; + text-align: center; + } + } + } + } + + .controls { + margin-left: auto; + } + } + .tooltip-container { + width: 100%; + } +} diff --git a/styles/less/dialog/index.less b/styles/less/dialog/index.less index eb882eeb..947142ff 100644 --- a/styles/less/dialog/index.less +++ b/styles/less/dialog/index.less @@ -31,10 +31,14 @@ @import './reroll-dialog/sheet.less'; +@import './group-roll/group-roll.less'; + @import './tag-team-dialog/initialization.less'; @import './tag-team-dialog/sheet.less'; -@import './group-roll-dialog/index.less'; +@import './group-roll-dialog/initialization.less'; +@import './group-roll-dialog/leader.less'; +@import './group-roll-dialog/sheet.less'; @import './image-select/sheet.less'; diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index afd56057..c5bca1da 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -100,7 +100,7 @@ scrollbar-color: light-dark(@dark-blue, @golden) transparent; } - button:where(:not(.plain)) { + button { background: light-dark(transparent, @golden); border: 1px solid light-dark(@dark-blue, @dark-blue); color: light-dark(@dark-blue, @dark-blue); diff --git a/system.json b/system.json index 9b8a8403..6751f957 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.2.1", + "version": "2.2.0", "compatibility": { "minimum": "14.359", "verified": "14.360", @@ -10,7 +10,7 @@ }, "url": "https://github.com/Foundryborne/daggerheart", "manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/v14/system.json", - "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.2.1/system.zip", + "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.2.0/system.zip", "authors": [ { "name": "WBHarry" diff --git a/templates/dialogs/group-roll/group-roll.hbs b/templates/dialogs/group-roll/group-roll.hbs new file mode 100644 index 00000000..9b23c0a5 --- /dev/null +++ b/templates/dialogs/group-roll/group-roll.hbs @@ -0,0 +1,84 @@ +
+
+

{{localize "DAGGERHEART.UI.Chat.groupRoll.title"}}

+
+ +
+ {{localize "DAGGERHEART.UI.Chat.groupRoll.leader"}} + {{#unless leader.actor}} + +
+ {{localize "DAGGERHEART.UI.Chat.groupRoll.selectLeader"}} +
+ {{else}} +
+ {{leader.actor.name}} +
+ {{leader.actor.name}} +
+
+ + +
+ {{!-- Not used yet --}} + {{!--
+ + +
--}} +
+
+
+ + + +
+
+ {{/unless}} +
+ +
+ {{localize "DAGGERHEART.UI.Chat.groupRoll.partyTeam"}} + + + + {{#if (gt this.members.length 0)}} + {{#each members as |member index|}} +
+ {{member.actor.name}} +
+ {{member.actor.name}} +
+
+ + +
+ {{!-- Not used yet --}} + {{!--
+ + +
--}} +
+
+
+ + + +
+
+ {{/each}} + {{/if}} + {{#unless allSelected}} +
+ {{localize "DAGGERHEART.UI.Chat.groupRoll.selectMember"}} +
+ {{/unless}} +
+ +
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/parts/footer.hbs b/templates/dialogs/groupRollDialog/footer.hbs similarity index 62% rename from templates/dialogs/groupRollDialog/parts/footer.hbs rename to templates/dialogs/groupRollDialog/footer.hbs index 34b4efa1..e401966b 100644 --- a/templates/dialogs/groupRollDialog/parts/footer.hbs +++ b/templates/dialogs/groupRollDialog/footer.hbs @@ -1,9 +1,6 @@
- +
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/groupRoll.hbs b/templates/dialogs/groupRollDialog/groupRoll.hbs new file mode 100644 index 00000000..edf1c980 --- /dev/null +++ b/templates/dialogs/groupRollDialog/groupRoll.hbs @@ -0,0 +1,20 @@ +
+
+ {{localize "DAGGERHEART.GENERAL.result.single"}} + +
+ {{#if hasRolled}}{{groupRoll.total}} {{groupRoll.totalLabel}}{{/if}} +
+ {{#if groupRoll.leaderTotal includeZero=true}}{{groupRoll.leaderTotal}}{{else}}{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leaderRoll"}}{{/if}} + {{#each groupRoll.modifiers as |modifier|}} + {{#if (gte modifier 0)}}+{{else}}-{{/if}} + {{positive modifier}} + {{/each}} + {{#unless groupRoll.modifiers.length}} + + + {{localize "DAGGERHEART.GENERAL.Modifier.plural"}} + {{/unless}} +
+
+
+
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/groupRollMember.hbs b/templates/dialogs/groupRollDialog/groupRollMember.hbs new file mode 100644 index 00000000..acf8e8f1 --- /dev/null +++ b/templates/dialogs/groupRollDialog/groupRollMember.hbs @@ -0,0 +1,85 @@ +{{#with (lookup members partId)}} +
+
+
+ +
+ {{name}} +
+
+
+ {{!-- --}} + +
+
+
+
+
+ {{#if readyToRoll}} +
+ + {{localize "DAGGERHEART.GENERAL.roll"}} +
+ + + + + {{#if hasRolled}} + + + + {{/if}} +
+
+ + {{#if roll}} +
+
{{roll.total}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.totalLabel}}
+
+ + {{roll.dHope.total}} + + + + + + {{roll.dFear.total}} + + + {{#if roll.advantage.type}} + {{#if (eq roll.advantage.type 1)}}+{{else}}-{{/if}} + + {{roll.advantage.value}} + + + {{/if}} + {{#if (gte roll.modifierTotal 0)}}+{{else}}-{{/if}} + {{positive roll.modifierTotal}} +
+
+ {{else}} + {{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.makeYourRoll"}} + {{/if}} +
+ {{/if}} + {{#if hasRolled}} +
+ {{#if ../isGM}} + + {{/if}} +
+ {{localize "DAGGERHEART.GENERAL.Modifier.single"}}{{#if successfull}} + 1{{else if (isNullish successfull)}} + ?{{else}} - 1{{/if}} +
+
+ {{/if}} +
+
+{{/with}} \ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/initialization.hbs b/templates/dialogs/groupRollDialog/initialization.hbs index a01a00bb..a520b8bd 100644 --- a/templates/dialogs/groupRollDialog/initialization.hbs +++ b/templates/dialogs/groupRollDialog/initialization.hbs @@ -1,43 +1,32 @@
-

{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.initializationTitle"}}

-
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leader"}}
-
-
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.selectLeaderHint"}}
- -
- -
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.members"}}
-
{{"DAGGERHEART.APPLICATIONS.GroupRollSelect.selectParticipantsHint"}}
{{#each memberSelection as |member|}} - + {{member.name}} + + {{/each}}
+
+
+ +
+ +
+
+
+
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/leader.hbs b/templates/dialogs/groupRollDialog/leader.hbs new file mode 100644 index 00000000..3d5db3f7 --- /dev/null +++ b/templates/dialogs/groupRollDialog/leader.hbs @@ -0,0 +1,73 @@ +
+ {{#with leader}} +
+
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leader"}}
+
+
+
+ +
+ {{name}} +
+
+
+ +
+
+
+
+
+
+ + {{#if readyToRoll}} +
+ + {{localize "DAGGERHEART.GENERAL.roll"}} +
+ + + + + {{#if hasRolled}} + + + + {{/if}} +
+
+ + {{#if roll}} +
+
{{roll.total}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.totalLabel}}
+
+ + {{roll.dHope.total}} + + + + + + {{roll.dFear.total}} + + + {{#if roll.advantage.type}} + {{#if (eq roll.advantage.type 1)}}+{{else}}-{{/if}} + + {{roll.advantage.value}} + + + {{/if}} + {{#if (gte roll.modifierTotal 0)}}+{{else}}-{{/if}} + {{positive roll.modifierTotal}} +
+
+ {{else}} + {{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.makeYourRoll"}} + {{/if}} +
+ {{/if}} +
+
+ {{/with}} +
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/main.hbs b/templates/dialogs/groupRollDialog/main.hbs deleted file mode 100644 index 6807a7e4..00000000 --- a/templates/dialogs/groupRollDialog/main.hbs +++ /dev/null @@ -1,15 +0,0 @@ -
-

{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.title"}}

-
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.members"}}
-
- {{#each aidKeys as |key|}} -
- {{/each}} -
- -
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leader"}}
-
-
{{localize "DAGGERHEART.GENERAL.result.single"}}
-
-
-
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/parts/member.hbs b/templates/dialogs/groupRollDialog/parts/member.hbs deleted file mode 100644 index ee857794..00000000 --- a/templates/dialogs/groupRollDialog/parts/member.hbs +++ /dev/null @@ -1,95 +0,0 @@ -{{#with (ifThen (eq partId "leader") leader (lookup members partId))}} -
- -
- {{name}} - {{#if hasRolled}} -
-
{{rollChoiceLabel}}
- {{#if modifier}} - - {{numberFormat modifier sign=true}} - - {{/if}} - {{#if isEditable}} -
- - -
- {{/if}} -
- {{else if readyToRoll}} -
- {{localize "DAGGERHEART.CONFIG.RollTypes.trait.name" }} - -
- {{/if}} -
- {{#if roll}} -
-
-
- {{roll.total}} - {{withLabelShort}} -
-
- - {{roll.dHope.total}} - - - - {{roll.dFear.total}} - - - {{#if roll.hasAdvantage}} - + - - {{roll.dAdvantage.total}} - - - {{/if}} - {{#if roll.hasDisadvantage}} - - - - {{roll.dDisadvantage.total}} - - - {{/if}} - {{#if (gte roll.modifierTotal 0)}}+{{else}}-{{/if}} - {{positive roll.modifierTotal}} -
-
- {{#if (and @root.isGM (ne ../partId "leader"))}} -
- - -
- {{/if}} -
- {{else if (and readyToRoll isEditable)}} - - 2d12 - - {{/if}} -
-{{/with}} \ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/parts/result.hbs b/templates/dialogs/groupRollDialog/parts/result.hbs deleted file mode 100644 index d90dfb5c..00000000 --- a/templates/dialogs/groupRollDialog/parts/result.hbs +++ /dev/null @@ -1,30 +0,0 @@ -{{#if (and hasRolled leader.roll)}} -
-
- {{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leaderRoll"}} - - {{leader.roll.total}} - {{localize "DAGGERHEART.GENERAL.withThing" thing=leader.roll.totalLabel}} - -
-
- {{localize "DAGGERHEART.GENERAL.Modifier.plural"}} -
- {{#each groupRoll.modifiers as |modifier|}} - - {{numberFormat modifier sign=true}} - - {{/each}} -
-
-
-
- {{localize "DAGGERHEART.GENERAL.total"}} - {{groupRoll.total}} {{groupRoll.totalLabel}} -
-
-{{else}} -
- {{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.resultsHint"}} -
-{{/if}} \ No newline at end of file diff --git a/templates/settings/variant-rules.hbs b/templates/settings/variant-rules.hbs index 9c9650dd..cdaef024 100644 --- a/templates/settings/variant-rules.hbs +++ b/templates/settings/variant-rules.hbs @@ -32,7 +32,7 @@