diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 80b84704..e245c7fa 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -35,7 +35,7 @@ jobs: env: version: ${{steps.get_version.outputs.version-without-v}} url: https://github.com/${{github.repository}} - manifest: https://raw.githubusercontent.com/{{github.repository}}/main/system.json + manifest: https://raw.githubusercontent.com/${{github.repository}}/main/system.json download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/system.zip # Create a zip file with all files required by the module to add to the release diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 5236afb8..054331b5 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -366,8 +366,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio let rollIsSelected = false; for (const member of Object.values(members)) { const rollFinished = Boolean(member.rollData); - const damageFinished = - member.rollData?.options?.hasDamage !== undefined ? member.rollData.options.damage : true; + const damageFinished = member.rollData?.options?.hasDamage ? Boolean(member.rollData.options.damage) : true; rollsAreFinished = rollsAreFinished && rollFinished && damageFinished; rollIsSelected = rollIsSelected || member.selected; diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 4bb1b6b3..26d67887 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -492,7 +492,7 @@ export const defaultRestOptions = { value: { custom: { enabled: true, - formula: '@system.armorScore' + formula: '@system.armorScore.max' } } } diff --git a/module/data/activeEffect/changeTypes/armor.mjs b/module/data/activeEffect/changeTypes/armor.mjs index f400d41b..2f3b9765 100644 --- a/module/data/activeEffect/changeTypes/armor.mjs +++ b/module/data/activeEffect/changeTypes/armor.mjs @@ -44,7 +44,8 @@ export default class ArmorChange extends foundry.abstract.DataModel { label: 'Armor', defaultPriority: 20, handler: (actor, change, _options, _field, replacementData) => { - const parsedMax = itemAbleRollParse(change.value.max, actor, change.effect.parent); + const baseParsedMax = itemAbleRollParse(change.value.max, actor, change.effect.parent); + const parsedMax = new Roll(baseParsedMax).evaluateSync().total; game.system.api.documents.DhActiveEffect.applyChange( actor, { @@ -110,6 +111,8 @@ export default class ArmorChange extends foundry.abstract.DataModel { }; get isSuppressed() { + if (!this.parent.parent?.actor) return false; + switch (this.value.interaction) { case CONFIG.DH.GENERAL.activeEffectArmorInteraction.active.id: return !this.parent.parent?.actor.system.armor; diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index e4a34bd4..aa4dd75f 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -246,7 +246,7 @@ export default class DHRoll extends Roll { return (this._formula = this.constructor.getFormula(this.terms)); } - /** + /** * Calculate total modifiers of any rolls, including non-dh rolls. * This exists because damage rolls still may receive base roll classes */ @@ -256,7 +256,7 @@ export default class DHRoll extends Roll { if (!roll.terms[i].isDeterministic) continue; const termTotal = roll.terms[i].total; if (typeof termTotal === 'number') { - const multiplier = roll.terms[i - 1]?.operator === " - " ? -1 : 1; + const multiplier = roll.terms[i - 1]?.operator === ' - ' ? -1 : 1; modifierTotal += multiplier * termTotal; } } @@ -272,7 +272,7 @@ export default class DHRoll extends Roll { const changeKeys = this.getActionChangeKeys(); return ( this.options.effects?.reduce((acc, effect) => { - if (effect.system.changes.some(x => changeKeys.some(key => x.key.includes(key)))) { + if (effect.system.changes.some(x => changeKeys.some(key => x.key?.includes(key)))) { acc[effect.id] = { id: effect.id, name: effect.name, diff --git a/module/dice/die/_module.mjs b/module/dice/die/_module.mjs index ed892f6a..19ca951a 100644 --- a/module/dice/die/_module.mjs +++ b/module/dice/die/_module.mjs @@ -1,9 +1,13 @@ import DualityDie from './dualityDie.mjs'; +import HopeDie from './hopeDie.mjs'; +import FearDie from './fearDie.mjs'; import AdvantageDie from './advantageDie.mjs'; import DisadvantageDie from './disadvantageDie.mjs'; export const diceTypes = { DualityDie, + HopeDie, + FearDie, AdvantageDie, DisadvantageDie }; diff --git a/module/dice/die/dualityDie.mjs b/module/dice/die/dualityDie.mjs index e9deb77f..83229425 100644 --- a/module/dice/die/dualityDie.mjs +++ b/module/dice/die/dualityDie.mjs @@ -43,9 +43,10 @@ export default class DualityDie extends foundry.dice.terms.Die { options: { appearance: {} } }; - const preset = await getDiceSoNicePreset(diceSoNice[key], faces); - diceSoNiceRoll.dice[0].options.appearance = preset.appearance; - diceSoNiceRoll.dice[0].options.modelFile = preset.modelFile; + const diceAppearance = await this.getDiceSoNiceAppearance(options.liveRoll.roll); + diceSoNiceRoll.dice[0].options.appearance = diceAppearance.appearance; + diceSoNiceRoll.dice[0].options.modelFile = diceAppearance.modelFile; + diceSoNiceRoll.dice[0].results = diceSoNiceRoll.dice[0].results.filter(x => x.active); await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true); } else { @@ -59,4 +60,11 @@ export default class DualityDie extends foundry.dice.terms.Die { this.#updateResources(oldDuality, newDuality, options.liveRoll.actor); } } + + /** + * Overridden by extending classes HopeDie and FearDie + */ + async getDiceSoNiceAppearance() { + return {}; + } } diff --git a/module/dice/die/fearDie.mjs b/module/dice/die/fearDie.mjs new file mode 100644 index 00000000..2a09d432 --- /dev/null +++ b/module/dice/die/fearDie.mjs @@ -0,0 +1,9 @@ +import { getDiceSoNicePresets } from '../../config/generalConfig.mjs'; +import DualityDie from './dualityDie.mjs'; + +export default class FearDie extends DualityDie { + async getDiceSoNiceAppearance(roll) { + const { fear } = await getDiceSoNicePresets(roll, this.denomination, this.denomination); + return fear; + } +} diff --git a/module/dice/die/hopeDie.mjs b/module/dice/die/hopeDie.mjs new file mode 100644 index 00000000..af5a4425 --- /dev/null +++ b/module/dice/die/hopeDie.mjs @@ -0,0 +1,9 @@ +import { getDiceSoNicePresets } from '../../config/generalConfig.mjs'; +import DualityDie from './dualityDie.mjs'; + +export default class HopeDie extends DualityDie { + async getDiceSoNiceAppearance(roll) { + const { hope } = await getDiceSoNicePresets(roll, this.denomination, this.denomination); + return hope; + } +} diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index bc381f07..f9a06d37 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -24,7 +24,7 @@ export default class DualityRoll extends D20Roll { } get dHope() { - if (!(this.dice[0] instanceof game.system.api.dice.diceTypes.DualityDie)) this.createBaseDice(); + if (!(this.dice[0] instanceof game.system.api.dice.diceTypes.HopeDie)) this.createBaseDice(); return this.dice[0]; } @@ -34,7 +34,7 @@ export default class DualityRoll extends D20Roll { } get dFear() { - if (!(this.dice[1] instanceof game.system.api.dice.diceTypes.DualityDie)) this.createBaseDice(); + if (!(this.dice[1] instanceof game.system.api.dice.diceTypes.FearDie)) this.createBaseDice(); return this.dice[1]; } @@ -68,8 +68,8 @@ export default class DualityRoll extends D20Roll { } get extraDice() { - const { DualityDie, AdvantageDie, DisadvantageDie } = game.system.api.dice.diceTypes; - return this.dice.filter(x => ![DualityDie, AdvantageDie, DisadvantageDie].some(die => x instanceof die)); + const { HopeDie, FearDie, AdvantageDie, DisadvantageDie } = game.system.api.dice.diceTypes; + return this.dice.filter(x => ![HopeDie, FearDie, AdvantageDie, DisadvantageDie].some(die => x instanceof die)); } setRallyChoices() { @@ -125,8 +125,8 @@ export default class DualityRoll extends D20Roll { /** @inheritDoc */ static fromData(data) { - data.terms[0].class = 'DualityDie'; - data.terms[2].class = 'DualityDie'; + data.terms[0].class = 'HopeDie'; + data.terms[2].class = 'FearDie'; if (data.options.roll.advantage?.type && data.terms[4]?.faces) { data.terms[4].class = data.options.roll.advantage.type === 1 ? 'AdvantageDie' : 'DisadvantageDie'; } @@ -135,18 +135,18 @@ export default class DualityRoll extends D20Roll { createBaseDice() { if ( - this.dice[0] instanceof game.system.api.dice.diceTypes.DualityDie && - this.dice[1] instanceof game.system.api.dice.diceTypes.DualityDie + this.dice[0] instanceof game.system.api.dice.diceTypes.HopeDie && + this.dice[1] instanceof game.system.api.dice.diceTypes.FearDie ) { this.terms = [this.terms[0], this.terms[1], this.terms[2]]; return; } - this.terms[0] = new game.system.api.dice.diceTypes.DualityDie({ + this.terms[0] = new game.system.api.dice.diceTypes.HopeDie({ faces: this.data.rules.dualityRoll?.defaultHopeDice ?? 12 }); this.terms[1] = new foundry.dice.terms.OperatorTerm({ operator: '+' }); - this.terms[2] = new game.system.api.dice.diceTypes.DualityDie({ + this.terms[2] = new game.system.api.dice.diceTypes.FearDie({ faces: this.data.rules.dualityRoll?.defaultFearDice ?? 12 }); } diff --git a/module/systemRegistration/migrations.mjs b/module/systemRegistration/migrations.mjs index 458ee6ef..c2c53f4e 100644 --- a/module/systemRegistration/migrations.mjs +++ b/module/systemRegistration/migrations.mjs @@ -1,3 +1,4 @@ +import { defaultRestOptions } from '../config/generalConfig.mjs'; import { RefreshType, socketEvent } from './socket.mjs'; export async function runMigrations() { @@ -341,6 +342,18 @@ export async function runMigrations() { lastMigrationVersion = '2.0.0'; } + + if (foundry.utils.isNewerVersion('2.0.4', lastMigrationVersion)) { + const downtimeMoves = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew); + if (downtimeMoves.restMoves.longRest.moves.repairArmor) { + await downtimeMoves.updateSource({ + 'restMoves.longRest.moves.repairArmor': defaultRestOptions.longRest().repairArmor + }); + game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, downtimeMoves.toObject()); + } + + lastMigrationVersion = '2.0.4'; + } //#endregion await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion, lastMigrationVersion); diff --git a/styles/less/global/prose-mirror.less b/styles/less/global/prose-mirror.less index 506fb8b7..3523dc89 100644 --- a/styles/less/global/prose-mirror.less +++ b/styles/less/global/prose-mirror.less @@ -4,6 +4,7 @@ .application.daggerheart { prose-mirror { height: 100% !important; + width: 100%; .editor-menu { background-color: transparent; diff --git a/styles/less/sheets/actors/party/resources.less b/styles/less/sheets/actors/party/resources.less index 4db254bf..68628295 100644 --- a/styles/less/sheets/actors/party/resources.less +++ b/styles/less/sheets/actors/party/resources.less @@ -155,6 +155,26 @@ body.game:is(.performance-low, .noblur) { } } + .stat-section { + position: relative; + display: flex; + gap: 10px; + background-color: light-dark(transparent, @dark-blue); + color: light-dark(@dark-blue, @golden); + padding: 5px 10px; + border: 1px solid light-dark(@dark-blue, @golden); + border-radius: 3px; + align-items: center; + width: fit-content; + + h4 { + font-size: var(--font-size-12); + font-weight: bold; + text-transform: uppercase; + color: light-dark(@dark-blue, @golden); + } + } + .threshold-section { display: flex; align-self: center; diff --git a/system.json b/system.json index ea71aaba..28d849b3 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.0.1", + "version": "2.0.3", "compatibility": { "minimum": "14.359", "verified": "14.359", @@ -297,7 +297,7 @@ "background": "systems/daggerheart/assets/logos/FoundrybornBackgroundLogo.png", "primaryTokenAttribute": "resources.hitPoints", "secondaryTokenAttribute": "resources.stress", - "url": "https://your/hosted/system/repo/", - "manifest": "https://your/hosted/system/repo/system.json", - "download": "https://your/packaged/download/archive.zip" + "url": "https://github.com/Foundryborne/daggerheart", + "manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/main/system.json", + "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.0.3/system.zip" } diff --git a/templates/actionTypes/range-target.hbs b/templates/actionTypes/range-target.hbs index 143acdf8..114c76a6 100644 --- a/templates/actionTypes/range-target.hbs +++ b/templates/actionTypes/range-target.hbs @@ -1,12 +1,12 @@
\ No newline at end of file diff --git a/templates/actionTypes/roll.hbs b/templates/actionTypes/roll.hbs index 2f257768..9784fc08 100644 --- a/templates/actionTypes/roll.hbs +++ b/templates/actionTypes/roll.hbs @@ -4,7 +4,7 @@ {{#if @root.hasBaseDamage}}{{formInput fields.useDefault name="roll.useDefault" value=source.useDefault dataset=(object tooltip="Use default Item values" tooltipDirection="UP")}}{{/if}} - {{formField fields.type label="Type" name="roll.type" value=source.type localize=true choices=@root.getRollTypeOptions}} + {{formField fields.type label="DAGGERHEART.GENERAL.type" name="roll.type" value=source.type localize=true choices=@root.getRollTypeOptions localize=true}} {{#if (eq source.type "diceSet")}}{{localize "DAGGERHEART.ACTIONS.Settings.saveHint"}}