diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index b472f383..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "js/ts.preferGoToSourceDefinition": true -} \ No newline at end of file diff --git a/README.md b/README.md index 6c90e73e..177636c7 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,11 @@ ## Table of Contents -- [Foundryborne Daggerheart](#foundryborne-daggerheart) - - [Table of Contents](#table-of-contents) - - [Overview](#overview) - - [User Install](#user-install) - - [Documentation](#documentation) - - [Development Setup](#development-setup) - - [Available Scripts](#available-scripts) - - [Notes](#notes) - - [Contributing](#contributing) - - [AI Policy](#ai-policy) - - [Disclaimer](#disclaimer) +- [Overview](#overview) +- [User Install Guide](#user-install) +- [Documentation](#documentation) +- [Developer Setup](#development-setup) +- [Contribution Info](#contributing) ## Overview @@ -78,7 +72,7 @@ Looking to contribute to the project? Look no further, check out our [contributi The Foundryborne Daggerheart system does not make use of AI (generative or otherwise) for any area of its implementation. We expect all contributors to follow this same policy when contributing with a pull request; contributions made using AI will be rejected outright. -## Disclaimer +## Disclaimer: **Daggerheart System** Daggerheart is a trademark of Darrington Press LLC. All original content, mechanics, and intellectual property related to the Daggerheart roleplaying game are © Darrington Press LLC. diff --git a/assets/icons/documents/actors/capybara.svg b/assets/icons/documents/actors/capybara.svg index 8fbe2c06..90deb64a 100644 --- a/assets/icons/documents/actors/capybara.svg +++ b/assets/icons/documents/actors/capybara.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/actors/dark-squad.svg b/assets/icons/documents/actors/dark-squad.svg index 39ca794a..f21b4c5b 100644 --- a/assets/icons/documents/actors/dark-squad.svg +++ b/assets/icons/documents/actors/dark-squad.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/actors/dragon-head.svg b/assets/icons/documents/actors/dragon-head.svg index 324ffbbb..d9e008f5 100644 --- a/assets/icons/documents/actors/dragon-head.svg +++ b/assets/icons/documents/actors/dragon-head.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/actors/drama-masks.svg b/assets/icons/documents/actors/drama-masks.svg index 98b9b68b..84307da0 100644 --- a/assets/icons/documents/actors/drama-masks.svg +++ b/assets/icons/documents/actors/drama-masks.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/actors/forest.svg b/assets/icons/documents/actors/forest.svg index fcdb8a9d..8f7117e8 100644 --- a/assets/icons/documents/actors/forest.svg +++ b/assets/icons/documents/actors/forest.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/battered-axe.svg b/assets/icons/documents/items/battered-axe.svg index 436884bd..5d7be27d 100644 --- a/assets/icons/documents/items/battered-axe.svg +++ b/assets/icons/documents/items/battered-axe.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/card-play.svg b/assets/icons/documents/items/card-play.svg index 5c29fc43..587cb1c1 100644 --- a/assets/icons/documents/items/card-play.svg +++ b/assets/icons/documents/items/card-play.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/chest-armor.svg b/assets/icons/documents/items/chest-armor.svg index 03b82d48..2cef80a6 100644 --- a/assets/icons/documents/items/chest-armor.svg +++ b/assets/icons/documents/items/chest-armor.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/family-tree.svg b/assets/icons/documents/items/family-tree.svg index 031f23da..d95c935d 100644 --- a/assets/icons/documents/items/family-tree.svg +++ b/assets/icons/documents/items/family-tree.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/laurel-crown.svg b/assets/icons/documents/items/laurel-crown.svg index 38dbcd04..34a54d2a 100644 --- a/assets/icons/documents/items/laurel-crown.svg +++ b/assets/icons/documents/items/laurel-crown.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/laurels.svg b/assets/icons/documents/items/laurels.svg index ae7398ec..2c3cdf63 100644 --- a/assets/icons/documents/items/laurels.svg +++ b/assets/icons/documents/items/laurels.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/open-treasure-chest.svg b/assets/icons/documents/items/open-treasure-chest.svg index d66399f4..172a8003 100644 --- a/assets/icons/documents/items/open-treasure-chest.svg +++ b/assets/icons/documents/items/open-treasure-chest.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/round-potion.svg b/assets/icons/documents/items/round-potion.svg index 0c235732..7f981914 100644 --- a/assets/icons/documents/items/round-potion.svg +++ b/assets/icons/documents/items/round-potion.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/stars-stack.svg b/assets/icons/documents/items/stars-stack.svg index 2d446683..19c197f6 100644 --- a/assets/icons/documents/items/stars-stack.svg +++ b/assets/icons/documents/items/stars-stack.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/village.svg b/assets/icons/documents/items/village.svg index b7c776a1..c28d742b 100644 --- a/assets/icons/documents/items/village.svg +++ b/assets/icons/documents/items/village.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/icons/documents/items/wolf-head.svg b/assets/icons/documents/items/wolf-head.svg index 7e57bbad..2be500c1 100644 --- a/assets/icons/documents/items/wolf-head.svg +++ b/assets/icons/documents/items/wolf-head.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/daggerheart.d.ts b/daggerheart.d.ts index 02abf063..7ff7fd59 100644 --- a/daggerheart.d.ts +++ b/daggerheart.d.ts @@ -2,19 +2,6 @@ import '@client/global.mjs'; import '@common/global.mjs'; import '@common/primitives/global.mjs'; import Canvas from '@client/canvas/board.mjs'; -import { ResourceUpdateMap } from './module/data/action/baseAction.mjs'; - -import * as applications from './module/applications/_module.mjs'; -import * as data from './module/data/_module.mjs'; -import * as models from './module/data/_module.mjs'; -import * as documents from './module/documents/_module.mjs'; -import { macros } from './module/_module.mjs'; -import * as dice from './module/dice/_module.mjs'; -import * as fields from './module/data/fields/_module.mjs'; -import { gameSettings } from './module/config/settingsConfig.mjs'; -import DhCountdowns from './module/data/countdowns.mjs'; -import DhAutomation from './module/data/settings/Automation.mjs'; - // Foundry's use of `Object.assign(globalThis) means many globally available objects are not read as such // This declare global hopefully fixes that @@ -52,67 +39,4 @@ declare global { const Collection: foundry.utils.Collection; const FormDataExtended: foundry.applications.ux.FormDataExtended; const TextEditor: foundry.applications.ux.TextEditor; - - /** - * Data used to build rolls such as duality rolls. The definition is incomplete and likely incorrect. - * Objects will often accept a Partial and spit out a non-partial. Those that are not guaranteed should be marked optional. - */ - interface RollConfig { - // unverified, check which ones are used and optional/not optional - event: Event; - title: string; - roll: { - modifier: number; - simple: boolean; - type: string; - difficulty: number; - }; - hasDamage: boolean; - hasEffect: boolean; - hasRoll: boolean; - chatMessage: { - template: string; - mute: boolean; - }; - targets: object; - costs: object; - - // verified - source?: { - /** uuid of the actor this roll is coming from */ - actor: string; - }; - /** Roll data associated with the actor or item */ - data: object; - resourceUpdates: ResourceUpdateMap; - hooks: string[]; - dialog: { - configure: boolean; - }; - damageOptions: object; - } } - -declare module '@client/packages/system.mjs' { - export default interface System { - api: { - applications: typeof applications, - data: typeof data, - models: typeof models, - documents: typeof documents, - macros: typeof macros, - dice: typeof dice, - fields: typeof fields - }; - } -} - -declare module '@client/helpers/client-settings.mjs' { - // Add explicit typed overrides for auto complete. These require /** @type {"string"} on the vars themselves to work */ - export default interface ClientSettings { - get(namespace: 'daggerheart', key: typeof gameSettings.Automation): DhAutomation; - get(namespace: 'daggerheart', key: typeof gameSettings.Homebrew): DhHomebrew; - get(namespace: 'daggerheart', key: typeof gameSettings.Countdowns): DhCountdowns; - get(namespace: 'daggerheart', key: string): unknown; - } -} \ No newline at end of file diff --git a/daggerheart.mjs b/daggerheart.mjs index 2c51c1f6..b92be2a2 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -6,7 +6,6 @@ import * as documents from './module/documents/_module.mjs'; import { macros } from './module/_module.mjs'; import * as collections from './module/documents/collections/_module.mjs'; import * as dice from './module/dice/_module.mjs'; -import * as die from './module/dice/die/_module.mjs'; import * as fields from './module/data/fields/_module.mjs'; import RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs'; import { enricherConfig, enricherRenderSetup } from './module/enrichers/_module.mjs'; @@ -24,7 +23,7 @@ import TokenManager from './module/documents/tokenManager.mjs'; CONFIG.DH = SYSTEM; CONFIG.TextEditor.enrichers.push(...enricherConfig); -CONFIG.Dice.rolls = [Roll = BaseRoll, DHRoll, DualityRoll, D20Roll, DamageRoll, FateRoll]; +CONFIG.Dice.rolls = [BaseRoll, DHRoll, DualityRoll, D20Roll, DamageRoll, FateRoll]; CONFIG.Dice.daggerheart = { DHRoll: DHRoll, DualityRoll: DualityRoll, @@ -39,8 +38,6 @@ CONFIG.RegionBehavior.dataModels = { }; Object.assign(CONFIG.Dice.termTypes, dice.diceTypes); -CONFIG.Dice.terms.d = die.BaseDie; -CONFIG.Dice.types = [die.BaseDie, CONFIG.Dice.terms.f]; CONFIG.Actor.documentClass = documents.DhpActor; CONFIG.Actor.dataModels = models.actors.config; @@ -270,10 +267,6 @@ Hooks.on('i18nInit', () => { }); Hooks.on('setup', () => { - if (game.user.isGM) { - document.body.dataset.gm = true; - } - CONFIG.statusEffects = [ ...CONFIG.statusEffects.filter(x => !['dead', 'unconscious'].includes(x.id)), ...Object.values(SYSTEM.GENERAL.conditions()).map(x => ({ @@ -397,7 +390,7 @@ const updateActorsRangeDependentEffects = async token => { ).rangeMeasurement; for (let effect of token.actor?.allApplicableEffects() ?? []) { - if (!effect.system.rangeDependence) continue; + if (!effect.system.rangeDependence?.enabled) continue; const { target, range, type } = effect.system.rangeDependence; // If there are no targets, assume false. Otherwise, start with the effect enabled. diff --git a/eslint.config.mjs b/eslint.config.mjs index 74141cc8..3c9b8fd9 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -90,26 +90,12 @@ export default defineConfig([ }, rules: { 'no-undef': 'error', - 'no-unused-vars': [ - 'error', - { - args: 'none', - destructuredArrayIgnorePattern: '^_', - varsIgnorePattern: '^_[A-Z]', - ignoreRestSiblings: true - } - ], + // 'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], ...stylisticRules } }, { files: ['**/*.ts'], - extends: [js.configs.recommended, tseslint.configs.recommended], - plugins: { - '@stylistic': stylistic - }, - rules: { - ...stylisticRules - } + extends: [js.configs.recommended, tseslint.configs.recommended] } ]); diff --git a/jsconfig.json b/jsconfig.json index 42c4b404..a0d51d0b 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -8,7 +8,7 @@ } }, "exclude": ["node_modules", "**/node_modules/*"], - "include": ["daggerheart.mjs", "foundry/client/client.mjs", "daggerheart.d.ts", "module/**/*.d.ts"], + "include": ["daggerheart.mjs", "foundry/client/client.mjs", "daggerheart.d.ts"], "typeAcquisition": { "include": ["jquery"] } diff --git a/lang/en.json b/lang/en.json index 232315c2..9f16828e 100755 --- a/lang/en.json +++ b/lang/en.json @@ -84,7 +84,6 @@ "transformActorMissing": "The assigned actor to transform into does not exist. It was probably deleted or moved in/out of a compendium", "canvasError": "There is no active scene.", "prototypeError": "You can only use a transform action from a Token", - "linkedSelectedError": "To transform a linked actor there either needs to be only a single token of it on the canvas, or you need to left-click select only one of them.", "actorLinkError": "You cannot transform a token with Actor Link set to true" } }, @@ -104,10 +103,8 @@ "startCountdown": "Start Countdown" }, "damage": { - "addResource": "Add Resource", "multiplier": "Multiplier", - "flatMultiplier": "Flat Multiplier", - "markResources": "Mark Resources" + "flatMultiplier": "Flat Multiplier" }, "general": { "customFormula": "Custom Formula", @@ -116,8 +113,7 @@ "area": { "sectionTitle": "Areas", "shape": "Shape", - "size": "Size", - "hasHole": "Area Hole" + "size": "Size" }, "displayInChat": "Display in chat", "deleteTriggerTitle": "Delete Trigger", @@ -126,15 +122,6 @@ "damageOnSave": "Damage on Save", "useDefaultItemValues": "Use default Item values" }, - "Reload": { - "checkReload": "Check Reload", - "reloadRequired": "Reload Required!", - "notRolled": "Not Rolled", - "checkFailed": "Check Failed", - "checkPassed": "Check Passed", - "rerollConfirmationTitle": "Reroll Reload Check", - "rerollConfirmationText": "Are you sure you want to reload the reload check?" - }, "RollField": { "diceRolling": { "compare": "Should be", @@ -178,7 +165,9 @@ }, "ACTIVEEFFECT": { "Config": { - "rangeDependence": { "title": "Range Dependence" }, + "rangeDependence": { + "title": "Range Dependence" + }, "stacking": { "title": "Stacking" }, "targetDispositions": "Affected Dispositions" }, @@ -495,6 +484,7 @@ "startFormula": "Randomized Start Value Formula", "currentCountdownCurrent": "Current: {value}", "currentCountdownStart": "Start: {value}", + "category": "Category", "progressionType": "Progression", "decreasing": "Decreasing", "looping": "Looping", @@ -783,7 +773,7 @@ "removeRoll": "Remove Roll", "resultsHint": "Results will appear when characters roll", "selectLeaderHint": "Select one Character to be the leader", - "selectParticipantsHint": "Select all Characters who will participate in the roll", + "selectParticipantsHint": "Select one Character to be the leader", "startGroupRoll": "Start Group Roll", "title": "Group Roll" }, @@ -881,10 +871,6 @@ "bruiser": "for each Bruiser adversary.", "solo": "for each Solo adversary." }, - "AreaTypes": { - "attached": { "label": "Attached To Token" }, - "placed": { "label": "Placed In Scene" } - }, "ArmorInteraction": { "none": { "label": "Ignores Armor" }, "active": { "label": "Active w/ Armor" }, @@ -1176,7 +1162,7 @@ "autoAppliedByLabel": "Max Stress" } }, - "CountdownProgressType": { + "CountdownType": { "actionRoll": "Action Roll", "characterAttack": "Character Attack", "characterSpotlight": "Character Spotlight", @@ -1184,10 +1170,6 @@ "fear": "Fear", "spotlight": "Spotlight" }, - "CountdownType": { - "encounter": { "label": "Short Term", "shortLabel": "Short" }, - "narrative": { "label": "Long Term", "shortLabel": "Long" } - }, "DaggerheartDiceAnimationEvents": { "critical": { "name": "Critical" }, "higher": { "name": "Highest Roll" } @@ -1331,11 +1313,6 @@ "short": "V. Far" } }, - "ReloadChoices": { - "off": { "label": "Don't Use" }, - "manual": { "label": "Manual" }, - "auto": { "label": "Automatic" } - }, "RollTypes": { "trait": { "name": "Trait" @@ -1471,7 +1448,7 @@ }, "triggerType": "Trigger Type", "triggeringActorType": "Triggering Actor Type", - "triggerError": "{trigger} trigger on {item}({itemUuid}) failed for {actor}. It's probably configured wrong." + "triggerError": "{trigger} trigger failed for {actor}. It's probably configured wrong." }, "WeaponFeature": { "barrier": { @@ -2030,8 +2007,7 @@ "Attachments": { "attachHint": "Drop items here to attach them", "transferHint": "If checked, this effect will be applied to any actor that owns this Effect's parent Item. The effect is always applied if this Item is attached to another one." - }, - "OriginTag": "Origin: {name}" + } }, "GENERAL": { "Ability": { @@ -2235,9 +2211,7 @@ }, "Resource": { "single": "Resource", - "plural": "Resources", - "unloaded": "The weapon is not loaded", - "loaded": "The weapon is loaded" + "plural": "Resources" }, "Roll": { "attack": "Attack Roll", @@ -2263,7 +2237,7 @@ "hint": "A used armor slot normally reduces damage by one step. This value increases the number of steps damage is reduced by." }, "magical": { - "label": "Damage Reduction: Only Magical", + "label": "Daamge Reduction: Only Magical", "hint": "Armor can only be used to reduce magical damage" }, "maxArmorMarkedBonus": "Max Armor Used", @@ -2501,6 +2475,7 @@ "reroll": "Reroll", "rerolled": "Rerolled", "rerollThing": "Reroll {thing}", + "resource": "Resource", "result": { "single": "Result", "plural": "Results" @@ -2567,9 +2542,6 @@ }, "identifier": { "label": "Identifier" - }, - "gmNotes": { - "label": "GM Notes" } }, "Ancestry": { @@ -2585,9 +2557,6 @@ "severe": "Severe Threshold" } }, - "Base": { - "addGMNote": "Add GM Note" - }, "Beastform": { "FIELDS": { "beastformType": { "label": "Beastform Type" }, @@ -2704,9 +2673,6 @@ "displayFear": { "label": "Display Fear" }, - "fearPosition": { - "label": "Fear Position" - }, "displayCountdownUI": { "label": "Display Countdown UI" }, @@ -2758,13 +2724,6 @@ "token": "Tokens", "bar": "Bar", "hide": "Hide" - }, - "fearPosition": { - "free": "Free", - "topCenter": "Top + Center", - "bottomCenter": "Bottom + Center", - "rightTop": "Right + Top", - "leftBottom": "Left + Bottom" } }, "Automation": { @@ -2823,10 +2782,6 @@ "hint": "Effects with defined range dependency will automatically turn on/off depending on range" } }, - "reload": { - "label": "Reload Checking", - "hint": "If the system should automatically roll reload checks or wait for the manual press of a button in chat" - }, "resourceScrollTexts": { "label": "Show Resource Change Scrolltexts", "hint": "When a character is damaged, uses armor etc, a scrolling text will briefly appear by the token to signify this." @@ -3270,7 +3225,7 @@ "beastformToManyAdvantages": "You cannot select any more advantages.", "beastformToManyFeatures": "You cannot select any more features.", "beastformEquipWeapon": "You cannot use weapons while in a Beastform.", - "loadoutMaxReached": "You've reached the maximum loadout size. To add more, move at least one domain card to the vault.", + "loadoutMaxReached": "You've reached maximum loadout. Move atleast one domain card to the vault, or increase the limit in homebrew settings if desired.", "domainMaxReached": "You've reached the maximum domains for the class. Increase the limit in homebrew settings if desired.", "insufficientResources": "You don't have enough resources to use that action.", "actionNoUsesRemaining": "That action doesn't have remaining uses.", @@ -3288,8 +3243,7 @@ "knowTheTide": "Know The Tide gained a token", "lackingItemTransferPermission": "User {user} lacks owner permission needed to transfer items to {target}", "noTokenTargeted": "No token is targeted", - "behaviorRegionRequiresGM": "Creating a Region with an attached Behavior requires an online GM", - "reloadRequired": "The {weapon} must be reloaded to be used!" + "behaviorRegionRequiresGM": "Creating a Region with an attached Behavior requires an online GM" }, "Progress": { "migrationLabel": "Performing system migration. Please wait and do not close Foundry." diff --git a/module/applications/characterCreation/characterCreation.mjs b/module/applications/characterCreation/characterCreation.mjs index 9d27fbb7..b068bf7a 100644 --- a/module/applications/characterCreation/characterCreation.mjs +++ b/module/applications/characterCreation/characterCreation.mjs @@ -1,5 +1,6 @@ import { abilities } from '../../config/actorConfig.mjs'; import { burden } from '../../config/generalConfig.mjs'; +import { createEmbeddedItemsWithEffects, createEmbeddedItemWithEffects } from '../../helpers/utils.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; diff --git a/module/applications/dialogs/beastformDialog.mjs b/module/applications/dialogs/beastformDialog.mjs index 8aca1844..8ae6d5fe 100644 --- a/module/applications/dialogs/beastformDialog.mjs +++ b/module/applications/dialogs/beastformDialog.mjs @@ -315,15 +315,15 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat const beastformEffect = selected.effects.find(x => x.type === 'beastform'); for (const traitBonus of app.modifications.traitBonuses) { - const existingChange = beastformEffect.system.changes.find( + const existingChange = beastformEffect.changes.find( x => x.key === `system.traits.${traitBonus.trait}.value` ); if (existingChange) { existingChange.value = Number.parseInt(existingChange.value) + traitBonus.bonus; } else { - beastformEffect.system.changes.push({ + beastformEffect.changes.push({ key: `system.traits.${traitBonus.trait}.value`, - type: 'add', + mode: 2, priority: null, value: traitBonus.bonus }); diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index 048797d8..e9140b56 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -160,7 +160,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio } if (rest.hasOwnProperty('trait')) { this.config.roll.trait = rest.trait; - if (!this.config.source.item && this.config.roll.trait) + if (!this.config.source.item) this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { ability: game.i18n.localize(abilities[this.config.roll.trait]?.label) }); @@ -225,6 +225,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio } static async submitRoll(event) { + event.preventDefault(); await this.close({ submitted: true }); } diff --git a/module/applications/dialogs/damageDialog.mjs b/module/applications/dialogs/damageDialog.mjs index ce613ade..46d3d41f 100644 --- a/module/applications/dialogs/damageDialog.mjs +++ b/module/applications/dialogs/damageDialog.mjs @@ -51,11 +51,7 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application const context = await super._prepareContext(_options); context.config = CONFIG.DH; context.title = this.config.title ?? this.title; - - const { damageFormula, resourceFormulas } = this.roll.constructFormulas(this.config); - context.damageFormula = damageFormula; - context.resourceFormulas = resourceFormulas; - + context.formula = this.roll.constructFormula(this.config); context.hasHealing = this.config.hasHealing; context.directDamage = this.config.directDamage; context.selectedMessageMode = this.config.selectedMessageMode; @@ -77,11 +73,7 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application static updateRollConfiguration(_event, _, formData) { const data = foundry.utils.expandObject(formData.object); - - if (this.config.damageFormula) - foundry.utils.mergeObject(this.config.damageFormula, data.damageFormula); - - foundry.utils.mergeObject(this.config.resourceFormulas, data.resourceFormulas); + foundry.utils.mergeObject(this.config.roll, data.roll); foundry.utils.mergeObject(this.config.modifiers, data.modifiers); this.config.selectedMessageMode = data.selectedMessageMode; diff --git a/module/applications/dialogs/damageReductionDialog.mjs b/module/applications/dialogs/damageReductionDialog.mjs index 8cb026f0..e5108e34 100644 --- a/module/applications/dialogs/damageReductionDialog.mjs +++ b/module/applications/dialogs/damageReductionDialog.mjs @@ -176,6 +176,7 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap } static updateData(event, _, formData) { + const form = foundry.utils.expandObject(formData.object); this.render(true); } diff --git a/module/applications/dialogs/deathMove.mjs b/module/applications/dialogs/deathMove.mjs index cfd7687b..4a949b99 100644 --- a/module/applications/dialogs/deathMove.mjs +++ b/module/applications/dialogs/deathMove.mjs @@ -139,15 +139,13 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV name: game.i18n.localize('DAGGERHEART.CONFIG.DeathMoves.blazeOfGlory.name'), description: game.i18n.localize('DAGGERHEART.CONFIG.DeathMoves.blazeOfGlory.description'), img: CONFIG.DH.GENERAL.deathMoves.blazeOfGlory.img, - system: { - changes: [ - { - key: 'system.rules.roll.guaranteedCritical', - type: 'add', - value: 'true' - } - ] - } + changes: [ + { + key: 'system.rules.roll.guaranteedCritical', + mode: 2, + value: 'true' + } + ] } ]); @@ -185,6 +183,8 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV if (result === undefined) return; + const autoExpandDescription = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance) + .expandRollMessage?.desc; const cls = getDocumentClass('ChatMessage'); const msg = { @@ -200,6 +200,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV img: this.selectedMove.img, description: game.i18n.localize(this.selectedMove.description), result: result, + open: autoExpandDescription ? 'open' : '', showRiskItAllButton: this.showRiskItAllButton, riskItAllButtonLabel: this.riskItAllButtonLabel, riskItAllHope: this.riskItAllHope diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index 5ba8e48e..e209cc3b 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -196,6 +196,9 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV .filter(x => x.testUserPermission(game.user, 'LIMITED')) .filter(x => x.uuid !== this.actor.uuid); + const autoExpandDescription = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance) + .expandRollMessage?.desc; + const cls = getDocumentClass('ChatMessage'); const msg = { user: game.user.id, @@ -216,7 +219,8 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV actor: { name: this.actor.name, img: this.actor.img }, moves: moves, characters: characters, - selfId: this.actor.uuid + selfId: this.actor.uuid, + open: autoExpandDescription ? 'open' : '' } ), flags: { diff --git a/module/applications/dialogs/groupRollDialog.mjs b/module/applications/dialogs/groupRollDialog.mjs index 779562cb..7196d848 100644 --- a/module/applications/dialogs/groupRollDialog.mjs +++ b/module/applications/dialogs/groupRollDialog.mjs @@ -1,7 +1,6 @@ import { ResourceUpdateMap } from '../../data/action/baseAction.mjs'; -import { shouldUseHopeFearAutomation } from '../../helpers/utils.mjs'; import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs'; -import PartySheet from '../sheets/actors/party.mjs'; +import Party from '../sheets/actors/party.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; @@ -11,7 +10,7 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat this.party = party; this.partyMembers = party.system.partyMembers - .filter(x => PartySheet.DICE_ROLL_ACTOR_TYPES.includes(x.type)) + .filter(x => Party.DICE_ROLL_ACTOR_TYPES.includes(x.type)) .map(member => ({ ...member.toObject(), uuid: member.uuid, @@ -481,23 +480,20 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat await cls.create(msgData); - /* Handle resource updates for the finished GroupRoll */ - if (shouldUseHopeFearAutomation({ gmAsPlayer: true })) { - const resourceMap = new ResourceUpdateMap(actor); - if (totalRoll.isCritical) { - resourceMap.addResources([ - { key: 'stress', value: -1 }, - { key: 'hope', value: 1 } - ]); - } else if (totalRoll.withHope) { - resourceMap.addResources([{ key: 'hope', value: 1 }]); - } else { - resourceMap.addResources([{ key: 'fear', value: 1 }]); - } - - resourceMap.updateResources(); + const resourceMap = new ResourceUpdateMap(actor); + if (totalRoll.isCritical) { + resourceMap.addResources([ + { key: 'stress', value: -1, total: 1 }, + { key: 'hope', value: 1, total: 1 } + ]); + } else if (totalRoll.withHope) { + resourceMap.addResources([{ key: 'hope', value: 1, total: 1 }]); + } else { + resourceMap.addResources([{ key: 'fear', value: 1, total: 1 }]); } + resourceMap.updateResources(); + /* Fin */ this.cancelRoll({ confirm: false }); } diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 4c6c5339..b2ce0258 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -1,9 +1,7 @@ -import { ResourceUpdateMap } from '../../data/action/baseAction.mjs'; -import { ChatDamageData } from '../../data/chat-message/chatDamageData.mjs'; import { MemberData } from '../../data/tagTeamData.mjs'; -import { getCritDamageBonus, shouldUseHopeFearAutomation } from '../../helpers/utils.mjs'; +import { getCritDamageBonus } from '../../helpers/utils.mjs'; import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs'; -import PartySheet from '../sheets/actors/party.mjs'; +import Party from '../sheets/actors/party.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; @@ -11,10 +9,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio constructor(party) { super({ id: `TagTeamDialog-${party.id}` }); - this.usesTagTeamHopeCost = true; this.party = party; this.partyMembers = party.system.partyMembers - .filter(x => PartySheet.DICE_ROLL_ACTOR_TYPES.includes(x.type)) + .filter(x => Party.DICE_ROLL_ACTOR_TYPES.includes(x.type)) .map(member => ({ ...member.toObject(), uuid: member.uuid, @@ -23,9 +20,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio owned: member.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) })); - this.initiator = { cost: - this.party.system.schema.fields.tagTeam.fields.initiator.fields.cost.initial - }; + this.initiator = { cost: 3 }; this.openForAllPlayers = true; this.tabGroups.application = Object.keys(party.system.tagTeam.members).length @@ -99,13 +94,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio ?.addEventListener('input', this.updateInitiatorMemberField.bind(this)); htmlElement - .querySelector('.initiator-cost-input') + .querySelector('.initiator-cost-field') ?.addEventListener('input', this.updateInitiatorCostField.bind(this)); - htmlElement - .querySelector('.initiator-cost-enabled-checkbox') - ?.addEventListener('change', this.toggleInitiatorCostEnabled.bind(this)); - htmlElement .querySelector('.openforall-field') ?.addEventListener('change', this.updateOpenForAllField.bind(this)); @@ -141,7 +132,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const hasRolled = Boolean(data.rollData); if (!hasRolled) return false; - return !data.rollData.options.hasDamage || data.damageRollData.active; + return !data.rollData.options.hasDamage || Boolean(data.rollData.options.damage); }); return context; @@ -165,7 +156,6 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio .map(x => ({ value: x.id, label: x.name })); partContext.initiatorDisabled = !selectedMembers.length; partContext.openForAllPlayers = this.openForAllPlayers; - partContext.usesTagTeamHopeCost = this.usesTagTeamHopeCost; break; case 'tagTeamRoll': @@ -182,7 +172,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const selectedRoll = Object.values(this.party.system.tagTeam.members).find(member => member.selected); const critSelected = !selectedRoll ? undefined - : (selectedRoll?.roll?.isCritical ?? false); + : (selectedRoll?.rollData?.options?.roll?.isCritical ?? false); partContext.hintText = await this.getInfoTexts(this.party.system.tagTeam.members); partContext.joinedRoll = await this.getJoinedRoll({ @@ -209,16 +199,6 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const rollOptions = []; const damageRollOptions = []; - - if (actor?.system.usedUnarmed) { - damageRollOptions.push({ - value: actor.system.attack.uuid, - label: actor.system.usedUnarmed.name, - group: actor.name, - baseAction: actor.system.attack - }); - } - for (const item of actor?.items ?? []) { if (!item.system.metadata.hasActions) continue; const actions = [...item.system.actions, ...(item.system.attack ? [item.system.attack] : [])]; @@ -236,7 +216,8 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio } const selectedRoll = Object.values(this.party.system.tagTeam.members).find(member => member.selected); - const critSelected = !selectedRoll ? undefined : (selectedRoll?.roll?.isCritical ?? false); + const critSelected = !selectedRoll ? undefined : (selectedRoll?.rollData?.options?.roll?.isCritical ?? false); + const damage = data.rollData?.options?.damage; return { ...data, @@ -247,9 +228,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio hasRolled: Boolean(data.rollData), rollOptions, damageRollOptions, - damage: data.damageRollData, - critDamage: await this.getCriticalDamage(data.damageRollData), - useCritDamage: critSelected || (critSelected === undefined && data.roll?.isCritical) + damage: damage, + critDamage: await this.getCriticalDamage(damage), + useCritDamage: critSelected || (critSelected === undefined && data.rollData?.options?.roll?.isCritical) }; } @@ -379,7 +360,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 ? member.damageRollData.active : true; + const damageFinished = member.rollData?.options?.hasDamage ? Boolean(member.rollData.options.damage) : true; rollsAreFinished = rollsAreFinished && rollFinished && damageFinished; rollIsSelected = rollIsSelected || member.selected; @@ -416,13 +397,6 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio this.render(); } - toggleInitiatorCostEnabled(_event) { - this.usesTagTeamHopeCost = !this.usesTagTeamHopeCost; - this.initiator.cost = this.usesTagTeamHopeCost ? - this.party.system.schema.fields.tagTeam.fields.initiator.fields.cost.initial : 0; - this.render(); - } - updateOpenForAllField(event) { this.openForAllPlayers = event.target.checked; this.render(); @@ -540,10 +514,17 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio await action.workflow.get('damage').execute(config, null, true); if (!config.damage) return; - + + const current = this.party.system.tagTeam.members[memberKey].rollData; await this.updatePartyData( { - [`system.tagTeam.members.${memberKey}.damageRollData`]: config.damage + [`system.tagTeam.members.${memberKey}.rollData`]: { + ...current, + options: { + ...current.options, + damage: config.damage + } + } }, this.getUpdatingParts(button) ); @@ -551,11 +532,15 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio static async #removeDamageRoll(_, button) { const { memberKey } = button.dataset; + const current = this.party.system.tagTeam.members[memberKey].rollData; this.updatePartyData( { - [`system.tagTeam.members.${memberKey}.damageRollData`]: { - main: null, - resources: _replace({}) + [`system.tagTeam.members.${memberKey}.rollData`]: { + ...current, + options: { + ...current.options, + damage: null + } } }, this.getUpdatingParts(button) @@ -563,44 +548,89 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio } static async #rerollDamageDice(_, button) { - const { isResource, memberKey, damageKey, diceIndex, resultIndex } = button.dataset; + const { memberKey, damageKey, part, dice } = button.dataset; const memberData = this.party.system.tagTeam.members[memberKey]; - await memberData.damageRollData.rerollDamageDie(isResource, damageKey, diceIndex, resultIndex); + const partData = memberData.rollData.options.damage[damageKey].parts[part]; + const activeDiceResultKey = Object.keys(partData.dice[dice].results).find( + index => partData.dice[dice].results[index].active + ); + const { parsedRoll, rerolledDice } = await game.system.api.dice.DamageRoll.reroll( + partData, + dice, + activeDiceResultKey + ); + + const rollData = this.party.system.tagTeam.members[memberKey].rollData; + rollData.options.damage[damageKey].parts = rollData.options.damage[damageKey].parts.map((damagePart, index) => { + if (index !== Number.parseInt(part)) return damagePart; + + return { + ...damagePart, + total: parsedRoll.total, + dice: rerolledDice + }; + }); + rollData.options.damage[damageKey].total = rollData.options.damage[damageKey].parts.reduce((acc, part) => { + acc += part.total; + return acc; + }, 0); - const basePath = `system.tagTeam.members.${memberKey}.damageRollData`; - const updatePath = isResource ? `${basePath}.resources.${damageKey}` : `${basePath}.main`; - const updateValue = isResource ? - memberData.damageRollData.resources[damageKey] : memberData.damageRollData.main; this.updatePartyData( { - [updatePath]: updateValue.toJSON() + [`system.tagTeam.members.${memberKey}.rollData`]: rollData }, this.getUpdatingParts(button) ); } - async getCriticalDamage(origDamage) { - const newDamage = origDamage ? ChatDamageData.fromJSON(JSON.stringify(origDamage)) : null; - if (newDamage?.main) { - const criticalDamage = await getCritDamageBonus(newDamage.main.formula); - if (criticalDamage) { - const criticalTerm = new foundry.dice.terms.NumericTerm({ number: criticalDamage, evaluated: true }); - criticalTerm.evaluate(); - newDamage.main = await Roll.fromTerms([ - ...origDamage.main.terms, - new foundry.dice.terms.OperatorTerm({ operator: '+' }), - criticalTerm - ]); - newDamage.main.options = foundry.utils.deepClone(origDamage.main.options); + async getCriticalDamage(damage) { + const newDamage = foundry.utils.deepClone(damage); + for (let key in newDamage) { + var damage = newDamage[key]; + damage.formula = ''; + damage.total = 0; + + for (let part of damage.parts) { + const criticalDamage = await getCritDamageBonus(part.formula); + if (criticalDamage) { + part.modifierTotal += criticalDamage; + part.total += criticalDamage; + part.formula = `${part.dice.map(x => x.formula).join(' + ')} + ${part.modifierTotal}`; + part.roll = new Roll(part.formula); + } + + damage.formula = [damage.formula, part.formula].filter(x => x).join(' + '); + damage.total += part.total; } - } + } + + return newDamage; + } + + async getNonCriticalDamage(config) { + const newDamage = foundry.utils.deepClone(config.damage); + for (let key in newDamage) { + var damage = newDamage[key]; + damage.formula = ''; + damage.total = 0; + + for (let part of damage.parts) { + const critDamageBonus = await getCritDamageBonus(part.formula); + part.modifierTotal -= critDamageBonus; + part.total -= critDamageBonus; + part.formula = `${part.dice.map(x => x.formula).join(' + ')} + ${part.modifierTotal}`; + part.roll = new Roll(part.formula); + + damage.formula = [damage.formula, part.formula].filter(x => x).join(' + '); + damage.total += part.total; + } + } return newDamage; } static async #selectRoll(_, button) { const { memberKey } = button.dataset; - this.updatePartyData( { [`system.tagTeam.members`]: Object.entries(this.party.system.tagTeam.members).reduce( @@ -611,12 +641,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio {} ) }, - /* Selecting a roll must update all member sections hbs to display the correct damage information incase of a critical */ - [ - ...Object.keys(this.party.system.tagTeam.members), - this.constructor.PARTS.rollSelection.id, - this.constructor.PARTS.result.id - ] + this.getUpdatingParts(button) ); } @@ -634,65 +659,29 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio if (!baseMainRoll?.rollData || !baseSecondaryRoll) return null; const mainRoll = new MemberData(baseMainRoll.toObject()); - mainRoll.damageRollData = baseMainRoll.damageRollData ? - ChatDamageData.fromJSON(JSON.stringify(baseMainRoll.damageRollData)) : null; - const secondaryRoll = new MemberData(baseSecondaryRoll.toObject()); - secondaryRoll.damageRollData = baseSecondaryRoll.damageRollData ? - ChatDamageData.fromJSON(JSON.stringify(baseSecondaryRoll.damageRollData)) : null; + const secondaryRollData = new MemberData(baseSecondaryRoll.toObject()).rollData; + const systemData = mainRoll.rollData.options; + const isCritical = overrideIsCritical ?? systemData.roll.isCritical; + if (isCritical) systemData.damage = await this.getCriticalDamage(systemData.damage); - const isCritical = overrideIsCritical ?? mainRoll.roll.isCritical; - if (isCritical) mainRoll.damageRollData = await this.getCriticalDamage(mainRoll.damageRollData); - - if (secondaryRoll.damageRollData) { + if (secondaryRollData?.options.hasDamage) { const secondaryDamage = (displayVersion ? overrideIsCritical : isCritical) - ? await this.getCriticalDamage(secondaryRoll.damageRollData) - : secondaryRoll.damageRollData; - if (mainRoll.damageRollData) { - if (secondaryDamage.main) { - if (mainRoll.damageRollData.main) { - mainRoll.damageRollData.main = Roll.fromTerms([ - ...baseMainRoll.damageRollData.main.terms, - new foundry.dice.terms.OperatorTerm({ operator: '+' }), - ...baseSecondaryRoll.damageRollData.main.terms - ]); - - /* Joining the roll.options of both rolls */ - const joinedDamageTypes = new Set([ - ...baseMainRoll.damageRollData.main.options.damageTypes, - ...baseSecondaryRoll.damageRollData.main.options.damageTypes - ]); - mainRoll.damageRollData.main.options = { - ...baseMainRoll.damageRollData.main.options, - damageTypes: [...joinedDamageTypes] - }; + ? await this.getCriticalDamage(secondaryRollData.options.damage) + : secondaryRollData.options.damage; + if (systemData.damage) { + for (const [key, damage] of Object.entries(secondaryDamage ?? {})) { + if (key in systemData.damage) { + systemData.damage[key].formula = [systemData.damage[key]?.formula, damage.formula] + .filter(x => x) + .join(' + '); + systemData.damage[key].total += damage.total; + systemData.damage[key].parts.push(...damage.parts); } else { - mainRoll.damageRollData.main = secondaryDamage.main; - } - } - - for (const [key, damage] of Object.entries(secondaryDamage.resources ?? {})) { - if (key in mainRoll.damageRollData.resources) { - mainRoll.damageRollData.resources[key] = Roll.fromTerms([ - ...baseMainRoll.damageRollData.resources[key].terms, - new foundry.dice.terms.OperatorTerm({ operator: '+' }), - ...baseSecondaryRoll.damageRollData.resources[key].terms - ]); - - /* Joining the roll.options of both rolls */ - const joinedDamageTypes = new Set([ - ...baseMainRoll.damageRollData.resources[key].options.damageTypes, - ...baseSecondaryRoll.damageRollData.resources[key].options.damageTypes - ]); - mainRoll.damageRollData.resources[key].options = { - ...baseMainRoll.damageRollData.resources[key].options, - damageTypes: [...joinedDamageTypes] - }; - } else { - mainRoll.damageRollData.resources[key] = damage; + systemData.damage[key] = damage; } } } else { - mainRoll.damageRollData = secondaryDamage; + systemData.damage = secondaryDamage; } } @@ -747,27 +736,13 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const mainActor = this.party.system.partyMembers.find(x => x.uuid === mainRoll.options.source.actor); mainRoll.options.title = game.i18n.localize('DAGGERHEART.APPLICATIONS.TagTeamSelect.chatMessageRollTitle'); - - /* This could assumably be done better. For some reason rolls don't get correctly done through rollData.toJSON */ - const systemData = { - ...mainRoll.options, - damage: joinedRoll.damageRollData?.toJSON() - }; - - if (joinedRoll.damageRollData.main) { - systemData.damage.main = joinedRoll.damageRollData.toJSON(); - } - for (const type of Object.keys(joinedRoll.damageRollData?.resources ?? {})) { - systemData.damage.resources[type] = joinedRoll.damageRollData.resources[type].toJSON(); - } - const cls = getDocumentClass('ChatMessage'), msgData = { type: 'dualityRoll', user: game.user.id, title: game.i18n.localize('DAGGERHEART.APPLICATIONS.TagTeamSelect.title'), speaker: cls.getSpeaker({ actor: mainActor }), - system: systemData, + system: mainRoll.options, rolls: [JSON.stringify(joinedRoll.roll)], sound: null, flags: { core: { RollTable: true } } @@ -777,37 +752,32 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio /* Handle resource updates from the finished TagTeamRoll */ const tagTeamData = this.party.system.tagTeam; - - const actorResourceMaps = Object.keys(tagTeamData.members).reduce((acc, key) => { - acc[key] = new ResourceUpdateMap(game.actors.get(key)); - return acc; - }, {}); - - if (shouldUseHopeFearAutomation({ gmAsPlayer: true })) { - const fearResourceMap = actorResourceMaps[tagTeamData.initiator.memberId]; - for (const memberId in tagTeamData.members) { - const resourceMap = actorResourceMaps[memberId]; - if (finalRoll.isCritical) { - resourceMap.addResources([ - { key: 'stress', value: -1, enabled: true }, - { key: 'hope', value: 1, enabled: true } - ]); - } else if (finalRoll.withHope) { - resourceMap.addResources([{ key: 'hope', value: 1, enabled: true }]); - } else if (finalRoll.withFear) { - fearResourceMap.addResources([{ key: 'fear', value: 1, enabled: true }]); - } + const fearUpdate = { key: 'fear', value: null, total: null, enabled: true }; + for (let memberId in tagTeamData.members) { + const resourceUpdates = []; + const rollGivesHope = finalRoll.isCritical || finalRoll.withHope; + if (memberId === tagTeamData.initiator.memberId) { + const value = tagTeamData.initiator.cost + ? rollGivesHope + ? 1 - tagTeamData.initiator.cost + : -tagTeamData.initiator.cost + : 1; + resourceUpdates.push({ key: 'hope', value: value, total: -value, enabled: true }); + } else if (rollGivesHope) { + resourceUpdates.push({ key: 'hope', value: 1, total: -1, enabled: true }); + } + if (finalRoll.isCritical) resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true }); + if (finalRoll.withFear) { + fearUpdate.value = fearUpdate.value === null ? 1 : fearUpdate.value + 1; + fearUpdate.total = fearUpdate.total === null ? -1 : fearUpdate.total - 1; } - } - /* Even with Hope/Fear automation off, the hope cost of performing the TagTeamRoll can still optionally be subtracted */ - if (tagTeamData.initiator.cost) { - const resourceMap = actorResourceMaps[tagTeamData.initiator.memberId]; - resourceMap.addResources([{ key: 'hope', value: -tagTeamData.initiator.cost, enabled: true }]); + game.actors.get(memberId).modifyResource(resourceUpdates); } - for (const resourceMap of Object.values(actorResourceMaps)) - resourceMap.updateResources(); + if (fearUpdate.value) { + mainActor.modifyResource([fearUpdate]); + } /* Fin */ this.cancelRoll({ confirm: false }); diff --git a/module/applications/levelup/levelup.mjs b/module/applications/levelup/levelup.mjs index f40609a4..cafc5c89 100644 --- a/module/applications/levelup/levelup.mjs +++ b/module/applications/levelup/levelup.mjs @@ -1,3 +1,4 @@ +import { abilities, subclassFeatureLabels } from '../../config/actorConfig.mjs'; import { getDeleteKeys, tagifyElement } from '../../helpers/utils.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; diff --git a/module/applications/settings/appearanceSettings.mjs b/module/applications/settings/appearanceSettings.mjs index f2defffb..9de9e752 100644 --- a/module/applications/settings/appearanceSettings.mjs +++ b/module/applications/settings/appearanceSettings.mjs @@ -1,13 +1,12 @@ +import DhAppearance from '../../data/settings/Appearance.mjs'; import { getDiceSoNicePreset } from '../../config/generalConfig.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; /** - * @import DhAppearance from '../../data/settings/Appearance.mjs'; * @import {ApplicationClickAction} from "@client/applications/_types.mjs" */ -/** Settings menu for appearance settings */ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(ApplicationV2) { /**@inheritdoc */ static DEFAULT_OPTIONS = { diff --git a/module/applications/sheets-configs/action-base-config.mjs b/module/applications/sheets-configs/action-base-config.mjs index e675fb3f..b65e1cdf 100644 --- a/module/applications/sheets-configs/action-base-config.mjs +++ b/module/applications/sheets-configs/action-base-config.mjs @@ -1,4 +1,4 @@ -import { DHDamageData } from '../../data/fields/action/damageField.mjs'; +import { getUnusedDamageTypes } from '../../helpers/utils.mjs'; import DaggerheartSheet from '../sheets/daggerheart-sheet.mjs'; const { ApplicationV2 } = foundry.applications.api; @@ -31,10 +31,8 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) removeElement: this.removeElement, removeTransformActor: this.removeTransformActor, editEffect: this.editEffect, - addDamage: this.#onAddDamage, - removeDamage: this.#onRemoveDamage, - addDamageResource: this.#onAddDamageResource, - removeDamageResource: this.#onRemoveDamageResource, + addDamage: this.addDamage, + removeDamage: this.removeDamage, editDoc: this.editDoc, addTrigger: this.addTrigger, removeTrigger: this.removeTrigger, @@ -159,9 +157,9 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) context.tabs = this._getTabs(this.constructor.TABS); context.config = CONFIG.DH; if (this.action.damage) { - const allKeys = Object.keys(CONFIG.DH.GENERAL.healingTypes); - context.allDamageTypesUsed = allKeys.every(k => k in this.action._source.damage.resources); - if (this.action.damage?.main?.hasOwnProperty('includeBase') && this.action.type === 'attack') + context.allDamageTypesUsed = !getUnusedDamageTypes(this.action.damage.parts).length; + + if (this.action.damage.hasOwnProperty('includeBase') && this.action.type === 'attack') context.hasBaseDamage = !!this.action.parent.attack; } @@ -255,7 +253,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) const submitData = this._prepareSubmitData(event, formData); const data = foundry.utils.mergeObject(this.action.toObject(), submitData); - this.action = (await this.action.update(data)) ?? this.action; + this.action = await this.action.update(data); this.sheetUpdate?.(this.action); this.render(); @@ -301,70 +299,53 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); } - /** @this DHActionBaseConfig */ - static #onAddDamage() { - if (!this.action.damage || this.action.damage?.main) return; + static addDamage(_event) { + if (!this.action.damage.parts) return; - const data = this.action.toObject(); - data.damage.main = { - ...DHDamageData.schema.getInitialValue(), - applyTo: 'hitPoints', - type: 'physical' - }; - this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); - } - - /** @this DHActionBaseConfig */ - static #onRemoveDamage() { - if (!this.action.damage?.main) return; - const data = this.action.toObject(); - data.damage.main = null; - this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); - } - - /** @this DHActionBaseConfig */ - static #onAddDamageResource(_event) { - if (!this.action.damage) return; - - const allKeys = Object.keys(CONFIG.DH.GENERAL.healingTypes); - const unused = allKeys.filter(k => !(k in this.action._source.damage.resources)); - const choices = unused.map(k => ({ value: k, label: _loc(CONFIG.DH.GENERAL.healingTypes[k].label) })); + const choices = getUnusedDamageTypes(this.action._source.damage.parts); const content = new foundry.data.fields.StringField({ - label: _loc('DAGGERHEART.GENERAL.Resource.single'), + label: game.i18n.localize('Damage Type'), choices, required: true - }).toFormGroup({}, { - name: 'type', - localize: true, - nameAttr: 'value', - labelAttr: 'label' - }).outerHTML; + }).toFormGroup( + {}, + { + name: 'type', + localize: true, + nameAttr: 'value', + labelAttr: 'label' + } + ).outerHTML; const callback = (_, button) => { const data = this.action.toObject(); const type = choices[button.form.elements.type.value].value; - data.damage.resources[type] = { - ...this.action.schema.fields.damage.fields.resources.element.getInitialValue(), - applyTo: type - }; + const part = this.action.schema.fields.damage.fields.parts.element.getInitialValue(); + part.applyTo = type; + if (type === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) + part.type = this.action.schema.fields.damage.fields.parts.element.fields.type.element.initial; + + data.damage.parts[type] = part; this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); }; const typeDialog = new foundry.applications.api.DialogV2({ buttons: [ - { - action: 'ok', - label: 'Confirm', - icon: 'fas fa-check', - default: true, - callback - } + foundry.utils.mergeObject( + { + action: 'ok', + label: 'Confirm', + icon: 'fas fa-check', + default: true + }, + { callback: callback } + ) ], content: content, rejectClose: false, modal: false, window: { - title: _loc('DAGGERHEART.ACTIONS.Config.damage.addResource') + title: game.i18n.localize('Add Damage') }, position: { width: 300 } }); @@ -372,12 +353,12 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) typeDialog.render(true); } - /** @this DHActionBaseConfig */ - static #onRemoveDamageResource(_event, button) { - if (!this.action.damage?.resources) return; + static removeDamage(_event, button) { + if (!this.action.damage.parts) return; const data = this.action.toObject(); const key = button.dataset.key; - data.damage.resources[key] = _del; + delete data.damage.parts[key]; + data.damage.parts[`${key}`] = _del; this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); } diff --git a/module/applications/sheets-configs/activeEffectConfig.mjs b/module/applications/sheets-configs/activeEffectConfig.mjs index 2967c5f1..2d9eafc3 100644 --- a/module/applications/sheets-configs/activeEffectConfig.mjs +++ b/module/applications/sheets-configs/activeEffectConfig.mjs @@ -155,10 +155,6 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac .querySelector('.stacking-change-checkbox') ?.addEventListener('change', this.stackingChangeToggle.bind(this)); - htmlElement - .querySelector('.range-dependence-change-checkbox') - ?.addEventListener('change', this.rangeDependenceChangeToggle.bind(this)); - htmlElement .querySelector('.armor-change-checkbox') ?.addEventListener('change', this.armorChangeToggle.bind(this)); @@ -228,20 +224,6 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac return this.submit({ updateData: { system: systemData } }); } - rangeDependenceChangeToggle(event) { - const rangeFields = this.document.system.schema.fields.rangeDependence.fields; - const systemData = { - rangeDependence: event.target.checked - ? _replace({ - type: rangeFields.type.initial, - target: rangeFields.target.initial, - range: rangeFields.range.initial - }) - : null - }; - return this.submit({ updateData: { system: systemData } }); - } - armorChangeToggle(event) { if (event.target.checked) { this.addArmorChange(); diff --git a/module/applications/sheets-configs/adversary-settings.mjs b/module/applications/sheets-configs/adversary-settings.mjs index 0bf18ee6..57405675 100644 --- a/module/applications/sheets-configs/adversary-settings.mjs +++ b/module/applications/sheets-configs/adversary-settings.mjs @@ -1,4 +1,3 @@ -import { DHDamageData } from '../../data/fields/action/damageField.mjs'; import DHBaseActorSettings from '../sheets/api/actor-setting.mjs'; /**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ @@ -9,11 +8,13 @@ export default class DHAdversarySettings extends DHBaseActorSettings { classes: ['adversary-settings'], position: { width: 455, height: 'auto' }, actions: { - addExperience: this.#onAddExperience, - removeExperience: this.#onRemoveExperience, - addDamage: this.#onAddDamage, - removeDamage: this.#onRemoveDamage - } + addExperience: DHAdversarySettings.#addExperience, + removeExperience: DHAdversarySettings.#removeExperience + }, + dragDrop: [ + { dragSelector: null, dropSelector: '.tab.features' }, + { dragSelector: '.feature-item', dropSelector: null } + ] }; /**@override */ @@ -37,8 +38,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings { }, features: { id: 'features', - template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs', - scrollable: [''] + template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs' } }; @@ -54,16 +54,12 @@ export default class DHAdversarySettings extends DHBaseActorSettings { async _prepareContext(options) { const context = await super._prepareContext(options); - // Get feature groups. Uncategorized go to actions - const featureFormsTypes = ['passive', 'action', 'reaction']; - const features = this.document.system.features.sort((a, b) => a.sort - b.sort); - const featureGroups = featureFormsTypes.map(t => ({ - featureForm: t, - label: _loc(CONFIG.DH.ITEM.featureForm[t]), - features: features.filter(f => f.system.featureForm === t) - })); - featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm))); - context.featureGroups = featureGroups; + const featureForms = ['passive', 'action', 'reaction']; + context.features = context.document.system.features.sort((a, b) => + a.system.featureForm !== b.system.featureForm + ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) + : a.sort - b.sort + ); return context; } @@ -74,7 +70,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings { * Adds a new experience entry to the actor. * @type {ApplicationClickAction} */ - static async #onAddExperience() { + static async #addExperience() { const newExperience = { name: 'Experience', modifier: 0 @@ -86,7 +82,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings { * Removes an experience entry from the actor. * @type {ApplicationClickAction} */ - static async #onRemoveExperience(_, target) { + static async #removeExperience(_, target) { const experience = this.actor.system.experiences[target.dataset.experience]; const confirmed = await foundry.applications.api.DialogV2.confirm({ window: { @@ -102,27 +98,31 @@ export default class DHAdversarySettings extends DHBaseActorSettings { await this.actor.update({ [`system.experiences.${target.dataset.experience}`]: _del }); } - /** - * @this DHAdversarySettings - * @type {ApplicationClickAction} - */ - static #onAddDamage() { - this.actor.update({ - 'system.attack.damage.main': { - ...DHDamageData.schema.getInitialValue(), - applyTo: 'hitPoints', - type: 'physical' - } - }); + async _onDragStart(event) { + const featureItem = event.currentTarget.closest('.feature-item'); + + if (featureItem) { + const feature = this.actor.items.get(featureItem.id); + const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true }; + event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); + event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0); + } } - - /** - * @this DHAdversarySettings - * @type {ApplicationClickAction} - */ - static #onRemoveDamage() { - this.actor.update({ - 'system.attack.damage.main': null - }); + + async _onDrop(event) { + event.stopPropagation(); + const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); + + const item = await fromUuid(data.uuid); + if (item?.type === 'feature') { + if (data.fromInternal && item.parent?.uuid === this.actor.uuid) { + return; + } + + const itemData = item.toObject(); + delete itemData._id; + + await this.actor.createEmbeddedDocuments('Item', [itemData]); + } } } diff --git a/module/applications/sheets-configs/environment-settings.mjs b/module/applications/sheets-configs/environment-settings.mjs index 954d6381..6d74f9c6 100644 --- a/module/applications/sheets-configs/environment-settings.mjs +++ b/module/applications/sheets-configs/environment-settings.mjs @@ -15,7 +15,7 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { dragDrop: [ { dragSelector: null, dropSelector: '.category-container' }, { dragSelector: null, dropSelector: '.tab.features' }, - { dragSelector: '.feature-item, .inventory-item[data-type="adversary"]', dropSelector: null } + { dragSelector: '.feature-item', dropSelector: null } ] }; @@ -32,13 +32,11 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { }, features: { id: 'features', - template: 'systems/daggerheart/templates/sheets-settings/environment-settings/features.hbs', - scrollable: [''] + template: 'systems/daggerheart/templates/sheets-settings/environment-settings/features.hbs' }, adversaries: { id: 'adversaries', - template: 'systems/daggerheart/templates/sheets-settings/environment-settings/adversaries.hbs', - scrollable: [''] + template: 'systems/daggerheart/templates/sheets-settings/environment-settings/adversaries.hbs' } }; @@ -54,16 +52,12 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { async _prepareContext(options) { const context = await super._prepareContext(options); - // Get feature groups. Uncategorized go to actions - const featureFormsTypes = ['passive', 'action', 'reaction']; - const features = this.document.system.features.sort((a, b) => a.sort - b.sort); - const featureGroups = featureFormsTypes.map(t => ({ - featureForm: t, - label: _loc(CONFIG.DH.ITEM.featureForm[t]), - features: features.filter(f => f.system.featureForm === t) - })); - featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm))); - context.featureGroups = featureGroups; + const featureForms = ['passive', 'action', 'reaction']; + context.features = context.document.system.features.sort((a, b) => + a.system.featureForm !== b.system.featureForm + ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) + : a.sort - b.sort + ); return context; } @@ -116,30 +110,33 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { } async _onDragStart(event) { - const element = event.currentTarget.closest('.inventory-item[data-type=adversary]'); - if (element) { - const adversaryData = { type: 'Actor', uuid: element.dataset.itemUuid }; - event.dataTransfer.setData('text/plain', JSON.stringify(adversaryData)); - event.dataTransfer.setDragImage(element, 60, 0); - } else { - return super._onDragStart(event); + const featureItem = event.currentTarget.closest('.feature-item'); + + if (featureItem) { + const feature = this.actor.items.get(featureItem.id); + const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true }; + event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); + event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0); } } async _onDrop(event) { event.stopPropagation(); const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - const doc = await fromUuid(data.uuid); - if (doc?.type === 'adversary' && event.target.closest('.category-container')) { + const item = await fromUuid(data.uuid); + if (data.fromInternal && item?.parent?.uuid === this.actor.uuid) return; + + if (item.type === 'adversary' && event.target.closest('.category-container')) { const target = event.target.closest('.category-container'); const path = `system.potentialAdversaries.${target.dataset.potentialAdversary}.adversaries`; const current = foundry.utils.getProperty(this.actor, path).map(x => x.uuid); - if (!current.includes(doc.uuid)) { - await this.actor.update({ [path]: [...current, doc.uuid] }); - } - return; + await this.actor.update({ + [path]: [...current, item.uuid] + }); + this.render(); + } else if (item.type === 'feature' && event.target.closest('.tab.features')) { + await this.actor.createEmbeddedDocuments('Item', [item]); + this.render(); } - - return super._onDrop(event); } } diff --git a/module/applications/sheets-configs/npc-settings.mjs b/module/applications/sheets-configs/npc-settings.mjs index 33cbc270..c187877c 100644 --- a/module/applications/sheets-configs/npc-settings.mjs +++ b/module/applications/sheets-configs/npc-settings.mjs @@ -27,8 +27,7 @@ export default class DHNPCSettings extends DHBaseActorSettings { }, features: { id: 'features', - template: 'systems/daggerheart/templates/sheets-settings/npc-settings/features.hbs', - scrollable: [''] + template: 'systems/daggerheart/templates/sheets-settings/npc-settings/features.hbs' } }; @@ -44,17 +43,43 @@ export default class DHNPCSettings extends DHBaseActorSettings { async _prepareContext(options) { const context = await super._prepareContext(options); - // Get feature groups. Uncategorized go to actions - const featureFormsTypes = ['passive', 'action', 'reaction']; - const features = this.document.system.features.sort((a, b) => a.sort - b.sort); - const featureGroups = featureFormsTypes.map(t => ({ - featureForm: t, - label: _loc(CONFIG.DH.ITEM.featureForm[t]), - features: features.filter(f => f.system.featureForm === t) - })); - featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm))); - context.featureGroups = featureGroups; + const featureForms = ['passive', 'action', 'reaction']; + context.features = context.document.system.features.sort((a, b) => + a.system.featureForm !== b.system.featureForm + ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) + : a.sort - b.sort + ); return context; } + + /* -------------------------------------------- */ + + async _onDragStart(event) { + const featureItem = event.currentTarget.closest('.feature-item'); + + if (featureItem) { + const feature = this.actor.items.get(featureItem.id); + const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true }; + event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); + event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0); + } + } + + async _onDrop(event) { + event.stopPropagation(); + const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); + + const item = await fromUuid(data.uuid); + if (item?.type === 'feature') { + if (data.fromInternal && item.parent?.uuid === this.actor.uuid) { + return; + } + + const itemData = item.toObject(); + delete itemData._id; + + await this.actor.createEmbeddedDocuments('Item', [itemData]); + } + } } diff --git a/module/applications/sheets/actors/_types.d.ts b/module/applications/sheets/actors/_types.d.ts deleted file mode 100644 index 368801b9..00000000 --- a/module/applications/sheets/actors/_types.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import DhCompanion from '../../../data/actor/companion.mjs'; -import DhParty from '../../../data/actor/party.mjs'; -import DhpActor from '../../../documents/actor.mjs'; - -declare module './companion.mjs' { - export default interface DhCompanionSheet { - actor: DhpActor; - document: DhpActor; - } -} - -declare module './party.mjs' { - export default interface PartySheet { - actor: DhpActor; - document: DhpActor; - } -} - diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index b6e17ddd..c8d5a299 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -7,7 +7,7 @@ export default class AdversarySheet extends DHBaseActorSheet { /** @inheritDoc */ static DEFAULT_OPTIONS = { classes: ['adversary'], - position: { width: 645, height: 750 }, + position: { width: 660, height: 766 }, window: { resizable: true }, actions: { toggleHitPoints: AdversarySheet.#toggleHitPoints, @@ -58,13 +58,12 @@ export default class AdversarySheet extends DHBaseActorSheet { template: 'systems/daggerheart/templates/sheets/actors/adversary/features.hbs', scrollable: ['.feature-section'] }, + notes: { + template: 'systems/daggerheart/templates/sheets/actors/adversary/notes.hbs' + }, effects: { template: 'systems/daggerheart/templates/sheets/actors/adversary/effects.hbs', scrollable: ['.effects-sections'] - }, - notes: { - template: 'systems/daggerheart/templates/sheets/actors/adversary/notes.hbs', - scrollable: ['.editor-content'] } }; @@ -104,7 +103,7 @@ export default class AdversarySheet extends DHBaseActorSheet { context.resources.stress.emptyPips = context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0; - const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm); + const featureForms = ['passive', 'action', 'reaction']; context.features = this.document.system.features.sort((a, b) => a.system.featureForm !== b.system.featureForm ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) @@ -132,15 +131,6 @@ export default class AdversarySheet extends DHBaseActorSheet { return context; } - /** @inheritdoc */ - _prepareTabs(group) { - const result = super._prepareTabs(group); - if (group === 'primary') { - result.notes.empty = !this.document.system.notes?.trim(); - } - return result; - } - /**@inheritdoc */ _attachPartListeners(partId, htmlElement, options) { super._attachPartListeners(partId, htmlElement, options); diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index b88ec6fd..f0f8326f 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, itemAbleRollParse, sortBy } from '../../../helpers/utils.mjs'; +import { getArmorSources, getDocFromElement, getDocFromElementSync, sortBy } from '../../../helpers/utils.mjs'; /**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ @@ -29,7 +29,6 @@ export default class CharacterSheet extends DHBaseActorSheet { toggleResourceDice: CharacterSheet.#toggleResourceDice, handleResourceDice: CharacterSheet.#handleResourceDice, advanceResourceDie: CharacterSheet.#advanceResourceDie, - toggleItemReload: CharacterSheet.#onToggleItemReload, cancelBeastform: CharacterSheet.#cancelBeastform, toggleResourceManagement: CharacterSheet.#toggleResourceManagement, useDowntime: this.useDowntime, @@ -810,7 +809,7 @@ export default class CharacterSheet extends DHBaseActorSheet { /* This could be avoided by baking config.costs into config.resourceUpdates. Didn't feel like messing with it at the time */ const costResources = - result.costs?.filter(x => x.enabled).map(cost => ({ ...cost, value: -cost.value })) || + result.costs?.filter(x => x.enabled).map(cost => ({ ...cost, value: -cost.value, total: -cost.total })) || {}; result.resourceUpdates.addResources(costResources); await result.resourceUpdates.updateResources(); @@ -915,7 +914,7 @@ export default class CharacterSheet extends DHBaseActorSheet { const doc = await getDocFromElement(button); const { available } = this.document.system.loadoutSlot; if (doc.system.inVault && !available && !doc.system.loadoutIgnore) { - return ui.notifications.warn('DAGGERHEART.UI.Notifications.loadoutMaxReached', { localize: true }); + return ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.loadoutMaxReached')); } await doc?.update({ 'system.inVault': !doc.system.inVault }); @@ -955,21 +954,11 @@ export default class CharacterSheet extends DHBaseActorSheet { }); } + /** */ static #advanceResourceDie(_, target) { this.updateResourceDie(target, true); } - static async #onToggleItemReload(_, target) { - const item = await getDocFromElement(target); - if (!item || !item.system.resource?.max) - return; - - await item.update({ - 'system.resource.value': item.system.needsReload ? - itemAbleRollParse(item.system.resource.max, this.document, item) : 0 - }) - } - lowerResourceDie(event) { event.preventDefault(); event.stopPropagation(); @@ -1068,7 +1057,7 @@ export default class CharacterSheet extends DHBaseActorSheet { direction: 'DOWN' }); - html.querySelectorAll('.armor .slot').forEach(element => { + html.querySelectorAll('.armor-slot').forEach(element => { element.addEventListener('click', CharacterSheet.armorSourcePipUpdate); }); } @@ -1083,7 +1072,7 @@ export default class CharacterSheet extends DHBaseActorSheet { /** Update specific armor source */ static async armorSourcePipUpdate(event) { - const target = event.target.closest('.slot'); + const target = event.target.closest('.armor-slot'); const { uuid, value } = target.dataset; const document = await foundry.utils.fromUuid(uuid); @@ -1111,7 +1100,7 @@ export default class CharacterSheet extends DHBaseActorSheet { } const container = target.closest('.slot-bar'); - for (const armorSlot of container.querySelectorAll('.armor .slot i')) { + for (const armorSlot of container.querySelectorAll('.armor-slot i')) { const index = Number.parseInt(armorSlot.dataset.index); if (decreasing && index >= newCurrent) { armorSlot.classList.remove('fa-shield'); @@ -1217,22 +1206,10 @@ export default class CharacterSheet extends DHBaseActorSheet { if (!confirmed) return; } - // Check for same actor drag/drop attempts - const isSameActor = this.document.uuid === item.parent?.uuid; - const loadoutFieldset = event.target.closest('[data-in-vault]'); - const vaulting = loadoutFieldset?.dataset.inVault === 'true'; - if (isSameActor && loadoutFieldset && item.type === 'domainCard' && vaulting !== item.system.inVault) { - // This is likely an attempt to vault or unvault an item - const { available } = this.document.system.loadoutSlot; - if (!vaulting && !available && !item.system.loadoutIgnore) { - return ui.notifications.warn('DAGGERHEART.UI.Notifications.loadoutMaxReached', { localize: true }); - } - return item.update({ 'system.inVault': vaulting }); - } else if (isSameActor) { + if (this.document.uuid === item.parent?.uuid) { return super._onDropItem(event, item); } - // Handle beastforms if (item.type === 'beastform') { if (this.document.effects.find(x => x.type === 'beastform')) { return ui.notifications.warn( diff --git a/module/applications/sheets/actors/companion.mjs b/module/applications/sheets/actors/companion.mjs index 4b5b5a56..a01b4a64 100644 --- a/module/applications/sheets/actors/companion.mjs +++ b/module/applications/sheets/actors/companion.mjs @@ -62,7 +62,9 @@ export default class DhCompanionSheet extends DHBaseActorSheet { await this.document.update({ 'system.resources.stress.value': newValue }); } - /** @this {DhCompanionSheet} **/ + /** + * + */ static async #actionRoll(event) { const partner = this.actor.system.partner; const config = { @@ -78,7 +80,6 @@ export default class DhCompanionSheet extends DHBaseActorSheet { const result = await partner.diceRoll(config); this.consumeResource(result?.costs); - result?.resourceUpdates.updateResources(); } // Remove when Action Refactor part #2 done diff --git a/module/applications/sheets/actors/environment.mjs b/module/applications/sheets/actors/environment.mjs index 60fb9071..f8ff74a6 100644 --- a/module/applications/sheets/actors/environment.mjs +++ b/module/applications/sheets/actors/environment.mjs @@ -72,22 +72,13 @@ export default class DhpEnvironment extends DHBaseActorSheet { return applicationOptions; } - /** @inheritdoc */ - _prepareTabs(group) { - const result = super._prepareTabs(group); - if (group === 'primary') { - result.potentialAdversaries.empty = foundry.utils.isEmpty(this.document.system.potentialAdversaries); - result.notes.empty = !this.document.system.notes?.trim(); - } - return result; - } - /**@inheritdoc */ async _preparePartContext(partId, context, options) { context = await super._preparePartContext(partId, context, options); switch (partId) { case 'header': await this._prepareHeaderContext(context, options); + break; case 'features': await this._prepareFeaturesContext(context, options); diff --git a/module/applications/sheets/actors/party.mjs b/module/applications/sheets/actors/party.mjs index a911669e..3af8ea5f 100644 --- a/module/applications/sheets/actors/party.mjs +++ b/module/applications/sheets/actors/party.mjs @@ -6,9 +6,7 @@ import DaggerheartMenu from '../../sidebar/tabs/daggerheartMenu.mjs'; import { socketEvent } from '../../../systemRegistration/socket.mjs'; import DhpActor from '../../../documents/actor.mjs'; -/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ - -export default class PartySheet extends DHBaseActorSheet { +export default class Party extends DHBaseActorSheet { constructor(options) { super(options); @@ -26,17 +24,17 @@ export default class PartySheet extends DHBaseActorSheet { resizable: true }, actions: { - openDocument: PartySheet.#onOpenDocument, - deletePartyMember: PartySheet.#onDeletePartyMember, - toggleHope: PartySheet.#onToggleHope, - toggleHitPoints: PartySheet.#onToggleHitPoints, - toggleStress: PartySheet.#onToggleStress, - toggleArmorSlot: PartySheet.#onToggleArmorSlot, - tempBrowser: PartySheet.#onTempBrowser, - refreshActions: PartySheet.#onRefreshActions, - triggerRest: PartySheet.#onTriggerRest, - tagTeamRoll: PartySheet.#onTagTeamRoll, - groupRoll: PartySheet.#onGroupRoll + openDocument: Party.#openDocument, + deletePartyMember: Party.#deletePartyMember, + toggleHope: Party.#toggleHope, + toggleHitPoints: Party.#toggleHitPoints, + toggleStress: Party.#toggleStress, + toggleArmorSlot: Party.#toggleArmorSlot, + tempBrowser: Party.#tempBrowser, + refeshActions: Party.#refeshActions, + triggerRest: Party.#triggerRest, + tagTeamRoll: Party.#tagTeamRoll, + groupRoll: Party.#groupRoll }, dragDrop: [{ dragSelector: '[data-item-id]', dropSelector: null }] }; @@ -74,23 +72,6 @@ export default class PartySheet extends DHBaseActorSheet { this._createSearchFilter(); } - /** @inheritdoc */ - _toggleDisabled(disabled) { - // Overriden to only disable text inputs by default if the user is a member - const isMember = this.actor.system.partyMembers.some( - m => m.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) - ); - if (!isMember) return super._toggleDisabled(disabled); - - const form = this.form; - for (const input of form.querySelectorAll('input:not([type=search]), .editor.prosemirror')) { - input.disabled = disabled; - } - for (const element of form.querySelectorAll('.input[contenteditable]')) { - element.classList.toggle('disabled', disabled); - } - } - /* -------------------------------------------- */ /* Prepare Context */ /* -------------------------------------------- */ @@ -217,16 +198,8 @@ export default class PartySheet extends DHBaseActorSheet { }; } } - - /* -------------------------------------------- */ - /* Event handlers */ - /* -------------------------------------------- */ - /** - * @this PartySheet - * @type {ApplicationClickAction} - */ - static async #onOpenDocument(_, target) { + static async #openDocument(_, target) { const uuid = target.dataset.uuid; const document = await foundry.utils.fromUuid(uuid); document?.sheet?.render(true); @@ -234,10 +207,9 @@ export default class PartySheet extends DHBaseActorSheet { /** * Toggles a hope resource value. - * @this PartySheet * @type {ApplicationClickAction} */ - static async #onToggleHope(_, target) { + static async #toggleHope(_, target) { const hopeValue = Number.parseInt(target.dataset.value); const actor = await foundry.utils.fromUuid(target.dataset.actorId); const newValue = actor.system.resources.hope.value >= hopeValue ? hopeValue - 1 : hopeValue; @@ -247,10 +219,9 @@ export default class PartySheet extends DHBaseActorSheet { /** * Toggles a hp resource value. - * @this PartySheet * @type {ApplicationClickAction} */ - static async #onToggleHitPoints(_, target) { + static async #toggleHitPoints(_, target) { const hitPointsValue = Number.parseInt(target.dataset.value); const actor = await foundry.utils.fromUuid(target.dataset.actorId); const newValue = actor.system.resources.hitPoints.value >= hitPointsValue ? hitPointsValue - 1 : hitPointsValue; @@ -260,10 +231,9 @@ export default class PartySheet extends DHBaseActorSheet { /** * Toggles a stress resource value. - * @this PartySheet * @type {ApplicationClickAction} */ - static async #onToggleStress(_, target) { + static async #toggleStress(_, target) { const stressValue = Number.parseInt(target.dataset.value); const actor = await foundry.utils.fromUuid(target.dataset.actorId); const newValue = actor.system.resources.stress.value >= stressValue ? stressValue - 1 : stressValue; @@ -273,10 +243,9 @@ export default class PartySheet extends DHBaseActorSheet { /** * Toggles a armor slot resource value. - * @this PartySheet * @type {ApplicationClickAction} */ - static async #onToggleArmorSlot(_, target) { + static async #toggleArmorSlot(_, target) { const actor = await foundry.utils.fromUuid(target.dataset.actorId); const { value, max } = actor.system.armorScore; const inputValue = Number.parseInt(target.dataset.value); @@ -289,19 +258,12 @@ export default class PartySheet extends DHBaseActorSheet { /** * Opens Compedium Browser - * @this PartySheet - * @type {ApplicationClickAction} */ - static async #onTempBrowser(_, target) { + static async #tempBrowser(_, target) { new ItemBrowser().render({ force: true }); } - /** - * @todo Is this unused? - * @this PartySheet - * @type {ApplicationClickAction} - */ - static async #onRefreshActions() { + static async #refeshActions() { const confirmed = await foundry.applications.api.DialogV2.confirm({ window: { title: 'New Section', @@ -319,11 +281,7 @@ export default class PartySheet extends DHBaseActorSheet { if (!confirmed) return; } - /** - * @this PartySheet - * @type {ApplicationClickAction} - */ - static async #onTriggerRest(_, button) { + static async #triggerRest(_, button) { const confirmed = await foundry.applications.api.DialogV2.confirm({ window: { title: game.i18n.localize(`DAGGERHEART.APPLICATIONS.Downtime.${button.dataset.type}.title`), @@ -346,30 +304,6 @@ export default class PartySheet extends DHBaseActorSheet { }); } - /** - * @this PartySheet - * @type {ApplicationClickAction} - */ - static async #onDeletePartyMember(event, target) { - const doc = await foundry.utils.fromUuid(target.closest('[data-uuid]')?.dataset.uuid); - if (!event.shiftKey) { - const confirmed = await foundry.applications.api.DialogV2.confirm({ - window: { - title: game.i18n.format('DAGGERHEART.ACTORS.Party.RemoveConfirmation.title', { - name: doc.name - }) - }, - content: game.i18n.format('DAGGERHEART.ACTORS.Party.RemoveConfirmation.text', { name: doc.name }) - }); - - if (!confirmed) return; - } - - const currentMembers = this.document.system.partyMembers.map(x => x.uuid); - const newMembersList = currentMembers.filter(uuid => uuid !== doc.uuid); - await this.document.update({ 'system.partyMembers': newMembersList }); - } - static async downtimeMoveQuery({ actorId, downtimeType }) { const actor = await foundry.utils.fromUuid(actorId); if (!actor || !actor?.isOwner) return; @@ -378,19 +312,11 @@ export default class PartySheet extends DHBaseActorSheet { }); } - /** - * @this PartySheet - * @type {ApplicationClickAction} - */ - static async #onTagTeamRoll() { + static async #tagTeamRoll() { new game.system.api.applications.dialogs.TagTeamDialog(this.document).render({ force: true }); } - /** - * @this PartySheet - * @type {ApplicationClickAction} - */ - static async #onGroupRoll(_params) { + static async #groupRoll(_params) { new game.system.api.applications.dialogs.GroupRollDialog(this.document).render({ force: true }); } @@ -534,10 +460,11 @@ export default class PartySheet extends DHBaseActorSheet { } } - /** @inheritdoc */ + /* -------------------------------------------- */ + async _onDropActor(event, document) { const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - if (document instanceof DhpActor && PartySheet.ALLOWED_ACTOR_TYPES.includes(document.type)) { + if (document instanceof DhpActor && Party.ALLOWED_ACTOR_TYPES.includes(document.type)) { const currentMembers = this.document.system.partyMembers.map(x => x.uuid); if (currentMembers.includes(data.uuid)) { return ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.duplicateCharacter')); @@ -550,4 +477,24 @@ export default class PartySheet extends DHBaseActorSheet { return null; } + + static async #deletePartyMember(event, target) { + const doc = await foundry.utils.fromUuid(target.closest('[data-uuid]')?.dataset.uuid); + if (!event.shiftKey) { + const confirmed = await foundry.applications.api.DialogV2.confirm({ + window: { + title: game.i18n.format('DAGGERHEART.ACTORS.Party.RemoveConfirmation.title', { + name: doc.name + }) + }, + content: game.i18n.format('DAGGERHEART.ACTORS.Party.RemoveConfirmation.text', { name: doc.name }) + }); + + if (!confirmed) return; + } + + const currentMembers = this.document.system.partyMembers.map(x => x.uuid); + const newMembersList = currentMembers.filter(uuid => uuid !== doc.uuid); + await this.document.update({ 'system.partyMembers': newMembersList }); + } } diff --git a/module/applications/sheets/api/actor-setting.mjs b/module/applications/sheets/api/actor-setting.mjs index fa434034..738f7002 100644 --- a/module/applications/sheets/api/actor-setting.mjs +++ b/module/applications/sheets/api/actor-setting.mjs @@ -1,15 +1,13 @@ import DHApplicationMixin from './application-mixin.mjs'; -const { ActorSheetV2 } = foundry.applications.sheets; +const { DocumentSheetV2 } = foundry.applications.api; -/** - * @typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction - */ +/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ /** * Base settings sheet for Daggerheart actors. - * @extends {DHApplicationMixin} + * @extends {DHApplicationMixin} */ -export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2) { +export default class DHBaseActorSettings extends DHApplicationMixin(DocumentSheetV2) { /**@inheritdoc */ static DEFAULT_OPTIONS = { classes: ['dialog'], @@ -25,7 +23,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2 }, dragDrop: [ { dragSelector: null, dropSelector: '.tab.features' }, - { dragSelector: '.feature-item, .inventory-item[data-type="feature"]', dropSelector: null } + { dragSelector: '.feature-item', dropSelector: null } ] }; @@ -36,7 +34,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2 return options; } - /** @returns {foundry.documents.Actor} */ + /**@returns {foundry.documents.Actor} */ get actor() { return this.document; } @@ -75,32 +73,4 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2 return context; } - - async _onDragStart(event) { - const featureItemEl = event.currentTarget.closest('.feature-item, .inventory-item[data-type="feature"]'); - const feature = this.actor.items.get(featureItemEl?.dataset.itemId); - if (feature && event.target.closest('.tab.features')) { - const featureData = { ...feature.toDragData(), fromInternal: true }; - event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); - event.dataTransfer.setDragImage(featureItemEl.querySelector('img'), 60, 0); - } - } - - async _onDrop(event) { - event.stopPropagation(); - const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); - const item = await fromUuid(data.uuid); - if (item?.type === 'feature') { - if (data.fromInternal && item.parent?.uuid === this.actor.uuid) { - return super._onDrop(event); - } - - const itemData = item.toObject(); - delete itemData._id; - await this.actor.createEmbeddedDocuments('Item', [itemData]); - } - } - - /** Setting sheets do not auto extend */ - async _autoExpandDescriptions() {} } diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index c99d245d..752dc80b 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -4,7 +4,6 @@ import { getDocFromElement, getDocFromElementSync, tagifyElement } from '../../. const typeSettingsMap = { character: 'extendCharacterDescriptions', adversary: 'extendAdversaryDescriptions', - npc: 'extendAdversaryDescriptions', environment: 'extendEnvironmentDescriptions', ancestry: 'extendItemDescriptions', community: 'extendItemDescriptions', @@ -263,7 +262,7 @@ export default function DHApplicationMixin(Base) { if (!!this.options.contextMenus.length) this._createContextMenus(); - this._autoExpandDescriptions(context); + this.#autoExtendDescriptions(context); } /** @inheritDoc */ @@ -305,7 +304,7 @@ export default function DHApplicationMixin(Base) { _preSyncPartState(partId, newElement, priorElement, state) { super._preSyncPartState(partId, newElement, priorElement, state); for (const el of priorElement.querySelectorAll('.extensible.extended')) { - const { actionId, itemUuid } = el.closest('[data-item-uuid], [data-action-id]').dataset; + const { actionId, itemUuid } = el.parentElement.dataset; const selector = `${actionId ? `[data-action-id="${actionId}"]` : `[data-item-uuid="${itemUuid}"]`} .extensible`; const newExtensible = newElement.querySelector(selector); newExtensible?.classList.add('extended'); @@ -382,35 +381,12 @@ export default function DHApplicationMixin(Base) { * @protected */ _onDrop(event) { - // Potentially handle subclasses that dont descend from actor/item sheet. + // Fallback to super, but note that config sheets don't have this option + // We still need this to avoid setting apps having issues event.stopPropagation(); return super._onDrop?.(event); } - /** @inheritdoc */ - _onSortItem(event, item) { - // If we are dragging a feature past its allowed feature form, put it in the front or in the back - const doc = this.actor.items.get(item.id); - const dropTargetEl = event.target.closest('[data-item-id]'); - const dropTarget = this.actor.items.get(dropTargetEl?.dataset.itemId); - if (doc?.type === 'feature' && dropTarget?.type === 'feature' && doc.system.featureForm !== dropTarget.system.featureForm) { - const siblings = this.actor.itemTypes.feature - .filter(f => f.system.featureForm === doc.system.featureForm) - .sort((a, b) => a.sort - b.sort); - if (siblings.length > 1) { - const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm); - const thisFeatureIdx = featureForms.indexOf(doc.system.featureForm); - const targetFeatureIdx = featureForms.indexOf(dropTarget.system.featureForm); - const target = targetFeatureIdx < thisFeatureIdx ? siblings[0] : siblings.at(-1); - const sortUpdates = foundry.utils.performIntegerSort(doc, { target, siblings }); - const updateData = sortUpdates.map(u => ({ ...u.update, _id: u.target._id })); - return this.actor.updateEmbeddedDocuments('Item', updateData); - } - } - - return super._onSortItem?.(event, item); - } - /* -------------------------------------------- */ /* Context Menu */ /* -------------------------------------------- */ @@ -518,7 +494,7 @@ export default function DHApplicationMixin(Base) { const doc = await getDocFromElement(target), action = doc?.system?.attack ?? doc; const config = action.prepareConfig(event); - config.effects = await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects( + config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects( this.document, doc ); @@ -603,7 +579,7 @@ export default function DHApplicationMixin(Base) { const doc = await fromUuid(itemUuid); //get inventory-item description element - const descriptionElement = el.querySelector('.inventory-description'); + const descriptionElement = el.querySelector('.invetory-description'); if (!doc || !descriptionElement) continue; // localize the description (idk if it's still necessary) @@ -631,9 +607,8 @@ export default function DHApplicationMixin(Base) { /** * Extend inventory description when enabled in settings. * @returns {Promise} - * @protected */ - async _autoExpandDescriptions(context) { + async #autoExtendDescriptions(context) { const inventoryItems = this.element.querySelectorAll('.inventory-item[data-item-uuid]'); for (const el of inventoryItems) { // Get the doc uuid from the element @@ -736,7 +711,7 @@ export default function DHApplicationMixin(Base) { * @type {ApplicationClickAction} */ static async #onCreateDoc(event, target) { - const { documentClass, type, inVault, disabled, featureForm } = target.dataset; + const { documentClass, type, inVault, disabled } = target.dataset; const parentIsItem = this.document.documentName === 'Item'; const featureOnCharacter = this.document.parent?.type === 'character' && type === 'feature'; const parent = featureOnCharacter @@ -754,7 +729,6 @@ export default function DHApplicationMixin(Base) { identifier: this.document.system.isMulticlass ? 'multiclass' : null }; } - if (featureForm) systemData.featureForm = featureForm; const cls = type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass); diff --git a/module/applications/sheets/api/base-actor.mjs b/module/applications/sheets/api/base-actor.mjs index 007b641b..027dd397 100644 --- a/module/applications/sheets/api/base-actor.mjs +++ b/module/applications/sheets/api/base-actor.mjs @@ -1,12 +1,10 @@ import { getDocFromElement, itemIsIdentical } from '../../../helpers/utils.mjs'; +import DHBaseActorSettings from './actor-setting.mjs'; import DHApplicationMixin from './application-mixin.mjs'; const { ActorSheetV2 } = foundry.applications.sheets; -/** - * @import DHBaseActorSettings from './actor-setting.mjs'; - * @typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction - */ +/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ /** * A base actor sheet extending {@link ActorSheetV2} via {@link DHApplicationMixin} @@ -212,7 +210,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { const doc = await getDocFromElement(target), action = doc?.system?.attack ?? doc; const config = action.prepareConfig(event); - config.effects = await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects( + config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects( this.document, doc ); diff --git a/module/applications/sheets/api/base-item.mjs b/module/applications/sheets/api/base-item.mjs index 70a6bcc6..1e08fc05 100644 --- a/module/applications/sheets/api/base-item.mjs +++ b/module/applications/sheets/api/base-item.mjs @@ -30,8 +30,7 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) { addFeature: DHBaseItemSheet.#addFeature, deleteFeature: DHBaseItemSheet.#deleteFeature, addResource: DHBaseItemSheet.#addResource, - removeResource: DHBaseItemSheet.#removeResource, - editGMNote: DHBaseItemSheet.#onEditGMNote + removeResource: DHBaseItemSheet.#removeResource }, dragDrop: [ { dragSelector: null, dropSelector: '.drop-section' }, @@ -77,16 +76,10 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) { /**@inheritdoc */ async _preparePartContext(partId, context, options) { await super._preparePartContext(partId, context, options); - const TextEditor = foundry.applications.ux.TextEditor.implementation; switch (partId) { case 'description': - context.enrichedDescription = await this.document.system.getEnrichedDescription({ gmNotes: false }); - context.enrichedGMNotes = await TextEditor.implementation.enrichHTML(this.item.system.gmNotes, { - relativeTo: this.item, - rollData: this.item.getRollData(), - secrets: this.item.isOwner - }) + context.enrichedDescription = await this.document.system.getEnrichedDescription(); break; case 'effects': await this._prepareEffectsContext(context, options); @@ -338,45 +331,4 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) { } } } - - /** - * Handles the Add GM Note button being pressed. This is only used when an item has no GM notes. - * Later edits to a GM note instead go through the normal editor toggle workflow. - * @this DHBaseItemSheet - */ - static #onEditGMNote() { - // Open the editor, which might be hidden. We remove the css class to hide temporarily - // so that menu auto resizing functions properly. - const editor = this.element.querySelector('prose-mirror[name="system.gmNotes"]'); - const wasHidden = editor.classList.contains('hide-if-inactive'); - editor.classList.remove('hide-if-inactive'); - editor.open = true; - window.setTimeout(() => { - if (wasHidden) editor.classList.add('hide-if-inactive'); - }, 0); - } - - /** @inheritdoc */ - async _onRender(context, options) { - await super._onRender(context, options); - - // Render an add gmnotes button if there are no set GM notes. - // We need to re-render on close since its possible to prosemirror to close *without* triggering a full re-render - if (game.user.isGM && !this.item.system.gmNotes) { - const description = this.element.querySelector('[name="system.description"]'); - const addButton = () => { - if (description.querySelector('[data-action=editGMNote]')) return; - - const button = document.createElement('button'); - button.type = 'button'; - button.classList.add('icon', 'toggle', 'fa-regular', 'fa-note-medical'); - button.dataset.action = 'editGMNote'; - button.dataset.tooltip = 'DAGGERHEART.ITEMS.Base.addGMNote'; - description.appendChild(button); - } - - addButton(); - description.addEventListener('close', () => addButton()); - } - } } diff --git a/module/applications/sidebar/tabs/actorDirectory.mjs b/module/applications/sidebar/tabs/actorDirectory.mjs index 4d00afa2..a6f48b54 100644 --- a/module/applications/sidebar/tabs/actorDirectory.mjs +++ b/module/applications/sidebar/tabs/actorDirectory.mjs @@ -1,6 +1,6 @@ export default class DhActorDirectory extends foundry.applications.sidebar.tabs.ActorDirectory { static DEFAULT_OPTIONS = { - renderUpdateKeys: ['system.levelData.level.current', 'system.partner', 'system.tier', 'system.type'] + renderUpdateKeys: ['system.levelData.level.current', 'system.partner', 'system.tier'] }; static _entryPartial = 'systems/daggerheart/templates/ui/sidebar/actor-document-partial.hbs'; diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 5fb61857..199ee87d 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -1,7 +1,6 @@ import { enrichedDualityRoll } from '../../enrichers/DualityRollEnricher.mjs'; import { enrichedFateRoll, getFateTypeData } from '../../enrichers/FateRollEnricher.mjs'; import { getCommandTarget, rollCommandToJSON } from '../../helpers/utils.mjs'; -import FearTracker from './fearTracker.mjs'; export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog { constructor(options) { @@ -111,7 +110,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo const message = game.messages.get(li.dataset.messageId); return message.system.hasRoll && (game.user.isGM || message.isAuthor); }, - onClick: async (_event, li) => { + callback: async li => { const message = game.messages.get(li.dataset.messageId); const reroll = await message.rolls[0].reroll({ liveRoll: true }); message.update({ rolls: [reroll] }); @@ -127,7 +126,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo : false; return (game.user.isGM || message.isAuthor) && hasRolledDamage; }, - onClick: async (_event, li) => { + callback: async li => { const message = game.messages.get(li.dataset.messageId); const update = await message.system.getRerolledDamage(); message.update(update); @@ -153,9 +152,6 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo html.querySelectorAll('.risk-it-all-button').forEach(element => element.addEventListener('click', event => this.riskItAllClearStressAndHitPoints(event, data)) ); - for (const element of html.querySelectorAll('.roll-reload-check')) { - element.addEventListener('click', event => this.onRollReloadCheck(event, message)); - } }; setupHooks() { @@ -183,15 +179,28 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo } async onRollSimple(event, message) { - const buttonType = event.target.dataset.type ?? 'damage'; - const total = message.rolls.reduce((a, c) => a + Roll.fromJSON(c).total, 0); - const targets = Array.from(game.user.targets); + const buttonType = event.target.dataset.type ?? 'damage', + total = message.rolls.reduce((a, c) => a + Roll.fromJSON(c).total, 0), + damages = { + hitPoints: { + parts: [ + { + applyTo: 'hitPoints', + damageTypes: [], + total + } + ] + } + }, + targets = Array.from(game.user.targets); + if (targets.length === 0) return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected')); - for (const target of targets) { - if (buttonType === 'healing') target.actor.takeHealing({ hitPoints: total }); - else target.actor.takeDamage({ total }); - } + + targets.forEach(target => { + if (buttonType === 'healing') target.actor.takeHealing(damages); + else target.actor.takeDamage(damages); + }); } async abilityUseButton(event, message) { @@ -247,17 +256,26 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo } const message = game.messages.get(messageData._id); - const target = event.target.closest('[data-result]'); + const target = event.target.closest('[data-die-index]'); if (target.dataset.type === 'damage') { - const { isResource, damageType, dice, result } = target.dataset; - await message.system.damage.rerollDamageDie(isResource, damageType, dice, result); - - const updatePath = isResource ? `system.damage.resources.${damageType}` : 'system.damage.main'; - const updateValue = isResource ? - message.system.damage.resources[damageType] : message.system.damage.main; - await message.update({ - [updatePath]: updateValue.toJSON() + const { damageType, part, dice, result } = target.dataset; + const damagePart = message.system.damage[damageType].parts[part]; + const { parsedRoll, rerolledDice } = await game.system.api.dice.DamageRoll.reroll(damagePart, dice, result); + const damageParts = message.system.damage[damageType].parts.map((damagePart, index) => { + if (index !== Number(part)) return damagePart; + return { + ...damagePart, + total: parsedRoll.total, + dice: rerolledDice + }; + }); + const updateMessage = game.messages.get(message._id); + await updateMessage.update({ + [`system.damage.${damageType}`]: { + total: parsedRoll.total, + parts: damageParts + } }); } else { const rerollDice = message.system.roll.dice[target.dataset.dieIndex]; @@ -279,27 +297,4 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo const actor = game.actors.get(event.target.dataset.actorId); new game.system.api.applications.dialogs.RiskItAllDialog(actor, resourceValue).render({ force: true }); } - - _toggleNotifications({ closing = false } = {}) { - super._toggleNotifications(closing) - FearTracker.handleOffSet(); - } - - async onRollReloadCheck(_event, messageData) { - const message = game.messages.get(messageData._id); - - if (message.system.reloadCheckValue) { - const confirmed = await foundry.applications.api.DialogV2.confirm({ - window: { - title: _loc('DAGGERHEART.ACTIONS.Reload.rerollConfirmationTitle') - }, - content: _loc('DAGGERHEART.ACTIONS.Reload.rerollConfirmationText') - }); - - if (!confirmed) return; - } - - const { rollValue } = await message.system.action.handleReload?.({ awaitRoll: true }); - await message.update({ 'system.reloadCheckValue': rollValue }); - } } diff --git a/module/applications/ui/countdownEdit.mjs b/module/applications/ui/countdownEdit.mjs index af1af46b..5974e1f2 100644 --- a/module/applications/ui/countdownEdit.mjs +++ b/module/applications/ui/countdownEdit.mjs @@ -35,7 +35,7 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio static PARTS = { countdowns: { - template: 'systems/daggerheart/templates/ui/countdowns/countdown-edit.hbs', + template: 'systems/daggerheart/templates/ui/countdown-edit.hbs', scrollable: ['.expanded-view', '.edit-content'] } }; @@ -45,7 +45,7 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio context.isGM = game.user.isGM; context.ownershipDefaultOptions = CONFIG.DH.GENERAL.basicOwnershiplevels; context.defaultOwnership = this.data.defaultOwnership; - context.countdownTypes = CONFIG.DH.GENERAL.countdownTypes; + context.countdownBaseTypes = CONFIG.DH.GENERAL.countdownBaseTypes; context.countdownProgressionTypes = CONFIG.DH.GENERAL.countdownProgressionTypes; context.countdownLoopingTypes = CONFIG.DH.GENERAL.countdownLoopingTypes; context.hideNewCountdowns = this.hideNewCountdowns; @@ -62,7 +62,7 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio const randomizeValid = !new Roll(countdown.progress.startFormula ?? '').isDeterministic; acc[key] = { ...countdown, - typeName: game.i18n.localize(CONFIG.DH.GENERAL.countdownTypes[countdown.type].label), + typeName: game.i18n.localize(CONFIG.DH.GENERAL.countdownBaseTypes[countdown.type].label), progress: { ...countdown.progress, typeName: game.i18n.localize( @@ -153,6 +153,7 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio action: socketEvent.Refresh, data: { refreshType: RefreshType.Countdown } }); + Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown }); } static #addCountdown() { diff --git a/module/applications/ui/countdowns.mjs b/module/applications/ui/countdowns.mjs index 996a46ea..2a2a113e 100644 --- a/module/applications/ui/countdowns.mjs +++ b/module/applications/ui/countdowns.mjs @@ -11,12 +11,10 @@ const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; */ export default class DhCountdowns extends HandlebarsApplicationMixin(ApplicationV2) { - previousCountdownData = null; - constructor(options = {}) { super(options); - this.previousCountdownData = - game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns).countdowns; + + this.setupHooks(); } /** @inheritDoc */ @@ -34,7 +32,6 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application }, actions: { toggleViewMode: DhCountdowns.#onToggleViewMode, - toggleCountdownTypes: DhCountdowns.#onToggleCountdownTypes, editCountdowns: DhCountdowns.#onEditCountdowns, loopCountdown: DhCountdowns.#onLoopCountdown, decreaseCountdown: (_, target) => this.editCountdown(false, target), @@ -51,20 +48,11 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application static PARTS = { resources: { root: true, - template: 'systems/daggerheart/templates/ui/countdowns/countdowns-view.hbs' + template: 'systems/daggerheart/templates/ui/countdowns.hbs' } }; - /** - * Returns all visible countdown types - * @returns {string[]} - */ - get visibleCountdownTypes() { - const { encounter, narrative } = CONFIG.DH.GENERAL.countdownTypes; - return game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes) - ?? [encounter.id, narrative.id]; - } - + /**@inheritdoc */ async _renderFrame(options) { const frame = await super._renderFrame(options); @@ -77,78 +65,29 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application return frame; } - /** @inheritdoc */ - async _onFirstRender(context, options) { - await super._onFirstRender(context, options); - this._createContextMenu(this._getCountdownContextOptions, '.countdown-container[data-countdown]', { - parentClassHooks: false, fixed: true - }); - } - - /** @inheritdoc */ - async _onRender(context, options) { - await super._onRender(context, options); - - /* Handle rendering/hiding/positioning of the countdown UI */ - this.element.hidden = !game.user.isGM && this.#getCountdowns().length === 0; - if (options?.force) { - document.getElementById('ui-right-column-1')?.appendChild(this.element); - } - - this.previousCountdownData = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns) - .countdowns; - - /* Handle animations to draw attention to countdown values changing */ - const typesToAnimate = new Set(); - for (const countdownKey of options.animate ?? []) { - const shimmerAnimation = [ - { backgroundPositionX: '98%' }, - { backgroundPositionX: '0%' } - ]; - const shimmerTiming = { - duration: 1000, - iterations: 1 - }; - - const element = this.element.querySelector(`.countdown-container[data-countdown="${countdownKey}"]`); - element?.animate(shimmerAnimation, shimmerTiming); - - const countdown = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns) - .countdowns[countdownKey]; - if (!this.visibleCountdownTypes.includes(countdown?.type)) - typesToAnimate.add(countdown.type); - } - - for (const type of typesToAnimate) { - const pulseAnimation = [ - { boxShadow: '0 0 1px 1px var(--golden)' }, - { boxShadow: '0 0 2px 2px var(--golden)' } - ]; - const pulseTiming = { - duration: 1000, - iterations: 3 - }; - - const element = this.element.querySelector(`.header-type-toggles .header-type[data-type="${type}"]`); - element?.animate(pulseAnimation, pulseTiming); - } - } - /** Returns countdown data filtered by ownership */ #getCountdowns() { const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); const values = Object.entries(setting.countdowns).map(([key, countdown]) => ({ key, countdown, - ownership: countdown.getUserLevel(game.user) + ownership: DhCountdowns.#getPlayerOwnership(game.user, setting, countdown) })); return values.filter(v => v.ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE); } - _getCountdownData() { - return this.#getCountdowns().reduce((acc, { key, countdown, ownership }) => { + /** @override */ + async _prepareContext(options) { + const context = await super._prepareContext(options); + context.isGM = game.user.isGM; + + context.iconOnly = + game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode) === + CONFIG.DH.GENERAL.countdownAppMode.iconOnly; + const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); + context.countdowns = this.#getCountdowns().reduce((acc, { key, countdown, ownership }) => { const playersWithAccess = game.users.reduce((acc, user) => { - const ownership = countdown.getUserLevel(user); + const ownership = DhCountdowns.#getPlayerOwnership(user, setting, countdown); if (!user.isGM && ownership && ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) { acc.push(user); } @@ -169,7 +108,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application !countdownEditable || (isLooping && (countdown.progress.current > 0 || countdown.progress.start === '0')); - acc[countdown.type][key] = { + acc[key] = { ...countdown, editable: countdownEditable, noPlayerAccess: nonGmPlayers.length && playersWithAccess.length === 0, @@ -178,42 +117,24 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application loopTooltip: isLooping && game.i18n.localize(loopTooltip) }; return acc; - }, Object.keys(CONFIG.DH.GENERAL.countdownTypes).reduce((acc, key) => { - acc[key] = {}; - return acc; - }, {})); - } - - /** @override */ - async _prepareContext(options) { - const context = await super._prepareContext(options); - context.isGM = game.user.isGM; - - context.iconOnly = - game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode) - === CONFIG.DH.GENERAL.countdownAppMode.iconOnly; - - context.userCountdownTypes = this.visibleCountdownTypes; - - context.typeToggles = - Object.values(CONFIG.DH.GENERAL.countdownTypes).map(type => ({ - type: type.id, - label: game.i18n.localize(type.shortLabel), - active: context.userCountdownTypes.includes(type.id) - })); - - context.countdowns = this._getCountdownData(); - context.countdownTypesWithVisibleEntries = this.#getCountdowns().reduce((acc, data) => { - if (context.userCountdownTypes.includes(data.countdown.type) && !acc.includes(data.countdown.type)) - acc.push(data.countdown.type); - - return acc; - }, []); - + }, {}); return context; } + static #getPlayerOwnership(user, setting, countdown) { + if (user.isGM) return CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER; + + const playerOwnership = countdown.ownership[user.id]; + return playerOwnership === undefined || playerOwnership === CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT + ? setting.defaultOwnership + : playerOwnership; + } + + cooldownRefresh = ({ refreshType }) => { + if (refreshType === RefreshType.Countdown) this.render(); + }; + static canPerformEdit() { if (game.user.isGM) return true; @@ -226,7 +147,6 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application return true; } - /** @this {DhCountdowns} */ static async #onToggleViewMode() { const currentMode = game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode); const appMode = CONFIG.DH.GENERAL.countdownAppMode; @@ -238,24 +158,10 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application this.render(); } - /** @this {DhCountdowns} */ - static async #onToggleCountdownTypes(event, target) { - const currentTypes = this.visibleCountdownTypes; - const { type } = target.dataset; - const newTypes = event.shiftKey ? - [type] : - currentTypes.includes(type) ? currentTypes.filter(x => x !== type) : [...currentTypes, type]; - await game.user.setFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes, newTypes); - - this.render(); - } - - /** @this {DhCountdowns} */ static async #onEditCountdowns() { new game.system.api.applications.ui.CountdownEdit().render(true); } - /** @this {DhCountdowns} */ static async #onLoopCountdown(_, target) { if (!DhCountdowns.canPerformEdit()) return; @@ -311,12 +217,18 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application action: socketEvent.Refresh, data: { refreshType: RefreshType.Countdown } }); + Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown }); + } + + setupHooks() { + Hooks.on(socketEvent.Refresh, this.cooldownRefresh.bind()); } async close(options) { /* Opt out of Foundry's standard behavior of closing all application windows marked as UI when Escape is pressed */ if (options.closeKey) return; + Hooks.off(socketEvent.Refresh, this.cooldownRefresh); return super.close(options); } @@ -324,31 +236,29 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application * Sends updates of the countdowns to the GM player. Since this is asynchronous, be sure to * update all the countdowns at the same time. * - * @param {...(string | { type: string; undo?: boolean })} progressTypes Countdowns to be updated + * @param {...any} progressTypes Countdowns to be updated */ static async updateCountdowns(...progressTypes) { - progressTypes = progressTypes.map(p => typeof p === 'string' ? { type: p } : p); const { countdownAutomation } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); if (!countdownAutomation) return; const countdownSetting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); const updatedCountdowns = Object.keys(countdownSetting.countdowns).reduce((acc, key) => { const countdown = countdownSetting.countdowns[key]; - const progressData = progressTypes.find(x => x.type === countdown.progress.type); - if (progressData && countdown.progress.current > 0) { - acc[key] = { value: progressData.undo ? 1 : -1 }; + if (progressTypes.indexOf(countdown.progress.type) !== -1 && countdown.progress.current > 0) { + acc.push(key); } return acc; - }, {}); + }, []); const countdownData = countdownSetting.toObject(); const settings = { ...countdownData, countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => { const countdown = foundry.utils.deepClone(countdownData.countdowns[key]); - if (updatedCountdowns[key]) { - countdown.progress.current += updatedCountdowns[key].value; + if (updatedCountdowns.includes(key)) { + countdown.progress.current -= 1; } acc[key] = countdown; @@ -360,29 +270,11 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application }); } - /** - * @returns {import('@client/applications/ux/context-menu.mjs').ContextMenuEntry[]} - */ - _getCountdownContextOptions() { - /** @param {HTMLElement} element */ - const getCountdownFromElement = element => { - const id = element.closest('[data-countdown]').dataset.countdown; - if (!id) return null; - const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); - return setting.countdowns[id ?? '']; + async _onRender(context, options) { + await super._onRender(context, options); + this.element.hidden = !game.user.isGM && this.#getCountdowns().length === 0; + if (options?.force) { + document.getElementById('ui-right-column-1')?.appendChild(this.element); } - - return [ - { - label: 'CONTROLS.CommonDelete', - icon: 'fa-solid fa-trash', - visible: element => { - return getCountdownFromElement(element)?.isOwner; - }, - onClick: (_, target) => { - getCountdownFromElement(target)?.delete(); - } - } - ]; } } diff --git a/module/applications/ui/effectsDisplay.mjs b/module/applications/ui/effectsDisplay.mjs index c9739f56..a64b1b22 100644 --- a/module/applications/ui/effectsDisplay.mjs +++ b/module/applications/ui/effectsDisplay.mjs @@ -39,12 +39,6 @@ export default class DhEffectsDisplay extends HandlebarsApplicationMixin(Applica } }; - /** - * Debounce and slightly delayed request to re-render this panel. Necessary for situations where it is not possible - * to properly wait for promises to resolve before refreshing the UI. - */ - refresh = foundry.utils.debounce(this.render.bind(this), 50); - get element() { return document.body.querySelector('.daggerheart.dh-style.effects-display'); } diff --git a/module/applications/ui/fearTracker.mjs b/module/applications/ui/fearTracker.mjs index d1813736..8c247f79 100644 --- a/module/applications/ui/fearTracker.mjs +++ b/module/applications/ui/fearTracker.mjs @@ -13,14 +13,6 @@ const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV2) { constructor(options = {}) { super(options); - - this._dragData = { - isDragging: false, - startX: 0, - startY: 0, - startLeft: 0, - startTop: 0 - } } /** @inheritDoc */ @@ -29,20 +21,19 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV classes: [], tag: 'div', window: { - frame: false, + frame: true, title: 'DAGGERHEART.GENERAL.fear', positioned: true, resizable: true, minimizable: false }, - classes: ['daggerheart', 'dh-style', 'fear-tracker'], actions: { setFear: FearTracker.setFear, increaseFear: FearTracker.increaseFear }, position: { - width: 540, - height: 'auto' + width: 222, + height: 222 } }; @@ -62,10 +53,6 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV return game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxFear; } - get fearPosition() { - return game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance).fearPosition; - } - /* -------------------------------------------- */ /* Rendering */ /* -------------------------------------------- */ @@ -76,48 +63,15 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV current = this.currentFear, max = this.maxFear, percent = (current / max) * 100, - isGM = game.user.isGM, - locked = false, - isFree = this.fearPosition == 'free'; + isGM = game.user.isGM; - return { display, current, max, percent, isGM, locked, isFree }; + return { display, current, max, percent, isGM }; } /** @override */ - async _onRender(context, options) { - await super._onRender(context, options); - - this.#setupDragging(); - this.#setupResizing(); - - const fearPosition = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance).fearPosition; - - if (options.isFirstRender) FearTracker.handleOffSet(); - if (!options.force) return; - - this.handleStyleElement(fearPosition); - - switch (fearPosition) { - case 'topCenter': - document.getElementById('ui-top')?.appendChild(this.element); - break; - case 'bottomCenter': - document.getElementById('ui-bottom')?.prepend(this.element); - break; - case 'rightTop': - document.getElementById('ui-right-column-1')?.appendChild(this.element); - break; - case 'leftBottom': - document.getElementById('ui-left-column-1')?.insertBefore(this.element, document.getElementById('players')); - break; - - default: - document.body?.appendChild(this.element); - const position = - game.user.getFlag(CONFIG.DH.id, 'app.resources.position') ?? FearTracker.DEFAULT_OPTIONS.position; - this.setPosition(position); - break; - } + async _preFirstRender(context, options) { + options.position = + game.user.getFlag(CONFIG.DH.id, 'app.resources.position') ?? FearTracker.DEFAULT_OPTIONS.position; } /** @override */ @@ -126,31 +80,15 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear, this.maxFear); } - handleStyleElement(fearPosition) { - for (const position of Object.values(CONFIG.DH.GENERAL.fearPosition)) { - this.element.classList.remove(position.value); - } - - this.element.classList.add(fearPosition); - } - - static handleOffSet() { - const fearTracker = document.getElementById('resources'); - const hotbar = document.getElementById('hotbar'); - - if (!fearTracker) return; - - const offset = Number(hotbar.style.getPropertyValue('--offset').replace(/px$/, '')) || 0; - - if (offset > 0) return; - - fearTracker.style.setProperty('--offset', `${offset - 13}px`); - } - _onPosition(position) { game.user.setFlag(CONFIG.DH.id, 'app.resources.position', position); } + async close(options = {}) { + if (!options.allowed) return; + else super.close(options); + } + static async setFear(event, target) { if (!game.user.isGM) return; const fearCount = Number(target.dataset.index ?? 0); @@ -172,119 +110,4 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV value ); } - - // TODO: Remove methods later to use Foundry's dragger and resize methods - /* -------------------------------------------- */ - /* Dragging handlers */ - /* -------------------------------------------- */ - #setupDragging() { - const dragHandle = this.element.querySelector('.drag-handle'); - if (!dragHandle) return; - dragHandle.addEventListener('mousedown', this.#onDragStart.bind(this)); - } - - #onDragStart(event) { - if (event.button !== 0) return; - this._dragData.isDragging = true; - this._dragData.startX = event.clientX; - this._dragData.startY = event.clientY; - const rect = this.element.getBoundingClientRect(); - this._dragData.startLeft = rect.left; - this._dragData.startTop = rect.top; - this.element.style.cursor = 'grabbing'; - - this._dragHandler = this.#onDragging.bind(this); - this._dragEndHandler = this.#onDragEnd.bind(this); - window.addEventListener('mousemove', this._dragHandler); - window.addEventListener('mouseup', this._dragEndHandler); - } - - #onDragging(event) { - if (!this._dragData.isDragging) return; - - const dragX = event.clientX - this._dragData.startX; - const dragY = event.clientY - this._dragData.startY; - - this.element.style.left = `${this._dragData.startLeft + dragX}px`; - this.element.style.top = `${this._dragData.startTop + dragY}px`; - } - - #onDragEnd() { - if (!this._dragData.isDragging) return; - this._dragData.isDragging = false; - this.element.style.cursor = ''; - - if (this._dragHandler) window.removeEventListener('mousemove', this._dragHandler); - if (this._dragEndHandler) window.removeEventListener('mouseup', this._dragEndHandler); - - const rect = this.element.getBoundingClientRect(); - const pos = { top: rect.top, left: rect.left }; - - this.setPosition(pos); - } - - /* -------------------------------------------- */ - /* Resize handlers */ - /* -------------------------------------------- */ - - #setupResizing() { - const resizeHandle = this.element.querySelector('.resize-handle'); - if (!resizeHandle) return; - resizeHandle.addEventListener('mousedown', this.#onResizeStart.bind(this)); - } - - #onResizeStart(e) { - if (e.button !== 0) return; - e.stopPropagation(); - - let maxAllowedWidth = 10000; - - this._resizeData = { - isResizing: true, - startX: e.clientX, - startY: e.clientY, - startWidth: this.element.offsetWidth, - startHeight: this.element.offsetHeight, - maxAllowedWidth: Math.max(50, maxAllowedWidth) - }; - - this._resizeHandler = this.#onResizing.bind(this); - this._resizeEndHandler = this.#onResizeEnd.bind(this); - window.addEventListener('mousemove', this._resizeHandler); - window.addEventListener('mouseup', this._resizeEndHandler); - } - - #onResizing(e) { - if (!this._resizeData?.isResizing) return; - - const currentDx = e.clientX - this._resizeData.startX; - const potentialWidth = Math.max(50, this._resizeData.startWidth + currentDx); - - const width = Math.min(potentialWidth, this._resizeData.maxAllowedWidth); - - this.element.style.width = `${width}px`; - - if (width < 100) { - this.element.classList.add('narrow'); - } else { - this.element.classList.remove('narrow'); - } - } - - #onResizeEnd() { - if (!this._resizeData?.isResizing) return; - this._resizeData.isResizing = false; - - if (this._resizeHandler) window.removeEventListener('mousemove', this._resizeHandler); - if (this._resizeEndHandler) window.removeEventListener('mouseup', this._resizeEndHandler); - - let width = parseFloat(this.element.style.width); - - - if (isNaN(width)) { - width = this.element.getBoundingClientRect().width; - } - - this.setPosition({ width: width }); - } } diff --git a/module/canvas/placeables/regionLayer.mjs b/module/canvas/placeables/regionLayer.mjs index b71ccc3f..684fdd5e 100644 --- a/module/canvas/placeables/regionLayer.mjs +++ b/module/canvas/placeables/regionLayer.mjs @@ -96,7 +96,7 @@ export default class DhRegionLayer extends foundry.canvas.layers.RegionLayer { return inBounds.length === 1 ? inBounds[0] : null; } - static getTemplateShape({ shapeType, angle, range, direction, hasHole } = {}) { + static getTemplateShape({ type, angle, range, direction } = {}) { const { line, rectangle, inFront, cone, circle, emanation } = CONFIG.DH.GENERAL.templateTypes; /* Length calculation */ @@ -112,11 +112,11 @@ export default class DhRegionLayer extends foundry.canvas.layers.RegionLayer { const shapeData = { ...canvas.mousePosition, - type: shapeType, + type: type, direction: direction ?? 0 }; - switch (shapeType) { + switch (type) { case rectangle.id: shapeData.width = length; shapeData.height = length; @@ -145,8 +145,7 @@ export default class DhRegionLayer extends foundry.canvas.layers.RegionLayer { y: 0, width: 1, height: 1, - shape: game.canvas.grid.isHexagonal ? CONST.TOKEN_SHAPES.ELLIPSE_1 : CONST.TOKEN_SHAPES.RECTANGLE_1, - hole: hasHole + shape: game.canvas.grid.isHexagonal ? CONST.TOKEN_SHAPES.ELLIPSE_1 : CONST.TOKEN_SHAPES.RECTANGLE_1 }; break; } diff --git a/module/config/actionConfig.mjs b/module/config/actionConfig.mjs index e413a828..a6c04e18 100644 --- a/module/config/actionConfig.mjs +++ b/module/config/actionConfig.mjs @@ -119,10 +119,6 @@ export const advantageState = { export const areaTypes = { placed: { id: 'placed', - label: 'DAGGERHEART.CONFIG.AreaTypes.placed.label' - }, - attached: { - id: 'attached', - label: 'DAGGERHEART.CONFIG.AreaTypes.attached.label' + label: 'Placed Area' } }; diff --git a/module/config/encounterConfig.mjs b/module/config/encounterConfig.mjs index 6ea03fcf..4e0f8a6e 100644 --- a/module/config/encounterConfig.mjs +++ b/module/config/encounterConfig.mjs @@ -90,20 +90,18 @@ export const BPModifiers = { name: 'DAGGERHEART.CONFIG.BPModifiers.increaseDamage.effect.name', description: 'DAGGERHEART.CONFIG.BPModifiers.increaseDamage.effect.description', img: 'icons/magic/control/buff-flight-wings-red.webp', - system: { - changes: [ - { - key: 'system.bonuses.damage.physical.dice', - type: 'add', - value: '1d4' - }, - { - key: 'system.bonuses.damage.magical.dice', - type: 'add', - value: '1d4' - } - ] - } + changes: [ + { + key: 'system.bonuses.damage.physical.dice', + mode: 2, + value: '1d4' + }, + { + key: 'system.bonuses.damage.magical.dice', + mode: 2, + value: '1d4' + } + ] } ] } diff --git a/module/config/flagsConfig.mjs b/module/config/flagsConfig.mjs index cb05bd72..817ac89d 100644 --- a/module/config/flagsConfig.mjs +++ b/module/config/flagsConfig.mjs @@ -24,8 +24,7 @@ export const itemAttachmentSource = 'attachmentSource'; export const userFlags = { welcomeMessage: 'welcome-message', - countdownMode: 'countdown-mode', - countdownTypeModes: 'countdown-type-modes' + countdownMode: 'countdown-mode' }; export const combatToggle = 'combat-toggle-origin'; diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 3876f6b5..6fc85ec5 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -825,7 +825,7 @@ export const refreshTypes = { export const itemAbilityCosts = { resource: { id: 'resource', - label: 'DAGGERHEART.GENERAL.Resource.single', + label: 'DAGGERHEART.GENERAL.resource', group: 'Global' }, quantity: { @@ -867,27 +867,27 @@ export const abilityCosts = { export const countdownProgressionTypes = { actionRoll: { id: 'actionRoll', - label: 'DAGGERHEART.CONFIG.CountdownProgressType.actionRoll' + label: 'DAGGERHEART.CONFIG.CountdownType.actionRoll' }, characterAttack: { id: 'characterAttack', - label: 'DAGGERHEART.CONFIG.CountdownProgressType.characterAttack' + label: 'DAGGERHEART.CONFIG.CountdownType.characterAttack' }, characterSpotlight: { id: 'characterSpotlight', - label: 'DAGGERHEART.CONFIG.CountdownProgressType.characterSpotlight' + label: 'DAGGERHEART.CONFIG.CountdownType.characterSpotlight' }, custom: { id: 'custom', - label: 'DAGGERHEART.CONFIG.CountdownProgressType.custom' + label: 'DAGGERHEART.CONFIG.CountdownType.custom' }, fear: { id: 'fear', - label: 'DAGGERHEART.CONFIG.CountdownProgressType.fear' + label: 'DAGGERHEART.CONFIG.CountdownType.fear' }, spotlight: { id: 'spotlight', - label: 'DAGGERHEART.CONFIG.CountdownProgressType.spotlight' + label: 'DAGGERHEART.CONFIG.CountdownType.spotlight' } }; export const rollTypes = { @@ -924,14 +924,6 @@ export const fearDisplay = { hide: { value: 'hide', label: 'DAGGERHEART.SETTINGS.Appearance.fearDisplay.hide' } }; -export const fearPosition = { - free: { value: 'free', label: 'DAGGERHEART.SETTINGS.Appearance.fearPosition.free' }, - topCenter: { value: 'topCenter', label: 'DAGGERHEART.SETTINGS.Appearance.fearPosition.topCenter' }, - bottomCenter: { value: 'bottomCenter', label: 'DAGGERHEART.SETTINGS.Appearance.fearPosition.bottomCenter' }, - rightTop: { value: 'rightTop', label: 'DAGGERHEART.SETTINGS.Appearance.fearPosition.rightTop' }, - leftBottom: { value: 'leftBottom', label: 'DAGGERHEART.SETTINGS.Appearance.fearPosition.leftBottom' } -}; - export const basicOwnershiplevels = { 0: { value: 0, label: 'OWNERSHIP.NONE' }, 2: { value: 2, label: 'OWNERSHIP.OBSERVER' }, @@ -943,6 +935,17 @@ export const simpleOwnershiplevels = { ...basicOwnershiplevels }; +export const countdownBaseTypes = { + narrative: { + id: 'narrative', + label: 'DAGGERHEART.APPLICATIONS.Countdown.types.narrative' + }, + encounter: { + id: 'encounter', + label: 'DAGGERHEART.APPLICATIONS.Countdown.types.encounter' + } +}; + export const countdownLoopingTypes = { noLooping: { id: 'noLooping', @@ -967,19 +970,6 @@ export const countdownAppMode = { iconOnly: 'icon-only' }; -export const countdownTypes = { - encounter: { - id: 'encounter', - label: 'DAGGERHEART.CONFIG.CountdownType.encounter.label', - shortLabel: 'DAGGERHEART.CONFIG.CountdownType.encounter.shortLabel' - }, - narrative: { - id: 'narrative', - label: 'DAGGERHEART.CONFIG.CountdownType.narrative.label', - shortLabel: 'DAGGERHEART.CONFIG.CountdownType.narrative.shortLabel' - } -}; - export const sceneRangeMeasurementSetting = { disable: { id: 'disable', diff --git a/module/config/itemConfig.mjs b/module/config/itemConfig.mjs index 61ed3703..43054ec5 100644 --- a/module/config/itemConfig.mjs +++ b/module/config/itemConfig.mjs @@ -37,15 +37,13 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.channeling.effects.channeling.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.channeling.effects.channeling.description', img: 'icons/magic/symbols/rune-sigil-horned-blue.webp', - system: { - changes: [ - { - key: 'system.bonuses.roll.spellcast', - type: 'add', - value: '1' - } - ] - } + changes: [ + { + key: 'system.bonuses.roll.spellcast', + mode: 2, + value: '1' + } + ] } ] }, @@ -57,45 +55,43 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.difficult.effects.difficult.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.difficult.effects.difficult.description', img: 'icons/magic/control/buff-flight-wings-red.webp', - system: { - changes: [ - { - key: 'system.traits.agility.value', - type: 'add', - value: '-1' - }, - { - key: 'system.traits.strength.value', - type: 'add', - value: '-1' - }, - { - key: 'system.traits.finesse.value', - type: 'add', - value: '-1' - }, - { - key: 'system.traits.instinct.value', - type: 'add', - value: '-1' - }, - { - key: 'system.traits.presence.value', - type: 'add', - value: '-1' - }, - { - key: 'system.traits.knowledge.value', - type: 'add', - value: '-1' - }, - { - key: 'system.evasion', - type: 'add', - value: '-1' - } - ] - } + changes: [ + { + key: 'system.traits.agility.value', + mode: 2, + value: '-1' + }, + { + key: 'system.traits.strength.value', + mode: 2, + value: '-1' + }, + { + key: 'system.traits.finesse.value', + mode: 2, + value: '-1' + }, + { + key: 'system.traits.instinct.value', + mode: 2, + value: '-1' + }, + { + key: 'system.traits.presence.value', + mode: 2, + value: '-1' + }, + { + key: 'system.traits.knowledge.value', + mode: 2, + value: '-1' + }, + { + key: 'system.evasion', + mode: 2, + value: '-1' + } + ] } ] }, @@ -107,15 +103,13 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.flexible.effects.flexible.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.flexible.effects.flexible.description', img: 'icons/magic/movement/abstract-ribbons-red-orange.webp', - system: { - changes: [ - { - key: 'system.evasion', - type: 'add', - value: '1' - } - ] - } + changes: [ + { + key: 'system.evasion', + mode: 2, + value: '1' + } + ] } ] }, @@ -127,15 +121,13 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.fortified.effects.fortified.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.fortified.effects.fortified.description', img: 'icons/magic/defensive/shield-barrier-glowing-blue.webp', - system: { - changes: [ - { - key: 'system.rules.damageReduction.increasePerArmorMark', - type: 'override', - value: '2' - } - ] - } + changes: [ + { + key: 'system.rules.damageReduction.increasePerArmorMark', + mode: 5, + value: '2' + } + ] } ] }, @@ -147,15 +139,13 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.gilded.effects.gilded.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.gilded.effects.gilded.description', img: 'icons/magic/control/control-influence-crown-gold.webp', - system: { - changes: [ - { - key: 'system.traits.presence.value', - type: 'add', - value: '1' - } - ] - } + changes: [ + { + key: 'system.traits.presence.value', + mode: 2, + value: '1' + } + ] } ] }, @@ -167,15 +157,13 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.heavy.effects.heavy.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.heavy.effects.heavy.description', img: 'icons/commodities/metal/ingot-worn-iron.webp', - system: { - changes: [ - { - key: 'system.evasion', - type: 'add', - value: '-1' - } - ] - } + changes: [ + { + key: 'system.evasion', + mode: 2, + value: '-1' + } + ] } ] }, @@ -224,15 +212,13 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.magical.effects.magical.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.magical.effects.magical.description', img: 'icons/magic/defensive/barrier-shield-dome-blue-purple.webp', - system: { - changes: [ - { - key: 'system.rules.damageReduction.magical', - type: 'override', - value: 1 - } - ] - } + changes: [ + { + key: 'system.rules.damageReduction.magical', + mode: 5, + value: 1 + } + ] } ] }, @@ -263,15 +249,13 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.physical.effects.physical.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.physical.effects.physical.description', img: 'icons/commodities/stone/ore-pile-tan.webp', - system: { - changes: [ - { - key: 'system.rules.damageReduction.physical', - type: 'override', - value: 1 - } - ] - } + changes: [ + { + key: 'system.rules.damageReduction.physical', + mode: 5, + value: 1 + } + ] } ] }, @@ -296,20 +280,18 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.reinforced.effects.reinforced.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.reinforced.effects.reinforced.description', img: 'icons/magic/defensive/shield-barrier-glowing-triangle-green.webp', - system: { - changes: [ - { - key: 'system.bunuses.damageThresholds.major', - type: 'add', - value: '2' - }, - { - key: 'system.bunuses.damageThresholds.severe', - type: 'add', - value: '2' - } - ] - } + changes: [ + { + key: 'system.bunuses.damageThresholds.major', + mode: 2, + value: '2' + }, + { + key: 'system.bunuses.damageThresholds.severe', + mode: 2, + value: '2' + } + ] } ] }, @@ -344,20 +326,18 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.sharp.effects.sharp.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.sharp.effects.sharp.description', img: 'icons/magic/defensive/shield-barrier-glowing-triangle-green.webp', - system: { - changes: [ - { - key: 'system.bonuses.damage.primaryWeapon.dice', - type: 'add', - value: '1d4' - }, - { - key: 'system.bonuses.damage.secondaryWeapon.dice', - type: 'add', - value: '1d4' - } - ] - } + changes: [ + { + key: 'system.bonuses.damage.primaryWeapon.dice', + mode: 2, + value: '1d4' + }, + { + key: 'system.bonuses.damage.secondaryWeapon.dice', + mode: 2, + value: '1d4' + } + ] } ] }, @@ -428,20 +408,18 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.veryHeavy.effects.veryHeavy.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.veryHeavy.effects.veryHeavy.description', img: 'icons/commodities/metal/ingot-stamped-steel.webp', - system: { - changes: [ - { - key: 'system.evasion', - type: 'add', - value: '-2' - }, - { - key: 'system.traits.agility.value', - type: 'add', - value: '-1' - } - ] - } + changes: [ + { + key: 'system.evasion', + mode: 2, + value: '-2' + }, + { + key: 'system.traits.agility.value', + mode: 2, + value: '-1' + } + ] } ] }, @@ -453,16 +431,14 @@ export const armorFeatures = { name: 'DAGGERHEART.CONFIG.ArmorFeature.warded.effects.warded.name', description: 'DAGGERHEART.CONFIG.ArmorFeature.warded.effects.warded.description', img: 'icons/magic/defensive/barrier-shield-dome-pink.webp', - system: { - changes: [ - { - key: 'system.resistance.magical.reduction', - type: 'add', - value: '@system.armorScore', - priority: 21 - } - ] - } + changes: [ + { + key: 'system.resistance.magical.reduction', + mode: 2, + value: '@system.armorScore', + priority: 21 + } + ] } ] } @@ -512,23 +488,21 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.barrier.effects.barrier.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.barrier.effects.barrier.description', img: 'icons/skills/melee/shield-block-bash-blue.webp', - system: { - changes: [ - { - key: 'system.evasion', - type: 'add', - value: '-1' - }, - { - key: 'Armor', + changes: [ + { + key: 'system.evasion', + mode: 2, + value: '-1' + }, + { + key: 'Armor', + type: 'armor', + typeData: { type: 'armor', - typeData: { - type: 'armor', - max: 'ITEM.@system.tier + 1' - } + max: 'ITEM.@system.tier + 1' } - ] - } + } + ] } ] }, @@ -540,15 +514,13 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.bonded.effects.damage.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.bonded.effects.damage.description', img: 'icons/magic/symbols/chevron-elipse-circle-blue.webp', - system: { - changes: [ - { - key: 'system.bonuses.damage.primaryWeapon.bonus', - type: 'add', - value: '@system.levelData.level.current' - } - ] - } + changes: [ + { + key: 'system.bonuses.damage.primaryWeapon.bonus', + mode: 2, + value: '@system.levelData.level.current' + } + ] } ] }, @@ -581,20 +553,18 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.brave.effects.brave.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.brave.effects.brave.description', img: 'icons/magic/life/heart-cross-strong-flame-purple-orange.webp', - system: { - changes: [ - { - key: 'system.evasion', - type: 'add', - value: '-1' - }, - { - key: 'system.damageThresholds.severe', - type: 'add', - value: 'ITEM.@system.tier' - } - ] - } + changes: [ + { + key: 'system.evasion', + mode: 2, + value: '-1' + }, + { + key: 'system.damageThresholds.severe', + mode: 2, + value: 'ITEM.@system.tier' + } + ] } ] }, @@ -648,15 +618,13 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.charged.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.charged.description', img: 'icons/magic/lightning/claws-unarmed-strike-teal.webp', - system: { - changes: [ - { - key: 'system.proficiency', - type: 'add', - value: '1' - } - ] - } + changes: [ + { + key: 'system.proficiency', + mode: 2, + value: '1' + } + ] } ] } @@ -692,15 +660,13 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.cumbersome.effects.cumbersome.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.cumbersome.effects.cumbersome.description', img: 'icons/commodities/metal/mail-plate-steel.webp', - system: { - changes: [ - { - key: 'system.traits.finesse.value', - type: 'add', - value: '-1' - } - ] - } + changes: [ + { + key: 'system.traits.finesse.value', + mode: 2, + value: '-1' + } + ] } ] }, @@ -741,16 +707,14 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.deflecting.effects.deflecting.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.deflecting.effects.deflecting.description', img: 'icons/skills/melee/hand-grip-sword-strike-orange.webp', - system: { - changes: [ - { - key: 'system.evasion', - type: 'add', - value: '@system.armorScore', - priority: 21 - } - ] - } + changes: [ + { + key: 'system.evasion', + mode: 2, + value: '@system.armorScore', + priority: 21 + } + ] } ] } @@ -790,15 +754,13 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.destructive.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.destructive.effects.agility', img: 'icons/skills/melee/strike-flail-spiked-pink.webp', - system: { - changes: [ - { - key: 'system.traits.agility.value', - type: 'add', - value: '-1' - } - ] - } + changes: [ + { + key: 'system.traits.agility.value', + mode: 2, + value: '-1' + } + ] } ] }, @@ -829,14 +791,14 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.doubleDuty.effects.doubleDuty.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.doubleDuty.effects.doubleDuty.description', img: 'icons/skills/melee/sword-shield-stylized-white.webp', + changes: [ + { + key: 'system.bonuses.damage.primaryWeapon.bonus', + mode: 2, + value: '1' + } + ], system: { - changes: [ - { - key: 'system.bonuses.damage.primaryWeapon.bonus', - type: 'add', - value: '1' - } - ], rangeDependence: { enabled: true, range: 'melee', @@ -940,15 +902,13 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.greedy.actions.greed.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.greedy.actions.greed.description', img: 'icons/commodities/currency/coins-crown-stack-gold.webp', - system: { - changes: [ - { - key: 'system.proficiency', - type: 'add', - value: '1' - } - ] - } + changes: [ + { + key: 'system.proficiency', + mode: 2, + value: '1' + } + ] } ] } @@ -991,15 +951,13 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.heavy.effects.heavy.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.heavy.effects.heavy.description', img: 'icons/commodities/metal/ingot-worn-iron.webp', - system: { - changes: [ - { - key: 'system.evasion', - type: 'add', - value: '-1' - } - ] - } + changes: [ + { + key: 'system.evasion', + mode: 2, + value: '-1' + } + ] } ] }, @@ -1108,15 +1066,13 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.massive.effects.massive.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.massive.effects.massive.description', img: 'icons/skills/melee/strike-flail-destructive-yellow.webp', - system: { - changes: [ - { - key: 'system.evasion', - type: 'add', - value: '-1' - } - ] - } + changes: [ + { + key: 'system.evasion', + mode: 2, + value: '-1' + } + ] } ] }, @@ -1147,14 +1103,14 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.paired.effects.paired.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.paired.effects.paired.description', img: 'icons/skills/melee/weapons-crossed-swords-yellow-teal.webp', + changes: [ + { + key: 'system.bonuses.damage.primaryWeapon.bonus', + mode: 2, + value: 'ITEM.@system.tier + 1' + } + ], system: { - changes: [ - { - key: 'system.bonuses.damage.primaryWeapon.bonus', - type: 'add', - value: 'ITEM.@system.tier + 1' - } - ], rangeDependence: { enabled: true, range: 'melee', @@ -1202,15 +1158,13 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.persuasive.effects.persuasive.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.persuasive.effects.persuasive.description', img: 'icons/magic/control/hypnosis-mesmerism-eye.webp', - system: { - changes: [ - { - key: 'system.traits.presence.value', - type: 'add', - value: '2' - } - ] - } + changes: [ + { + key: 'system.traits.presence.value', + mode: 2, + value: '2' + } + ] } ] } @@ -1249,20 +1203,17 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.protective.effects.protective.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.protective.effects.protective.description', img: 'icons/skills/melee/shield-block-gray-orange.webp', - system: { - changes: [ - { - key: 'Armor', + changes: [ + { + key: 'Armor', + type: 'armor', + value: 0, + typeData: { type: 'armor', - value: 0, - typeData: { - type: 'armor', - max: 'ITEM.@system.tier' - } + max: 'ITEM.@system.tier' } - ] - } - + } + ] } ] }, @@ -1293,15 +1244,13 @@ export const weaponFeatures = { name: 'DAGGERHEART.CONFIG.WeaponFeature.reliable.effects.reliable.name', description: 'DAGGERHEART.CONFIG.WeaponFeature.reliable.effects.reliable.description', img: 'icons/skills/melee/strike-sword-slashing-red.webp', - system: { - changes: [ - { - key: 'system.bonuses.roll.primaryWeapon.bonus', - type: 'add', - value: 1 - } - ] - } + changes: [ + { + key: 'system.bonuses.roll.primaryWeapon.bonus', + mode: 2, + value: 1 + } + ] } ] }, @@ -1392,7 +1341,7 @@ export const weaponFeatures = { changes: [ { key: 'system.bonuses.damage.primaryWeapon.bonus', - type: 'add', + mode: 2, value: '@system.traits.agility.value', priority: 21 } diff --git a/module/config/settingsConfig.mjs b/module/config/settingsConfig.mjs index 92a3361c..50841084 100644 --- a/module/config/settingsConfig.mjs +++ b/module/config/settingsConfig.mjs @@ -27,10 +27,8 @@ export const menu = { }; export const gameSettings = { - /** @type {'Automation'} */ Automation: 'Automation', Metagaming: 'Metagaming', - /** @type {'Homebrew'} */ Homebrew: 'Homebrew', appearance: 'Appearance', GlobalOverrides: 'GlobalOverrides', @@ -39,7 +37,6 @@ export const gameSettings = { Fear: 'ResourcesFear' }, LevelTiers: 'LevelTiers', - /** @type {'Countdowns'} */ Countdowns: 'Countdowns', LastMigrationVersion: 'LastMigrationVersion', SpotlightRequestQueue: 'SpotlightRequestQueue', @@ -62,18 +59,3 @@ export const actionAutomationChoices = { label: 'DAGGERHEART.CONFIG.ActionAutomationChoices.always' } }; - -export const reloadChoices = { - off: { - id: 'off', - label: 'DAGGERHEART.CONFIG.ReloadChoices.off.label' - }, - manual: { - id: 'manual', - label: 'DAGGERHEART.CONFIG.ReloadChoices.manual.label' - }, - auto: { - id: 'auto', - label: 'DAGGERHEART.CONFIG.ReloadChoices.auto.label' - } -}; \ No newline at end of file diff --git a/module/config/system.mjs b/module/config/system.mjs index de6630ec..31dba518 100644 --- a/module/config/system.mjs +++ b/module/config/system.mjs @@ -12,7 +12,6 @@ import * as HOOKS from './hooksConfig.mjs'; import * as TRIGGER from './triggerConfig.mjs'; import * as ITEMBROWSER from './itemBrowserConfig.mjs'; -/** @type {"daggerheart"} */ export const SYSTEM_ID = 'daggerheart'; export const SYSTEM = { diff --git a/module/data/_types.d.ts b/module/data/_types.d.ts deleted file mode 100644 index f0e2ade5..00000000 --- a/module/data/_types.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { DhCountdown } from './countdowns.mjs' - -declare module './countdowns.mjs' { - export default interface DhCountdowns { - countdowns: Record; - } -} \ No newline at end of file diff --git a/module/data/action/attackAction.mjs b/module/data/action/attackAction.mjs index ba11c6ff..1988b1d8 100644 --- a/module/data/action/attackAction.mjs +++ b/module/data/action/attackAction.mjs @@ -13,19 +13,18 @@ export default class DHAttackAction extends DHDamageAction { if (this.damage.includeBase) { const baseDamage = this.getParentHitPointDamage(); if (baseDamage) { - if (!this.damage.main) { - this.damage.main = baseDamage; + if (!this.damage.parts.hitPoints) { + this.damage.parts.hitPoints = baseDamage; } else { - for (const type of baseDamage.type) this.damage.main.type.add(type); + for (const type of baseDamage.type) this.damage.parts.hitPoints.type.add(type); - this.damage.main.value.custom = { + this.damage.parts.hitPoints.value.custom = { enabled: true, - formula: `${baseDamage.value.getFormula()} + ${this.damage.main.value.getFormula()}` + formula: `${baseDamage.value.getFormula()} + ${this.damage.parts.hitPoints.value.getFormula()}` }; } } } - if (this.roll.useDefault) { this.roll.trait = this.item.system.attack.roll.trait; this.roll.type = 'attack'; @@ -34,28 +33,24 @@ export default class DHAttackAction extends DHDamageAction { } getParentHitPointDamage() { - return this.item?.system?.attack.damage.main; + return this.item?.system?.attack.damage.parts.hitPoints; } get damageFormula() { - const hitPointsPart = this.damage.main; + const hitPointsPart = this.damage.parts.hitPoints; if (!hitPointsPart) return '0'; return hitPointsPart.value.getFormula(); } get altDamageFormula() { - const hitPointsPart = this.damage.main; + const hitPointsPart = this.damage.parts.hitPoints; if (!hitPointsPart) return '0'; return hitPointsPart.valueAlt.getFormula(); } async use(event, options) { - if (this.item?.system.needsReload) { - return ui.notifications.error(_loc('DAGGERHEART.UI.Notifications.reloadRequired', { weapon: this.item.name })); - } - const result = await super.use(event, options); if (result?.message?.system.action?.roll?.type === 'attack') { @@ -66,23 +61,6 @@ export default class DHAttackAction extends DHDamageAction { return result; } - async handleReload(options = { awaitRoll: false }) { - const roll = await new Roll('1d6').evaluate(); - if (game.modules.get('dice-so-nice')?.active) { - if (options.awaitRoll) - await game.dice3d.showForRoll(roll, game.user, true); - else - game.dice3d.showForRoll(roll, game.user, true); - } - - const needsReload = roll.total === 1; - if (needsReload) { - this.item.update({ 'system.resource.value': 0 }); - } - - return { needsReload, rollValue: roll.total }; - } - /** * Generate a localized label array for this item subtype. * @returns {(string | { value: string, icons: string[] })[]} An array of localized strings and damage label objects. @@ -95,7 +73,7 @@ export default class DHAttackAction extends DHDamageAction { if (range) labels.push(game.i18n.localize(`DAGGERHEART.CONFIG.Range.${range}.short`)); const useAltDamage = this.actor?.effects?.find(x => x.type === 'horde')?.active; - for (const { value, valueAlt, type } of [damage.main, ...damage.resources].filter(d => !!d)) { + for (const { value, valueAlt, type } of damage.parts) { const usedValue = useAltDamage ? valueAlt : value; const damageString = Roll.replaceFormulaData(usedValue.getFormula(), this.actor?.getRollData() ?? {}); const str = damageString @@ -104,7 +82,7 @@ export default class DHAttackAction extends DHDamageAction { x: game.i18n.localize('DAGGERHEART.GENERAL.damage') }); - const icons = Array.from(type ?? []) + const icons = Array.from(type) .map(t => CONFIG.DH.GENERAL.damageTypes[t]?.icon) .filter(Boolean); diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index 7c783f05..c71f5ef9 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -54,10 +54,6 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel return {}; } - get hasDescription() { - return Boolean(this.description); - } - /** * Create a Map containing each Action step based on fields define in schema. Ordered by Fields order property. * @@ -114,10 +110,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel return this._id; } - /** - * Returns true if the current user is the owner of the containing item. - * @returns {boolean} - */ + /** Returns true if the current user is the owner of the containing item */ get isOwner() { return this.item?.isOwner ?? true; } @@ -146,7 +139,6 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel /** * Return the first Actor parent found. - * @returns {DhpActor | null} */ get actor() { return this.item instanceof DhpActor @@ -159,7 +151,6 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel /** * Returns true if the action is usable. * An action is usable on any actor type. For example, an adversary might have a base attack action. - * @returns {boolean} */ get usable() { const actor = this.actor; @@ -237,8 +228,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel let config = this.prepareConfig(event, configOptions); if (!config) return; - config.effects = - await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects(this.actor, this.item); + config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects(this.actor, this.item); if (Hooks.call(`${CONFIG.DH.id}.preUseAction`, this, config) === false) return; @@ -256,8 +246,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel if (Hooks.call(`${CONFIG.DH.id}.postUseAction`, this, config) === false) return; - if (this.chatDisplay && !config.skips.createMessage && !config.actionChatMessageHandled) - await this.toChat(null, config); + if (this.chatDisplay && !config.skips.createMessage && !config.actionChatMessageHandled) await this.toChat(); return config; } @@ -289,6 +278,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel hasEffect: this.hasEffect, hasSave: this.hasSave, onSave: this.save?.damageMod, + isDirect: !!this.damage?.direct, selectedMessageMode: game.settings.get('core', 'messageMode'), data: this.getRollData(), evaluate: this.hasRoll, @@ -306,20 +296,20 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel }; if (this.damage) { - config.isDirect = !!this.damage.main?.direct; + config.isDirect = this.damage.direct; - const groupAttackTokens = this.damage.main?.groupAttack + const groupAttackTokens = this.damage.groupAttack ? game.system.api.fields.ActionFields.DamageField.getGroupAttackTokens( this.actor.id, - this.damage.main.groupAttack + this.damage.groupAttack ) : null; config.damageOptions = { - groupAttack: this.damage.main?.groupAttack + groupAttack: this.damage.groupAttack ? { numAttackers: Math.max(groupAttackTokens.length, 1), - range: this.damage.main.groupAttack + range: this.damage.groupAttack } : null }; @@ -343,45 +333,27 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel } /** - * Get the all potentially applicable effects on the actor for the action's RollDialog + * Get the all potentially applicable effects on the actor * @param {DHActor} actor The actor performing the action * @param {DHItem|DhActor} effectParent The parent of the effect * @returns {DhActiveEffect[]} */ - static async getActionRelevantEffects(actor, effectParent) { + static async getEffects(actor, effectParent) { if (!actor) return []; - // Changes on weapon effects are not typically only applicable to show in the roll dialog for the weapon itself - // The exemptions to this rule are listed below - const weaponTransferredEffectKeys = [ - 'system.bonuses.roll.spellcast.bonus' - ]; - - const results = []; - const applicableEffects = await actor.allApplicableEffects({ noTransferArmor: true, noSelfArmor: true }); - for (const effect of [...applicableEffects].filter(e => !e.isSuppressed)) { - if (effect.parent.type === 'weapon') { - // Effects on weapons only ever apply for the weapon itself (with a few exceptions) - const restricted = - effect.parent.system.secondary - // Secondary applies only to other primary weapons - ? effectParent?.type !== 'weapon' || effectParent?.system.secondary - // Primary only applies to itself - : effectParent?.id !== effect.parent.id; - if (restricted) { - const sourceChanges = effect._source.system.changes; - const changes = sourceChanges.filter(x => weaponTransferredEffectKeys.includes(x.key)); - if (changes.length) { - results.push(effect.clone({ 'system.changes': changes })); - } - continue; + return Array.from(await actor.allApplicableEffects({ noTransferArmor: true, noSelfArmor: true })).filter( + effect => { + /* Effects on weapons only ever apply for the weapon itself */ + if (effect.parent.type === 'weapon') { + /* Unless they're secondary - then they apply only to other primary weapons */ + if (effect.parent.system.secondary) { + if (effectParent?.type !== 'weapon' || effectParent?.system.secondary) return false; + } else if (effectParent?.id !== effect.parent.id) return false; } - } - - results.push(effect); - } - return results; + return !effect.isSuppressed; + } + ); } /** @@ -429,11 +401,11 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel } get hasDamage() { - return this.type !== 'healing' && (Boolean(this.damage?.main) || !foundry.utils.isEmpty(this.damage?.resources)); + return Boolean(Object.keys(this.damage?.parts ?? {}).length) && this.type !== 'healing'; } get hasHealing() { - return this.type === 'healing' && !foundry.utils.isEmpty(this.damage?.resources); + return Boolean(Object.keys(this.damage?.parts ?? {}).length) && this.type === 'healing'; } get hasSave() { @@ -456,38 +428,11 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel static migrateData(source) { if (source.damage?.parts && Array.isArray(source.damage.parts)) { - let hitPointsExists = source.damage.parts.some(x => x.applyTo === 'hitPoints'); source.damage.parts = source.damage.parts.reduce((acc, part) => { - if (!part.applyTo && hitPointsExists) return acc; - - if (!part.applyTo) { - hitPointsExists = true; - part.applyTo = 'hitPoints'; - } - acc[part.applyTo] = part; return acc; }, {}); } - - if (source.damage?.parts && !source.damage.resources && !source.damage.main) { - source.damage.main = null; - source.damage.resources = {}; - for (const [partKey, part] of Object.entries(source.damage.parts)) { - if (partKey === 'hitPoints' && source.type !== 'healing') { - source.damage.main = { - ...part, - includeBase: source.damage.includeBase, - direct: source.damage.direct, - groupAttack: source.damage.groupAttack - }; - } else { - source.damage.resources[partKey] = part; - } - } - - delete source.damage.parts; - } } } @@ -514,7 +459,8 @@ export class ResourceUpdateMap extends Map { } else if (!existing?.clear) { this.set(resource.key, { ...existing, - value: existing.value + (resource.value ?? 0) + value: existing.value + (resource.value ?? 0), + total: existing.total + (resource.total ?? 0) }); } } diff --git a/module/data/action/damageAction.mjs b/module/data/action/damageAction.mjs index 15135e0d..51735543 100644 --- a/module/data/action/damageAction.mjs +++ b/module/data/action/damageAction.mjs @@ -8,8 +8,11 @@ export default class DHDamageAction extends DHBaseAction { * @returns Formula string */ getDamageFormula() { - if (!this.damage.main) return ''; + const strings = []; + for (const { value } of this.damage.parts) { + strings.push(Roll.replaceFormulaData(value.getFormula(), this.actor?.getRollData() ?? {})); + } - return Roll.replaceFormulaData(this.damage.main.value.getFormula(), this.actor?.getRollData() ?? {}); + return strings.join(' + '); } } diff --git a/module/data/activeEffect/baseEffect.mjs b/module/data/activeEffect/baseEffect.mjs index 547bdcf7..9b17164d 100644 --- a/module/data/activeEffect/baseEffect.mjs +++ b/module/data/activeEffect/baseEffect.mjs @@ -57,6 +57,11 @@ export default class BaseEffect extends foundry.data.ActiveEffectTypeDataModel { description: new fields.HTMLField({ label: 'DAGGERHEART.GENERAL.description' }) }), rangeDependence: new fields.SchemaField({ + enabled: new fields.BooleanField({ + required: true, + initial: false, + label: 'DAGGERHEART.GENERAL.enabled' + }), type: new fields.StringField({ required: true, choices: CONFIG.DH.GENERAL.rangeInclusion, @@ -75,7 +80,7 @@ export default class BaseEffect extends foundry.data.ActiveEffectTypeDataModel { initial: CONFIG.DH.GENERAL.range.melee.id, label: 'DAGGERHEART.GENERAL.range' }) - }, { nullable: true, initial: null }), + }), stacking: new fields.SchemaField( { value: new fields.NumberField({ @@ -141,8 +146,14 @@ export default class BaseEffect extends foundry.data.ActiveEffectTypeDataModel { description: '', transfer: options.transfer, statuses: [], + changes: [], system: { - changes: [] + rangeDependence: { + enabled: false, + type: CONFIG.DH.GENERAL.rangeInclusion.withinRange.id, + target: CONFIG.DH.GENERAL.otherTargetTypes.hostile.id, + range: CONFIG.DH.GENERAL.range.melee.id + } } }; } @@ -174,12 +185,4 @@ export default class BaseEffect extends foundry.data.ActiveEffectTypeDataModel { if (this.parent.actor && options.scrollingTextData) this.parent.actor.queueScrollText(options.scrollingTextData); } - - static migrateData(source) { - if (source.rangeDependence?.enabled === false) { - source.rangeDependence = null; - } - - return super.migrateData(source); - } } diff --git a/module/data/actor/_types.d.ts b/module/data/actor/_types.d.ts deleted file mode 100644 index fec6e638..00000000 --- a/module/data/actor/_types.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import DhpActor from '../../documents/actor.mjs' -import DhCharacter from './character.mjs'; - -declare module './base.mjs' { - export default interface BaseDataActor { - parent: DhpActor; - } -} - -declare module './companion.mjs' { - export default interface DhCompanion { - partner: DhpActor; - } -} diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs index 2640211f..d6d0dcdf 100644 --- a/module/data/actor/adversary.mjs +++ b/module/data/actor/adversary.mjs @@ -84,11 +84,12 @@ export default class DhpAdversary extends DhCreature { type: 'attack' }, damage: { - main: { - type: ['physical'], - applyTo: 'hitPoints', - value: { - multiplier: 'flat' + parts: { + hitPoints: { + type: ['physical'], + value: { + multiplier: 'flat' + } } } } diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index 995708eb..9efbe7d7 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -1,13 +1,9 @@ +import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs'; +import DHItem from '../../documents/item.mjs'; import { createShallowProxy, getScrollTextData } from '../../helpers/utils.mjs'; const fields = foundry.data.fields; -/** - * @import DHItem from '../../documents/item.mjs'; - * @import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs'; - */ - -/** Function to generate resistance fields for damage types */ const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) => new fields.SchemaField({ resistance: new fields.BooleanField({ @@ -100,8 +96,6 @@ export const commonActorRules = (extendedData = { damageReduction: {}, attack: { * @property {Boolean} isNPC - This data model represents a NPC? * @property {typeof DHBaseActorSettings} settingSheet - The sheet class used to render the settings UI for this actor type. */ - -/** Base actor type data model for all actors in Daggerheart */ export default class BaseDataActor extends foundry.abstract.TypeDataModel { /** @returns {ActorDataModelMetadata}*/ static get metadata() { diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 8ff50a5d..0cae662f 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -104,13 +104,14 @@ export default class DhCharacter extends DhCreature { trait: 'strength' }, damage: { - main: { - type: ['physical'], - applyTo: 'hitPoints', - value: { - custom: { - enabled: true, - formula: '@profd4' + parts: { + hitPoints: { + type: ['physical'], + value: { + custom: { + enabled: true, + formula: '@profd4' + } } } } @@ -314,12 +315,7 @@ export default class DhCharacter extends DhCreature { label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice' }) }) - }), - /** Accumulated armor score from all sources */ - armorScore: new fields.SchemaField({ - value: new fields.NumberField(), - max: new fields.NumberField() - }, { persisted: false }) + }) }; } @@ -415,8 +411,8 @@ export default class DhCharacter extends DhCreature { get domainCards() { const domainCards = this.parent.items.filter(x => x.type === 'domainCard'); - const loadout = domainCards.filter(x => !x.system.inVault).sort((a, b) => a.sort - b.sort); - const vault = domainCards.filter(x => x.system.inVault).sort((a, b) => a.sort - b.sort); + const loadout = domainCards.filter(x => !x.system.inVault); + const vault = domainCards.filter(x => x.system.inVault); return { loadout: loadout, @@ -836,7 +832,7 @@ export default class DhCharacter extends DhCreature { isReversed: true }; - this.attack.damage.main.value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`; + 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(); diff --git a/module/data/actor/companion.mjs b/module/data/actor/companion.mjs index 2ca7fd5b..300bd698 100644 --- a/module/data/actor/companion.mjs +++ b/module/data/actor/companion.mjs @@ -102,7 +102,6 @@ export default class DhCompanion extends DhCreature { parts: { hitPoints: { type: ['physical'], - applyTo: 'hitPoints', value: { dice: 'd6', multiplier: 'prof' diff --git a/module/data/actor/tierAdjustment.mjs b/module/data/actor/tierAdjustment.mjs index 4bf74a45..bc6ad176 100644 --- a/module/data/actor/tierAdjustment.mjs +++ b/module/data/actor/tierAdjustment.mjs @@ -2,14 +2,8 @@ import { calculateExpectedValue, parseTermsFromSimpleFormula } from '../../helpe import { adversaryExpectedDamage, adversaryScalingData } from '../../config/actorConfig.mjs'; import { parseInlineParams } from '../../enrichers/parser.mjs'; -/** - * Accepts source data for an adversary and a target tier, and returns new source data - * @type {object} source - * @type {number} tier - * @returns {object} adjusted source data - */ export function getTierAdjustedAdversary(source, tier) { - const currentTier = source.system.tier ?? 1; + const currentTier = source.tier ?? 1; /** @type {(2 | 3 | 4)[]} */ const tiers = new Array(Math.abs(tier - currentTier)) @@ -40,20 +34,20 @@ export function getTierAdjustedAdversary(source, tier) { // Store initial attack damage for abilities that have you deal a "standard attack" const initialAttack = { - type: source.system.attack.damage?.main?.type?.toSorted(), - value: getFormula(source.system.attack.damage?.main?.value) + type: source.system.attack.damage?.parts.hitPoints?.type?.toSorted(), + value: getDamagePartsFormula(source.system.attack.damage?.parts.hitPoints?.value) }; // Update damage of base attack. try { const damage = source.system.attack.damage; - if (!damage?.main) throw new Error('Unexpected missing damage in adversary'); + if (!damage?.parts.hitPoints) throw new Error('Unexpected missing attack in adversary'); for (const property of ['value', 'valueAlt']) { - const data = damage.main[property]; - const previousFormula = getFormula(data); - const value = calculateAdjustedDamage(previousFormula, 'attack', damageMeta); - applyAdjustedDamage(data, value); + const data = damage.parts.hitPoints[property]; + const previousFormula = getDamagePartsFormula(data); + const { value, formula } = calculateAdjustedDamage(previousFormula, 'attack', damageMeta); + applyAdjustedDamage(data, value, formula); } } catch (err) { ui.notifications.warn('Failed to convert attack damage of adversary'); @@ -71,7 +65,7 @@ export function getTierAdjustedAdversary(source, tier) { if (!formula) return match; try { - const newFormula = getFormula(calculateAdjustedDamage(formula, 'action', damageMeta)); + const newFormula = calculateAdjustedDamage(formula, 'action', damageMeta)?.formula; descriptionFormulas.push(formula); return match.replace(formula, newFormula); } catch { @@ -82,21 +76,21 @@ export function getTierAdjustedAdversary(source, tier) { // Update damage in item actions and convert all formula matches in the descriptions to the new damage for (const action of Object.values(item.system.actions)) { - if (!action.damage?.main) continue; + if (!action.damage?.parts.hitPoints) continue; try { // Apply conversions and save a record. If it matches attack damage *and* Its not in the description, use attack conversion instead const result = []; for (const property of ['value', 'valueAlt']) { - const { [property]: data, type: damageType } = action.damage.main; - const previousFormula = getFormula(data); + const { [property]: data, type: damageType } = action.damage.parts.hitPoints; + const previousFormula = getDamagePartsFormula(data); const isActuallyAttack = previousFormula === initialAttack.value && foundry.utils.equals(damageType.toSorted(), initialAttack.type) && !descriptionFormulas.includes(previousFormula); const type = isActuallyAttack ? 'attack' : 'action'; - const value = calculateAdjustedDamage(previousFormula, type, damageMeta); - applyAdjustedDamage(data, value); - result.push({ previousFormula, formula: getFormula(value) }); + const { value, formula } = calculateAdjustedDamage(previousFormula, type, damageMeta); + applyAdjustedDamage(data, value, formula); + result.push({ previousFormula, formula }); } // Override text in the description with those values @@ -195,30 +189,24 @@ function calculateAdjustedDamage(formula, type, { currentDamageRange, newDamageR value.bonus = Math.round(expected - getBaseAverage()); } - return value; + const newFormula = [value.diceQuantity ? `${value.diceQuantity}d${value.faces}` : null, value.bonus] + .filter(p => !!p) + .join('+'); + return { value, formula: newFormula }; } -/** - * Get formula from either damage data *or* a simple formula object. - * @returns {string} the new formula data - */ -function getFormula(data) { - if (data.custom?.enabled) { - return data.custom.formula; - } - - const diceQuantity = data.flatMultiplier ?? data.diceQuantity; - const dice = data.faces ? `d${data.faces}` : data.dice; - const mod = data.bonus; - return [diceQuantity ? `${diceQuantity}${dice}` : 0, mod].filter(p => !!p).join('+'); +function getDamagePartsFormula(data) { + return data.custom.enabled + ? data.custom.formula + : [data.flatMultiplier ? `${data.flatMultiplier}${data.dice}` : 0, data.bonus ?? 0].filter(p => !!p).join('+'); } /** * Updates damage to reflect a specific value. - * @param {object} diceData - * @param {object} value + * @throws if damage structure is invalid for conversion + * @returns the converted formula and value as a simplified term, or null if it doesn't deal HP damage */ -function applyAdjustedDamage(diceData, value) { +function applyAdjustedDamage(diceData, value, formula) { if (value.diceQuantity) { diceData.custom.enabled = false; diceData.bonus = value.bonus; @@ -226,6 +214,6 @@ function applyAdjustedDamage(diceData, value) { diceData.flatMultiplier = value.diceQuantity; } else if (!value.diceQuantity) { diceData.custom.enabled = true; - diceData.custom.formula = getFormula(value); + diceData.custom.formula = formula; } } diff --git a/module/data/chat-message/actorRoll.mjs b/module/data/chat-message/actorRoll.mjs index 3dcf2a8d..ccfe25ea 100644 --- a/module/data/chat-message/actorRoll.mjs +++ b/module/data/chat-message/actorRoll.mjs @@ -1,5 +1,4 @@ import { triggerChatRollFx } from '../../helpers/utils.mjs'; -import { ChatDamageData } from './chatDamageData.mjs'; const fields = foundry.data.fields; @@ -42,7 +41,6 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { hasEffect: new fields.BooleanField({ initial: false }), hasSave: new fields.BooleanField({ initial: false }), hasTarget: new fields.BooleanField({ initial: false }), - reloadCheckValue: new fields.NumberField({ integer: true, nullable: true, initial: null }), isDirect: new fields.BooleanField({ initial: false }), onSave: new fields.StringField(), source: new fields.SchemaField({ @@ -51,7 +49,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { originItem: originItemField(), action: new fields.StringField() }), - damage: new fields.EmbeddedDataField(ChatDamageData), + damage: new fields.ObjectField(), damageOptions: new fields.ObjectField(), costs: new fields.ArrayField(new fields.ObjectField()), successConsumed: new fields.BooleanField({ initial: false }) @@ -76,14 +74,10 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { return fromUuidSync(this.source.actor); } - get item() { + get actionItem() { const actionActor = this.actionActor; if (!actionActor || !this.source.item) return null; - - return actionActor.items.get(this.source.item); - } - get actionItem() { switch (this.source.originItem.type) { case CONFIG.DH.ITEM.originItemType.restMove: const restMoves = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).restMoves; @@ -91,18 +85,11 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { this.source.originItem.actionIndex ]; default: - return this.item?.system.actionsList?.find(a => a.id === this.source.action); + const item = actionActor.items.get(this.source.item); + return item ? item.system.actionsList?.find(a => a.id === this.source.action) : null; } } - get hasReload() { - return this.item?.system.hasReload; - } - - get reloadCheckFailed() { - return this.reloadCheckValue === 1; - } - get action() { const { actionActor, actionItem: itemAction } = this; if (!this.source.action) return null; @@ -145,21 +132,28 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { }); } + /* TODO: Change how damage data is stored somehow to enable better rerolling */ async getRerolledDamage() { - if (!this.damage.active) return; + if (!this.damage) return; const rerolls = []; - const update = { system: { damage: { main: null, resources: _replace({}) } } }; - if (this.damage.main) { - const reroll = await this.damage.main.reroll(); - rerolls.push(reroll); - update.system.damage.main = reroll.toJSON(); - } + const update = { system: { damage: {} } }; + for (const partKey in this.damage) { + const part = this.damage[partKey]; + const testRoll = Roll.fromData(part.parts[0].roll); + const rerolled = await testRoll.reroll(); + rerolls.push(rerolled); - for (const key of Object.keys(this.damage.resources)) { - const reroll = await this.damage.resources[key].reroll(); - rerolls.push(reroll); - update.system.damage.resources[key] = reroll.toJSON(); + if (!update.system.damage[partKey]) update.system.damage[partKey] = { parts: [part.parts[0]] }; + const partData = update.system.damage[partKey].parts[0]; + update.system.damage[partKey].total = rerolled.total; + partData.modifierTotal = rerolled.terms.reduce((acc, x) => { + if (x.isDeterministic && !x.operator) acc += x.total; + return acc; + }, 0); + partData.dice = rerolled.dice.map(d => ({ ...d.toJSON(), dice: d.denomination })); + partData.total = rerolled.total; + partData.roll = rerolled.toJSON(); } await triggerChatRollFx(rerolls); @@ -204,43 +198,6 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { this.isGM = game.user.isGM; //temp } - static migrateData(source) { - const { main, resources, ...flatDamageKeys } = source.damage ?? {}; - if (source.damage && !main && !resources) { - source.damage.main = null; - source.damage.resources = {}; - - const getRoll = key => { - const damageData = source.damage[key]; - const oldRoll = damageData.parts[0]?.roll; - return oldRoll ? JSON.stringify({ - ...oldRoll, - class: 'BaseRoll', - options: { - ...oldRoll.options, - damageTypes: damageData.parts[0].damageTypes ?? [] - } - }) : null; - }; - - for (const key of Object.keys(flatDamageKeys)) { - if (key === 'hitPoints' && source.hasDamage && !source.hasHealing) { - source.damage.main = getRoll('hitPoints'); - } - else { - source.damage.resources[key] = getRoll(key); - } - } - } - - for (const key of Object.keys(flatDamageKeys)) { - delete source.damage[key]; - } - - return source; - } - - getTargetList() { const targets = this.targetMode && this.parent.isAuthor diff --git a/module/data/chat-message/chatDamageData.mjs b/module/data/chat-message/chatDamageData.mjs deleted file mode 100644 index 404cda43..00000000 --- a/module/data/chat-message/chatDamageData.mjs +++ /dev/null @@ -1,58 +0,0 @@ -import { triggerChatRollFx } from '../../helpers/utils.mjs'; - -export class ChatDamageData extends foundry.abstract.DataModel { - constructor(data = {}, options = {}) { - super(data, options); - - this._prepareRolls(); - } - - static defineSchema() { - const fields = foundry.data.fields; - - return { - main: new fields.JSONField({ nullable: true, validate: ChatDamageData.#validateRoll}), - resources: new fields.TypedObjectField(new fields.JSONField({validate: ChatDamageData.#validateRoll})) - }; - } - - get active() { - return !!this.main || Boolean(Object.keys(this.resources).length); - } - - static #validateRoll(rollJSON) { - if (rollJSON) { - const roll = JSON.parse(rollJSON); - if (!roll.evaluated) throw new Error('Roll objects added to ChatMessage documents must be evaluated'); - } - } - - _prepareRolls() { - this.main &&= Roll.fromData(this.main); - for (const key of Object.keys(this.resources)) { - this.resources[key] = Roll.fromData(this.resources[key]); - } - } - - async rerollDamageDie(isResource, damageType, dice, resultIndex) { - const reroll = isResource ? this.resources[damageType] : this.main; - const rerollDice = reroll.dice[dice]; - await rerollDice.rerollResult(resultIndex); - await reroll._evaluate(); - - const rerolledResult = rerollDice.results[rerollDice.results.length - 1]; - if (rerolledResult) { - const fakeRoll = { - _evaluated: true, - dice: [new foundry.dice.terms.Die({ - ...rerollDice, - results: [rerolledResult], - total: rerolledResult.value, - faces: rerollDice.faces - })], - options: { appearance: {} } - }; - await triggerChatRollFx([fakeRoll]); - } - } -} \ No newline at end of file diff --git a/module/data/countdowns.mjs b/module/data/countdowns.mjs index 5fe01e20..54971d34 100644 --- a/module/data/countdowns.mjs +++ b/module/data/countdowns.mjs @@ -1,4 +1,3 @@ -import { RefreshType, socketEvent } from '../systemRegistration/socket.mjs'; import FormulaField from './fields/formulaField.mjs'; export default class DhCountdowns extends foundry.abstract.DataModel { @@ -14,71 +13,6 @@ export default class DhCountdowns extends foundry.abstract.DataModel { }) }; } - - /** @inheritdoc */ - _initialize(options) { - super._initialize(options); - for (const [id, countdown] of Object.entries(this.countdowns)) { - countdown.id = id; - } - } - - async handleChange() { - const previousCountdowns = foundry.ui.countdowns.previousCountdownData; - const changedCountdowns = Object.entries(this.countdowns).reduce((acc, [key, countdown]) => { - const previous = previousCountdowns[key]; - const currentChanged = !previous || (previous.progress.current !== countdown.progress.current); - if (currentChanged && previous?.progress.start === countdown.progress.start) { - acc.push(key); - } - return acc; - }, []); - - // Re-render countdowns applications. When the change is due to an actual update, resync the editor - if (!foundry.utils.equals(previousCountdowns, this.countdowns)) { - await foundry.ui.countdowns.render({ animate: changedCountdowns }); - for (const instance of game.system.api.applications.ui.CountdownEdit.instances()) { - instance.data = this; - await instance.render(); - } - } - - // Inform modules of updates - Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown }); - } - - static migrateData(source) { - const migrateOldCountdowns = (data, type) => { - for (const key of Object.keys(data.countdowns)) { - const countdown = data.countdowns[key]; - source.countdowns[key] = { - ...countdown, - type: type, - ownership: Object.keys(countdown.ownership.players).reduce((acc, key) => { - acc[key] = - countdown.ownership.players[key].type === 1 ? 2 : countdown.ownership.players[key].type; - return acc; - }, {}), - progress: { - ...countdown.progress, - type: countdown.progress.type.value - } - }; - } - - source[type] = null; - }; - - if (source.narrative) { - migrateOldCountdowns(source.narrative, 'narrative'); - } - - if (source.encounter) { - migrateOldCountdowns(source.encounter, 'encounter'); - } - - return super.migrateData(source); - } } export class DhCountdown extends foundry.abstract.DataModel { @@ -87,8 +21,7 @@ export class DhCountdown extends foundry.abstract.DataModel { return { type: new fields.StringField({ required: true, - choices: CONFIG.DH.GENERAL.countdownTypes, - initial: CONFIG.DH.GENERAL.countdownTypes.encounter.id, + choices: CONFIG.DH.GENERAL.countdownBaseTypes, label: 'DAGGERHEART.GENERAL.type' }), name: new fields.StringField({ @@ -152,7 +85,7 @@ export class DhCountdown extends foundry.abstract.DataModel { : undefined; return { - type: type ?? CONFIG.DH.GENERAL.countdownTypes.encounter.id, + type: type ?? CONFIG.DH.GENERAL.countdownBaseTypes.narrative.id, name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Countdown.newCountdown'), img: 'icons/magic/time/hourglass-yellow-green.webp', ownership: ownership, @@ -178,14 +111,6 @@ export class DhCountdown extends foundry.abstract.DataModel { }, {}); } - /** - * A boolean indicator for whether the current game User has ownership rights for this countdown - * @returns {boolean} - */ - get isOwner() { - return this.getUserLevel(game.user) === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER; - } - /** @inheritDoc */ static migrateData(source) { if (source.progress.max) { @@ -196,29 +121,4 @@ export class DhCountdown extends foundry.abstract.DataModel { return super.migrateData(source); } - - /** - * Get the explicit permission level that a User has over this Document, a value in CONST.DOCUMENT_OWNERSHIP_LEVELS. - * Compendium content ignores the ownership field in favor of User role-based ownership. Otherwise, Documents use - * granular per-User ownership definitions and Embedded Documents defer to their parent ownership. - * - * @param {BaseUser} [user=game.user] The User being tested - * @returns {DocumentOwnershipNumber} A numeric permission level from {@link CONST.DOCUMENT_OWNERSHIP_LEVELS} - */ - getUserLevel(user) { - if (user.isGM) return CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER; - - const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); - const playerOwnership = this.ownership[user.id]; - return playerOwnership === undefined || playerOwnership === CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT - ? setting.defaultOwnership - : playerOwnership; - } - - async delete() { - const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); - const data = foundry.utils.deepClone(setting._source); - delete data.countdowns[this.id]; - await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data); - } } diff --git a/module/data/fields/action/areasField.mjs b/module/data/fields/action/areasField.mjs index a4180101..52110045 100644 --- a/module/data/fields/action/areasField.mjs +++ b/module/data/fields/action/areasField.mjs @@ -33,10 +33,6 @@ export default class AreasField extends fields.ArrayField { initial: CONFIG.DH.GENERAL.range.veryClose.id, label: 'DAGGERHEART.ACTIONS.Config.area.size' }), - hasHole: new fields.BooleanField({ - initial: false, - label: 'DAGGERHEART.ACTIONS.Config.area.hasHole' - }), effects: new fields.ArrayField(new fields.DocumentIdField()) }); super(element, options, context); diff --git a/module/data/fields/action/countdownField.mjs b/module/data/fields/action/countdownField.mjs index 53e132c9..96d9dd91 100644 --- a/module/data/fields/action/countdownField.mjs +++ b/module/data/fields/action/countdownField.mjs @@ -8,8 +8,8 @@ export default class CountdownField extends fields.ArrayField { ...game.system.api.data.countdowns.DhCountdown.defineSchema(), type: new fields.StringField({ required: true, - choices: CONFIG.DH.GENERAL.countdownTypes, - initial: CONFIG.DH.GENERAL.countdownTypes.encounter.id, + choices: CONFIG.DH.GENERAL.countdownBaseTypes, + initial: CONFIG.DH.GENERAL.countdownBaseTypes.encounter.id, label: 'DAGGERHEART.GENERAL.type' }), name: new fields.StringField({ diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index 25b3ba97..9b21d3ba 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -12,10 +12,20 @@ export default class DamageField extends fields.SchemaField { /** @inheritDoc */ constructor(options, context = {}) { - super({ - main: new fields.EmbeddedDataField(DHDamageData, { nullable: true }), - resources: new IterableTypedObjectField(DHResourceData) - }, options, context); + const damageFields = { + parts: new IterableTypedObjectField(DHDamageData), + includeBase: new fields.BooleanField({ + initial: false, + label: 'DAGGERHEART.ACTIONS.Settings.includeBase.label' + }), + direct: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.CONFIG.DamageType.direct.name' }), + groupAttack: new fields.StringField({ + choices: CONFIG.DH.GENERAL.groupAttackRange, + blank: true, + label: 'DAGGERHEART.ACTIONS.Settings.groupAttack.label' + }) + }; + super(damageFields, options, context); } /** @@ -31,23 +41,25 @@ export default class DamageField extends fields.SchemaField { this.hasRoll && DamageField.getAutomation() === CONFIG.DH.SETTINGS.actionAutomationChoices.never.id && !force - ) { + ) return; - } - const damageFormula = this.damage.main ? - DamageField.formatFormulas.call(this, [this.damage.main], config)[0] : null; - const resourceFormulas = DamageField.formatFormulas.call(this, this.damage.resources, config); + let formulas = this.damage.parts.map(p => ({ + formula: DamageField.getFormulaValue.call(this, p, config).getFormula(this.actor), + damageTypes: p.applyTo === 'hitPoints' && !p.type.size ? new Set(['physical']) : p.type, + applyTo: p.applyTo + })); - if (!damageFormula && !resourceFormulas.length) return false; + if (!formulas.length) return false; + + formulas = DamageField.formatFormulas.call(this, formulas, config); messageId = config.message?._id ?? messageId; const message = game.messages.get(messageId); const damageConfig = { dialog: {}, ...config, - damageFormula, - resourceFormulas, + roll: formulas, data: this.getRollData(), isCritical: Boolean(message?.system.roll?.isCritical) }; @@ -80,7 +92,7 @@ export default class DamageField extends fields.SchemaField { const targetDamage = []; const damagePromises = []; - for (const target of targets) { + for (let target of targets) { const actor = foundry.utils.fromUuidSync(target.actorId); if (!actor) continue; if (!config.hasHealing && config.onSave && target.saved?.success === true) { @@ -102,12 +114,13 @@ export default class DamageField extends fields.SchemaField { actor.takeHealing(config.damage).then(updates => targetDamage.push({ token, updates })) ); else { - const configDamage = config.damage.clone(); - configDamage.main &&= configDamage.main.toJSON(); - if (configDamage.main) { - const multiplier = config.actionActor?.system.rules?.attack?.damage?.hpDamageMultiplier ?? 1; - const takenMultiplier = actor.system.rules?.attack?.damage?.hpDamageTakenMultiplier; - configDamage.main.total = Math.ceil(configDamage.main.total * multiplier * takenMultiplier); + const configDamage = foundry.utils.deepClone(config.damage); + const hpDamageMultiplier = config.actionActor?.system.rules?.attack?.damage?.hpDamageMultiplier ?? 1; + const hpDamageTakenMultiplier = actor.system.rules?.attack?.damage?.hpDamageTakenMultiplier; + if (configDamage.hitPoints) { + for (const part of configDamage.hitPoints.parts) { + part.total = Math.ceil(part.total * hpDamageMultiplier * hpDamageTakenMultiplier); + } } damagePromises.push( @@ -170,19 +183,13 @@ export default class DamageField extends fields.SchemaField { /** * Prepare formulas for Damage Roll * Must be called within Action context or similar. - * @param {DHResourceData[]} damageData Array of DHResourceData + * @param {object[]} formulas Array of formatted formulas object * @param {object} data Action getRollData * @returns */ - static formatFormulas(damageData, data) { - const formulas = damageData.map(x => ({ - formula: DamageField.getFormulaValue.call(this, x, data).getFormula(this.actor), - damageTypes: x.type ?? new Set(), - applyTo: x.applyTo - })); - + static formatFormulas(formulas, data) { const formattedFormulas = []; - for (const formula of formulas) { + formulas.forEach(formula => { if (isNaN(formula.formula)) formula.formula = Roll.replaceFormulaData(formula.formula, this.getRollData(data)); const same = formattedFormulas.find( @@ -190,8 +197,7 @@ export default class DamageField extends fields.SchemaField { ); if (same) same.formula += ` + ${formula.formula}`; else formattedFormulas.push(formula); - } - + }); return formattedFormulas; } @@ -269,18 +275,10 @@ export class DHActionDiceData extends foundry.abstract.DataModel { }; } - /** - * @returns {string} the formula associated with this damage field - */ getFormula() { - if (this.custom.enabled) return this.custom.formula; - - const multiplier = this.multiplier === 'flat' ? this.flatMultiplier : `@${this.multiplier}`; - if (!multiplier) return String(this.bonus || 0); - - const dice = `${multiplier ?? 1}${this.dice}`; - const sign = this.bonus < 0 ? ' - ' : ' + '; - return this.bonus ? `${dice} ${sign} ${Math.abs(this.bonus)}` : dice; + const multiplier = this.multiplier === 'flat' ? this.flatMultiplier : `@${this.multiplier}`, + bonus = this.bonus ? (this.bonus < 0 ? ` - ${Math.abs(this.bonus)}` : ` + ${this.bonus}`) : ''; + return this.custom.enabled ? this.custom.formula : `${multiplier ?? 1}${this.dice}${bonus}`; } } @@ -288,7 +286,6 @@ export class DHResourceData extends foundry.abstract.DataModel { /** @override */ static defineSchema() { return { - base: new fields.BooleanField({ initial: false, readonly: true, label: 'Base' }), applyTo: new fields.StringField({ choices: CONFIG.DH.GENERAL.healingTypes, required: true, @@ -311,16 +308,7 @@ export class DHDamageData extends DHResourceData { static defineSchema() { return { ...super.defineSchema(), - includeBase: new fields.BooleanField({ - initial: false, - label: 'DAGGERHEART.ACTIONS.Settings.includeBase.label' - }), - direct: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.CONFIG.DamageType.direct.name' }), - groupAttack: new fields.StringField({ - choices: CONFIG.DH.GENERAL.groupAttackRange, - blank: true, - label: 'DAGGERHEART.ACTIONS.Settings.groupAttack.label' - }), + base: new fields.BooleanField({ initial: false, readonly: true, label: 'Base' }), type: new fields.SetField( new fields.StringField({ choices: CONFIG.DH.GENERAL.damageTypes, diff --git a/module/data/fields/action/summonField.mjs b/module/data/fields/action/summonField.mjs index fef6625a..a2275fa5 100644 --- a/module/data/fields/action/summonField.mjs +++ b/module/data/fields/action/summonField.mjs @@ -1,4 +1,4 @@ -import { getWorldActor, itemAbleRollParse, triggerChatRollFx } from '../../../helpers/utils.mjs'; +import { itemAbleRollParse, triggerChatRollFx } from '../../../helpers/utils.mjs'; import FormulaField from '../formulaField.mjs'; const fields = foundry.data.fields; @@ -23,7 +23,7 @@ export default class DHSummonField extends fields.ArrayField { super(summonFields, options, context); } - static async execute(config) { + static async execute() { if (!canvas.scene) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.summon.error')); return; @@ -36,14 +36,13 @@ export default class DHSummonField extends fields.ArrayField { const rolls = []; const summonData = []; - const chatMessageData = []; for (const summon of this.summon) { const roll = new Roll(itemAbleRollParse(summon.count, this.actor, this.item)); await roll.evaluate(); const count = roll.total; if (!roll.isDeterministic) rolls.push(roll); - const actor = await getWorldActor(await foundry.utils.fromUuid(summon.actorUUID)); + const actor = await DHSummonField.getWorldActor(await foundry.utils.fromUuid(summon.actorUUID)); /* Extending summon data in memory so it's available in actionField.toChat. Think it's harmless, but ugly. Could maybe find a better way. */ summon.actor = actor.toObject(); @@ -55,18 +54,30 @@ export default class DHSummonField extends fields.ArrayField { tokenPreviewName: `${actor.prototypeToken.name}${remaining > 1 ? ` (${remaining}x)` : ''}` }); } - - chatMessageData.push({ - data: actor, - quantity: countNumber - }); } if (rolls.length) await triggerChatRollFx(rolls); this.actor.sheet?.minimize(); - await CONFIG.ux.TokenManager.createTokensWithPreview(summonData, { elevation: this.actor.token?.elevation }); - this.actor.sheet?.maximize(); - config.summonData = chatMessageData; + DHSummonField.handleSummon(summonData, this.actor); + } + + /* Check for any available instances of the actor present in the world if we're missing artwork in the compendium. If none exists, create one. */ + static async getWorldActor(baseActor) { + const dataType = game.system.api.data.actors[`Dh${baseActor.type.capitalize()}`]; + if (baseActor.inCompendium && dataType && baseActor.img === dataType.DEFAULT_ICON) { + const worldActorCopy = game.actors.find(x => x.name === baseActor.name); + if (worldActorCopy) return worldActorCopy; + + return await game.system.api.documents.DhpActor.create(baseActor.toObject()); + } + + return baseActor; + } + + static async handleSummon(summonData, actionActor) { + await CONFIG.ux.TokenManager.createTokensWithPreview(summonData, { elevation: actionActor.token?.elevation }); + + return actionActor.sheet?.maximize(); } } diff --git a/module/data/fields/action/transformField.mjs b/module/data/fields/action/transformField.mjs index 0fc35742..07b32166 100644 --- a/module/data/fields/action/transformField.mjs +++ b/module/data/fields/action/transformField.mjs @@ -1,11 +1,5 @@ -import { getWorldActor } from '../../../helpers/utils.mjs'; - const fields = foundry.data.fields; -/** - * @import DHSummonAction from '../../action/summonAction.mjs' - */ - export default class DHSummonField extends fields.SchemaField { /** * Action Workflow order @@ -26,11 +20,6 @@ export default class DHSummonField extends fields.SchemaField { super(transformFields, options, context); } - /** - * Runs the execute. This is run on behalf of DHSummonAction. - * @todo move this function to be on the summon action. - * @this DHSummonAction - */ static async execute() { if (!this.transform.actorUUID) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.noTransformActor')); @@ -48,37 +37,26 @@ export default class DHSummonField extends fields.SchemaField { return false; } - const activeTokens = this.actor.getActiveTokens(false, true); - const controlledMatchingTokens = canvas.tokens.controlled - .filter(x => x.actor && x.actor.uuid === this.actor.uuid) - .map(x => x.document); - /** @type {typeof game.system.api.documents.DhToken | null} */ - const token = this.actor.token ?? ( - activeTokens.length === 1 ? activeTokens[0] : - (controlledMatchingTokens.length === 1 ? controlledMatchingTokens[0] : null) - ); - - if (!this.actor.token && !token) { - ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.linkedSelectedError')); + if (this.actor.prototypeToken.actorLink) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.actorLinkError')); return false; } - if (!token) { + if (!this.actor.token) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.prototypeError')); return false; } - const actor = await getWorldActor(baseActor); + const actor = await DHSummonField.getWorldActor(baseActor); const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes; const tokenSize = actor?.system.metadata.usesSize ? tokenSizes[actor.system.size] : actor.prototypeToken.width; - // Update token. Avoid using recursive: false, since that prevents animations - await token.update( - { ...actor.prototypeToken.toObject(), actorId: actor.id, width: tokenSize, height: tokenSize }, - { diff: false, noHook: true } + await this.actor.token.update( + { ...actor.prototypeToken.toJSON(), actorId: actor.id, width: tokenSize, height: tokenSize }, + { diff: false, recursive: false, noHook: true } ); - if (token.combatant) { + if (this.actor.token.combatant) { this.actor.token.combatant.update({ actorId: actor.id, img: actor.prototypeToken.texture.src }); } @@ -86,17 +64,17 @@ export default class DHSummonField extends fields.SchemaField { if (!this.transform.resourceRefresh.hitPoints) { marks.hitPoints = Math.min( this.actor.system.resources.hitPoints.value, - token.actor.system.resources.hitPoints.max - 1 + this.actor.token.actor.system.resources.hitPoints.max - 1 ); } if (!this.transform.resourceRefresh.stress) { marks.stress = Math.min( this.actor.system.resources.stress.value, - token.actor.system.resources.stress.max - 1 + this.actor.token.actor.system.resources.stress.max - 1 ); } if (marks.hitPoints || marks.stress) { - token.actor.update({ + this.actor.token.actor.update({ 'system.resources': { hitPoints: { value: marks.hitPoints }, stress: { value: marks.stress } @@ -106,9 +84,20 @@ export default class DHSummonField extends fields.SchemaField { const prevPosition = { ...this.actor.sheet.position }; this.actor.sheet.close(); - token.actor.sheet.render({ force: true, position: prevPosition }); - if (token.object.controlled) { - ui.effectsDisplay.refresh(); + this.actor.token.actor.sheet.render({ force: true, position: prevPosition }); + } + + /* Check for any available instances of the actor present in the world, or create a world actor based on compendium */ + static async getWorldActor(baseActor) { + if (!baseActor.inCompendium) return baseActor; + + const dataType = game.system.api.data.actors[`Dh${baseActor.type.capitalize()}`]; + if (dataType && baseActor.img === dataType.DEFAULT_ICON) { + const worldActorCopy = game.actors.find(x => x.name === baseActor.name); + if (worldActorCopy) return worldActorCopy; } + + const worldActor = await game.system.api.documents.DhpActor.create(baseActor.toObject()); + return worldActor; } } diff --git a/module/data/fields/actionField.mjs b/module/data/fields/actionField.mjs index f3bdce8a..83672c8e 100644 --- a/module/data/fields/actionField.mjs +++ b/module/data/fields/actionField.mjs @@ -238,7 +238,6 @@ export function ActionMixin(Base) { result = this.parent; } else { result = await this.item.update({ [path]: updates }, options); - if (!result) return result; } return this.inCollection @@ -270,7 +269,10 @@ export function ActionMixin(Base) { return this.delete(); } - async toChat(origin, config) { + async toChat(origin) { + const autoExpandDescription = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance) + .expandRollMessage?.desc; + const cls = getDocumentClass('ChatMessage'); const systemData = { title: game.i18n.localize('DAGGERHEART.CONFIG.FeatureForm.action'), @@ -280,7 +282,7 @@ export function ActionMixin(Base) { img: this.baseAction ? this.parent.parent.img : this.img, tags: this.tags ? this.tags : ['Spell', 'Arcana', 'Lv 10'], areas: this.areas, - summon: config?.summonData + summon: this.summon }, source: { actor: this.actor.uuid, @@ -305,7 +307,7 @@ export function ActionMixin(Base) { system: systemData, content: await foundry.applications.handlebars.renderTemplate( 'systems/daggerheart/templates/ui/chat/action.hbs', - systemData + { ...systemData, open: autoExpandDescription ? 'open' : '' } ), flags: { daggerheart: { diff --git a/module/data/fields/formulaField.mjs b/module/data/fields/formulaField.mjs index c465bec3..85922f1f 100644 --- a/module/data/fields/formulaField.mjs +++ b/module/data/fields/formulaField.mjs @@ -39,7 +39,7 @@ export default class FormulaField extends foundry.data.fields.StringField { let roll = null; try { roll = new Roll(value.replace(/@([a-z.0-9_-]+)/gi, '1')); - } catch { + } catch (_) { roll = new Roll(value.replace(/@([a-z.0-9_-]+)/gi, 'd6')); } roll.evaluateSync({ strict: false }); diff --git a/module/data/item/_types.d.ts b/module/data/item/_types.d.ts deleted file mode 100644 index 6004e13b..00000000 --- a/module/data/item/_types.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import DHItem from '../../documents/item.mjs'; - -declare module './base.mjs' { - export default interface BaseDataItem { - parent: DHItem; - actor: DhpActor; - } -} \ No newline at end of file diff --git a/module/data/item/armor.mjs b/module/data/item/armor.mjs index 70fbbb47..21c56f9a 100644 --- a/module/data/item/armor.mjs +++ b/module/data/item/armor.mjs @@ -8,8 +8,7 @@ export default class DHArmor extends AttachableItem { type: 'armor', hasDescription: true, isInventoryItem: true, - hasActions: true, - hasResource: true + hasActions: true }); } @@ -53,10 +52,6 @@ export default class DHArmor extends AttachableItem { ); } - get itemFeatures() { - return this.armorFeatures; - } - /**@inheritdoc */ async getDescriptionData() { const baseDescription = this.description; @@ -174,4 +169,8 @@ export default class DHArmor extends AttachableItem { const labels = [`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseScore')}: ${this.armor.max}`]; return labels; } + + get itemFeatures() { + return this.armorFeatures; + } } diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs index 095ba8f2..ba114fda 100644 --- a/module/data/item/base.mjs +++ b/module/data/item/base.mjs @@ -49,10 +49,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { }) }; - if (this.metadata.hasDescription) { - schema.description = new fields.HTMLField({ required: true, nullable: true }); - schema.gmNotes = new fields.HTMLField({ required: true, nullable: true }); - } + if (this.metadata.hasDescription) schema.description = new fields.HTMLField({ required: true, nullable: true }); if (this.metadata.hasResource) { schema.resource = new fields.SchemaField( @@ -137,7 +134,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { /** * Augments the description for the item with type specific info to display. Implemented in applicable item subtypes. * @param {object} [options] - Options that modify the styling of the rendered template. { headerStyle: undefined|'none'|'large' } - * @returns {Promise<{ prefix: string | null; value: string | null; suffix: string | null }>} + * @returns {string} */ async getDescriptionData(_options) { return { prefix: null, value: this.description, suffix: null }; @@ -146,26 +143,16 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { /** * Gets the enriched and augmented description for the item. * @param {object} [options] - Options that modify the styling of the rendered template. { headerStyle: undefined|'none'|'large' } - * @returns {Promise} + * @returns {string} */ - async getEnrichedDescription({ gmNotes = true } = {}) { + async getEnrichedDescription() { if (!this.metadata.hasDescription) return ''; const { prefix, value, suffix } = await this.getDescriptionData(); - let fullDescription = [prefix, value, suffix].filter(p => !!p).join('\n\n'); - if (this.gmNotes && gmNotes) { - const gmNotesElement = document.createElement('section'); - gmNotesElement.classList.add('gm-notes-section'); - gmNotesElement.dataset.visibility = 'gm'; - const header = document.createElement('header'); - header.classList.add('gm-notes'); - header.textContent = _loc('DAGGERHEART.ITEMS.FIELDS.gmNotes.label'); - gmNotesElement.innerHTML = header.outerHTML + this.gmNotes; - fullDescription += gmNotesElement.outerHTML; - } + const fullDescription = [prefix, value, suffix].filter(p => !!p).join('\n\n'); return await foundry.applications.ux.TextEditor.implementation.enrichHTML(fullDescription, { - relativeTo: this.parent, + relativeTo: this, rollData: this.getRollData(), secrets: this.parent.isOwner }); diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index 3d50e68a..84e4de7f 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -9,8 +9,7 @@ export default class DHWeapon extends AttachableItem { type: 'weapon', hasDescription: true, isInventoryItem: true, - hasActions: true, - hasResource: true + hasActions: true }); } @@ -67,11 +66,13 @@ export default class DHWeapon extends AttachableItem { type: 'attack' }, damage: { - main: { - type: ['physical'], - value: { - multiplier: 'prof', - dice: 'd8' + parts: { + hitPoints: { + type: ['physical'], + value: { + multiplier: 'prof', + dice: 'd8' + } } } } @@ -112,18 +113,6 @@ export default class DHWeapon extends AttachableItem { ); } - get itemFeatures() { - return this.weaponFeatures; - } - - get hasReload() { - return Boolean(this.weaponFeatures.find(x => x.value === 'reloading')); - } - - get needsReload() { - return this.hasReload && this.resource.value === 0; - } - /**@inheritdoc */ async getDescriptionData() { const baseDescription = this.description; @@ -236,12 +225,11 @@ export default class DHWeapon extends AttachableItem { game.i18n.localize(`DAGGERHEART.CONFIG.Burden.${burden}`) ]; - if (attack.damage.main) { - const { value, type } = attack.damage.main; + for (const { value, type } of attack.damage.parts) { const parts = value.custom.enabled ? [game.i18n.localize('DAGGERHEART.GENERAL.custom')] : [value.dice]; if (!value.custom.enabled && value.bonus) parts.push(value.bonus.signedString()); - if (type?.size) { + if (type.size > 0) { const typeTags = Array.from(type) .map(t => game.i18n.localize(`DAGGERHEART.CONFIG.DamageType.${t}.abbreviation`)) .join(' | '); @@ -250,7 +238,7 @@ export default class DHWeapon extends AttachableItem { tags.push(parts.join('')); } - + return tags; } @@ -265,10 +253,10 @@ export default class DHWeapon extends AttachableItem { if (roll.trait) labels.push(game.i18n.localize(`DAGGERHEART.CONFIG.Traits.${roll.trait}.short`)); if (range) labels.push(game.i18n.localize(`DAGGERHEART.CONFIG.Range.${range}.short`)); - for (const { value, type } of [damage.main, ...damage.resources].filter(d => !!d)) { + for (const { value, type } of damage.parts) { const str = Roll.replaceFormulaData(value.getFormula(), this.actor?.getRollData() ?? {}); - const icons = Array.from(type ?? []) + const icons = Array.from(type) .map(t => CONFIG.DH.GENERAL.damageTypes[t]?.icon) .filter(Boolean); @@ -281,4 +269,8 @@ export default class DHWeapon extends AttachableItem { return labels; } + + get itemFeatures() { + return this.weaponFeatures; + } } diff --git a/module/data/registeredTriggers.mjs b/module/data/registeredTriggers.mjs index 64e7f93e..ab86351c 100644 --- a/module/data/registeredTriggers.mjs +++ b/module/data/registeredTriggers.mjs @@ -149,15 +149,12 @@ export default class RegisteredTriggers extends Map { const result = await command(...args); if (result?.updates?.length) updates.push(...result.updates); - } catch { - const item = await foundry.utils.fromUuid(itemUuid); + } catch (_) { const triggerName = game.i18n.localize(triggerData.label); - console.error( + ui.notifications.error( game.i18n.format('DAGGERHEART.CONFIG.Triggers.triggerError', { trigger: triggerName, - actor: currentActor?.name, - item: item?.name ?? '', - itemUuid: item?.uuid ?? '' + actor: currentActor?.name }) ); } diff --git a/module/data/settings/Appearance.mjs b/module/data/settings/Appearance.mjs index 16f5fac0..4db27be0 100644 --- a/module/data/settings/Appearance.mjs +++ b/module/data/settings/Appearance.mjs @@ -41,11 +41,6 @@ export default class DhAppearance extends foundry.abstract.DataModel { choices: CONFIG.DH.GENERAL.fearDisplay, initial: CONFIG.DH.GENERAL.fearDisplay.token.value }), - fearPosition: new StringField({ - required: true, - choices: CONFIG.DH.GENERAL.fearPosition, - initial: CONFIG.DH.GENERAL.fearPosition.topCenter.value - }), displayCountdownUI: new BooleanField({ initial: true }), diceSoNice: new SchemaField({ hope: diceStyle({ fg: '#ffffff', bg: '#ffe760', outline: '#000000', edge: '#ffffff' }), diff --git a/module/data/settings/Automation.mjs b/module/data/settings/Automation.mjs index 523ddaac..35e87327 100644 --- a/module/data/settings/Automation.mjs +++ b/module/data/settings/Automation.mjs @@ -196,13 +196,6 @@ export default class DhAutomation extends foundry.abstract.DataModel { }) }) }), - reload: new fields.StringField({ - required: true, - choices: CONFIG.DH.SETTINGS.reloadChoices, - initial: CONFIG.DH.SETTINGS.reloadChoices.manual.id, - label: 'DAGGERHEART.SETTINGS.Automation.FIELDS.reload.label', - hint: 'DAGGERHEART.SETTINGS.Automation.FIELDS.reload.hint' - }), autoExpireActiveEffects: new fields.BooleanField({ required: true, initial: true, diff --git a/module/data/tagTeamData.mjs b/module/data/tagTeamData.mjs index ef6536f1..640c2f6c 100644 --- a/module/data/tagTeamData.mjs +++ b/module/data/tagTeamData.mjs @@ -1,5 +1,3 @@ -import { ChatDamageData } from './chat-message/chatDamageData.mjs'; - export default class TagTeamData extends foundry.abstract.DataModel { static defineSchema() { const fields = foundry.data.fields; @@ -39,7 +37,6 @@ export class MemberData extends foundry.abstract.DataModel { }), rollChoice: new fields.StringField({ nullable: true, initial: null }), rollData: new fields.JSONField({ nullable: true, initial: null }), - damageRollData: new fields.EmbeddedDataField(ChatDamageData), selected: new fields.BooleanField({ initial: false }) }; } diff --git a/module/dice/baseRoll.mjs b/module/dice/baseRoll.mjs index 2c42d38a..4d065fff 100644 --- a/module/dice/baseRoll.mjs +++ b/module/dice/baseRoll.mjs @@ -4,8 +4,4 @@ export default class BaseRoll extends Roll { /** @inheritdoc */ static TOOLTIP_TEMPLATE = 'systems/daggerheart/templates/ui/chat/foundryRollTooltip.hbs'; - - get modifierTotal() { - return this.total - this.dice.reduce((acc, dice) => acc + dice.total, 0); - } } diff --git a/module/dice/d20Roll.mjs b/module/dice/d20Roll.mjs index 7dc06741..c0069822 100644 --- a/module/dice/d20Roll.mjs +++ b/module/dice/d20Roll.mjs @@ -107,12 +107,6 @@ export default class D20Roll extends DHRoll { this.options.data.companion; actorExperiences = companion?.system?.experiences ?? {}; } - for (const m of this.options.experiences?.filter(m => !!actorExperiences[m]) ?? []) { - this.options.roll.modifiers.push({ - label: actorExperiences[m].name, - value: actorExperiences[m].value - }); - } this.addModifiers(); if (this.options.extraFormula) { @@ -185,10 +179,8 @@ export default class D20Roll extends DHRoll { return changeKeys; } - static async buildEvaluate(roll, config = {}, message = {}) { - await super.buildEvaluate(roll, config, message); - - const data = config.roll; + static postEvaluate(roll, config = {}) { + const data = super.postEvaluate(roll, config); data.type = config.actionType; data.difficulty = config.roll.difficulty; if (config.targets?.length) { @@ -224,6 +216,7 @@ export default class D20Roll extends DHRoll { }; }); data.modifierTotal = roll.modifierTotal; + return data; } resetFormula() { diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs index 683d14d8..ef810ed7 100644 --- a/module/dice/damageRoll.mjs +++ b/module/dice/damageRoll.mjs @@ -13,34 +13,30 @@ export default class DamageRoll extends DHRoll { static DefaultDialog = DamageDialog; - static createRollInstance(config) { - return new this(undefined, config.data, config); - } - - /** @inheritdoc */ - static async buildEvaluate(roll, config = {}) { - if (config.dialog.configure === false) roll.constructFormulas(config); - - const evaluateRoll = async roll => { - await roll.roll.evaluate(); - roll.roll.options = { damageTypes: roll.damageTypes ? [...roll.damageTypes] : [] }; - return roll.roll; - } - - if (!config.damage) config.damage = { main: null, resources: {} }; - - if (config.damageFormula) { - config.damage.main = await evaluateRoll(config.damageFormula); - config.damage.main.options = { damageTypes: - config.damageFormula.damageTypes ? [...config.damageFormula.damageTypes] : [] - }; - } - - for (const roll of config.resourceFormulas) { - config.damage.resources[roll.applyTo] = await evaluateRoll(roll); - } + static async buildEvaluate(roll, config = {}, message = {}) { + if (config.dialog.configure === false) roll.constructFormula(config); + if (config.evaluate !== false) for (const roll of config.roll) await roll.roll.evaluate(); roll._evaluated = true; + + const parts = []; + for (const roll of config.roll) { + parts.push(this.postEvaluate(roll)); + roll.roll = JSON.stringify(roll.roll.toJSON()); + } + + config.damage = this.unifyDamageRoll(parts); + } + + static postEvaluate(roll, config = {}) { + return { + ...roll, + ...super.postEvaluate(roll.roll, config), + damageTypes: [...(roll.damageTypes ?? [])], + roll: roll.roll, + type: config.type, + modifierTotal: this.calculateTotalModifiers(roll.roll) + }; } static async buildPost(roll, config, message) { @@ -51,10 +47,9 @@ export default class DamageRoll extends DHRoll { const diceRolls = []; if (game.modules.get('dice-so-nice')?.active) { config.mute = true; - const pool = foundry.dice.terms.PoolTerm.fromRolls([ - ...(config.damage.main ? [config.damage.main] : []), - ...Object.values(config.damage.resources) - ]); + const pool = foundry.dice.terms.PoolTerm.fromRolls( + Object.values(config.damage).flatMap(r => r.parts.map(p => p.roll)) + ); diceRolls.push(Roll.fromTerms([pool])); } @@ -65,14 +60,22 @@ export default class DamageRoll extends DHRoll { await super.buildPost(roll, config, message); if (config.source?.message) { - chatMessage.update({ 'system.damage': { - ...config.damage.toObject(), - main: config.damage.main, - resources: config.damage.resources - }}); + chatMessage.update({ 'system.damage': config.damage }); } } + static unifyDamageRoll(rolls) { + const unified = {}; + rolls.forEach(r => { + const resource = unified[r.applyTo] ?? { formula: '', total: 0, parts: [] }; + resource.formula += `${resource.formula !== '' ? ' + ' : ''}${r.formula}`; + resource.total += r.total; + resource.parts.push(r); + unified[r.applyTo] = resource; + }); + return unified; + } + static formatGlobal(rolls) { let formula, total; const applyTo = new Set(rolls.flatMap(r => r.applyTo)); @@ -121,10 +124,12 @@ export default class DamageRoll extends DHRoll { const type = this.options.messageType ?? (this.options.hasHealing ? 'healing' : 'damage'); const changeKeys = []; - for (const damageType of this.options.damageFormula?.damageTypes?.values?.() ?? []) { - changeKeys.push(`system.bonuses.${type}.${damageType}`); + for (const roll of this.options.roll) { + for (const damageType of roll.damageTypes?.values?.() ?? []) { + changeKeys.push(`system.bonuses.${type}.${damageType}`); + } } - + const item = this.data.parent?.items?.get(this.options.source.item); if (item) { switch (item.type) { @@ -140,69 +145,62 @@ export default class DamageRoll extends DHRoll { return changeKeys; } - constructFormulas(config) { - return { - damageFormula: this.constructFormula(this.options.damageFormula, config, true), - resourceFormulas: this.options.resourceFormulas.map(x => this.constructFormula(x, config)) - }; - } - - constructFormula(formulaData, config, isDamage) { - if (!formulaData) return null; + constructFormula(config) { this.options.isCritical = config.isCritical; - - formulaData.roll = new Roll(Roll.replaceFormulaData(formulaData.formula, config.data)); - formulaData.roll.terms = Roll.parse(formulaData.roll.formula, config.data); - - if (formulaData.extraFormula) { - formulaData.roll.terms.push( - new foundry.dice.terms.OperatorTerm({ operator: '+' }), - ...this.constructor.parse(formulaData.extraFormula, this.options.data) - ); - } - - if (isDamage && formulaData.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) { - formulaData.modifiers = this.applyBaseBonus(formulaData); - this.addModifiers(formulaData); - formulaData.modifiers?.forEach(m => { - formulaData.roll.terms.push(...this.formatModifier(m.value)); - }); - - /* To Remove When Reaction System */ - for (const mod in config.modifiers) { - const modifier = config.modifiers[mod]; - if ( - modifier.beforeCrit === true && - (modifier.enabled || modifier.value) - ) modifier.callback(formulaData); + for (const [index, part] of this.options.roll.entries()) { + const isHitpointPart = part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id; + part.roll = new Roll(Roll.replaceFormulaData(part.formula, config.data)); + part.roll.terms = Roll.parse(part.roll.formula, config.data); + if (part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) { + part.modifiers = this.applyBaseBonus(part); + this.addModifiers(part); + part.modifiers?.forEach(m => { + part.roll.terms.push(...this.formatModifier(m.value)); + }); } /* To Remove When Reaction System */ - for (const mod in config.modifiers) { - const modifier = config.modifiers[mod]; - if (!modifier.beforeCrit && (modifier.enabled || modifier.value)) modifier.callback(formulaData); + if (index === 0 && part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) { + for (const mod in config.modifiers) { + const modifier = config.modifiers[mod]; + if (modifier.beforeCrit === true && (modifier.enabled || modifier.value)) modifier.callback(part); + } } - if (config.damageOptions.groupAttack?.numAttackers > 1) { + if (part.extraFormula) { + part.roll.terms.push( + new foundry.dice.terms.OperatorTerm({ operator: '+' }), + ...this.constructor.parse(part.extraFormula, this.options.data) + ); + } + + if (config.damageOptions.groupAttack?.numAttackers > 1 && isHitpointPart) { const damageTypes = [foundry.dice.terms.Die, foundry.dice.terms.NumericTerm]; - for (const term of formulaData.roll.terms) { + for (const term of part.roll.terms) { if (damageTypes.some(type => term instanceof type)) { term.number *= config.damageOptions.groupAttack.numAttackers; } } } - if (config.isCritical) { - const total = formulaData.roll.dice.reduce((acc, term) => acc + term._faces * term._number, 0); + if (config.isCritical && isHitpointPart) { + const total = part.roll.dice.reduce((acc, term) => acc + term._faces * term._number, 0); if (total > 0) { - formulaData.roll.terms.push(...this.formatModifier(total)); + part.roll.terms.push(...this.formatModifier(total)); } } - } - formulaData.roll._formula = this.constructor.getFormula(formulaData.roll.terms); - - return formulaData; + /* To Remove When Reaction System */ + if (index === 0 && part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) { + for (const mod in config.modifiers) { + const modifier = config.modifiers[mod]; + if (!modifier.beforeCrit && (modifier.enabled || modifier.value)) modifier.callback(part); + } + } + + part.roll._formula = this.constructor.getFormula(part.roll.terms); + } + return this.options.roll; } /* To Remove When Reaction System */ @@ -295,4 +293,76 @@ export default class DamageRoll extends DHRoll { config.modifiers = mods; return mods; } + + static async reroll(rollPart, dice, result) { + let diceIndex = 0; + let parsedRoll = game.system.api.dice.DamageRoll.fromData({ + ...rollPart.roll, + terms: rollPart.roll.terms.map(term => { + const isDie = term.class === 'Die'; + const fixedTerm = { + ...term, + ...(isDie ? { results: rollPart.dice[diceIndex].results } : {}) + }; + + if (isDie) diceIndex++; + return fixedTerm; + }), + class: 'DamageRoll', + evaluated: false + }); + + const parsedDiceTerms = Object.keys(parsedRoll.terms).reduce((acc, key) => { + const term = parsedRoll.terms[key]; + if (term instanceof CONFIG.Dice.termTypes.DiceTerm) acc[Object.keys(acc).length] = term; + return acc; + }, {}); + const term = parsedDiceTerms[dice]; + const termResult = parsedDiceTerms[dice].results[result]; + + const newIndex = parsedDiceTerms[dice].results.length; + await term.reroll(`/r1=${termResult.result}`); + + const diceRolls = []; + if (game.modules.get('dice-so-nice')?.active) { + const newResult = parsedDiceTerms[dice].results[newIndex]; + diceRolls.push({ + _evaluated: true, + dice: [ + new foundry.dice.terms.Die({ + ...term, + total: newResult.result, + faces: term._faces, + results: [newResult] + }) + ], + options: { appearance: {} } + }); + } + + await triggerChatRollFx(diceRolls); + await parsedRoll.evaluate(); + + const results = parsedRoll.dice[dice].results.map(result => ({ + ...result, + discarded: !result.active + })); + const newResult = results.splice(results.length - 1, 1); + results.splice(Number(result) + 1, 0, newResult[0]); + + const rerolledDice = parsedRoll.dice.map((x, index) => { + const isRerollDice = index === Number(dice); + if (!isRerollDice) return { ...x, dice: x.denomination }; + return { + dice: parsedRoll.dice[dice].denomination, + total: parsedRoll.dice[dice].total, + results: results.map(result => ({ + ...result, + hasRerolls: result.hasRerolls || isRerollDice + })) + }; + }); + + return { parsedRoll, rerolledDice }; + } } diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index 68185984..c28db98f 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -1,8 +1,7 @@ import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; import { triggerChatRollFx } from '../helpers/utils.mjs'; -import BaseRoll from './baseRoll.mjs'; -export default class DHRoll extends BaseRoll { +export default class DHRoll extends Roll { baseTerms = []; constructor(formula, data = {}, options = {}) { super(formula, data, foundry.utils.mergeObject(options, { roll: [] }, { overwrite: false })); @@ -24,31 +23,17 @@ export default class DHRoll extends BaseRoll { static DefaultDialog = D20RollDialog; - /** - * @param {Partial} config - * @returns {Promise} - */ static async build(config = {}, message = {}) { const roll = await this.buildConfigure(config, message); if (!roll) return; if (config.skips?.createMessage) config.messageRoll = roll; - if (config.evaluate !== false) { - await this.buildEvaluate(roll, config, (message = {})); - } + await this.buildEvaluate(roll, config, (message = {})); await this.buildPost(roll, config, (message = {})); return config; } - static createRollInstance(config) { - return new this(config.roll.formula, config.data, config); - } - - /** - * @param {Partial} config - * @returns {Promise} - */ static async buildConfigure(config = {}, message = {}) { config.hooks = [...this.getHooks(), '']; config.dialog ??= {}; @@ -62,7 +47,7 @@ export default class DHRoll extends BaseRoll { this.temporaryModifierBuilder(config); - let roll = this.createRollInstance(config); + let roll = new this(config.roll.formula, config.data, config); if (config.dialog.configure !== false) { // Open Roll Dialog const DialogClass = config.dialog?.class ?? this.DefaultDialog; @@ -79,30 +64,13 @@ export default class DHRoll extends BaseRoll { return roll; } - /** - * Evaluates the roll and assigns roll data into the config. - * This is only called if config.evaluate is not set to false - * @protected - */ static async buildEvaluate(roll, config = {}, message = {}) { - await roll.evaluate(); - config.roll = { - ...roll.options.roll, - total: roll.total, - formula: roll.formula, - dice: roll.dice.map(d => ({ - dice: d.denomination, - total: d.total, - formula: d.formula, - results: d.results - })) - }; + if (config.evaluate !== false) { + await roll.evaluate(); + config.roll = this.postEvaluate(roll, config); + } } - /** - * Runs any post configuration events that need to happen towards the end, such as hooks and dice so nice - * @protected - */ static async buildPost(roll, config, message) { for (const hook of config.hooks) { if (Hooks.call(`${CONFIG.DH.id}.postRoll${hook.capitalize()}`, config, message) === false) return null; @@ -115,13 +83,23 @@ export default class DHRoll extends BaseRoll { } } + static postEvaluate(roll, config = {}) { + return { + ...roll.options.roll, + total: roll.total, + formula: roll.formula, + dice: roll.dice.map(d => ({ + dice: d.denomination, + total: d.total, + formula: d.formula, + results: d.results + })) + }; + } + static async toMessage(roll, config) { const item = config.data.parent?.items?.get?.(config.source.item) ?? null; - const actions = item ? [ - ...item.system.actions, - ...(item.system.attack?.id === config.source.action ? [item.system.attack] : []) - ] : []; - const action = actions.find(x => x.id === config.source.action); + const action = item ? item.system.actions.get(config.source.action) : null; let actionDescription = null; if (action?.chatDisplay) { actionDescription = action @@ -133,14 +111,6 @@ export default class DHRoll extends BaseRoll { config.actionChatMessageHandled = true; } - const reloadSetting = - game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).reload; - const useReload = - item?.system.hasReload && - action?.type === 'attack' && - reloadSetting === CONFIG.DH.SETTINGS.reloadChoices.auto.id; - const reloadResult = useReload ? await action?.handleReload?.() : {}; - const cls = getDocumentClass('ChatMessage'), msgData = { type: this.messageType, @@ -148,11 +118,7 @@ export default class DHRoll extends BaseRoll { title: roll.title, speaker: cls.getSpeaker({ actor: roll.data?.parent }), sound: config.mute ? null : CONFIG.sounds.dice, - system: { - ...config, - actionDescription, - reloadCheckValue: reloadResult.rollValue - }, + system: { ...config, actionDescription }, rolls: [roll] }; @@ -174,17 +140,14 @@ export default class DHRoll extends BaseRoll { if (!this._evaluated) return; const metagamingSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming); - const automationSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); const chatData = await this._prepareChatRenderContext({ flavor, isPrivate, ...options }); return foundry.applications.handlebars.renderTemplate(template, { roll: this, ...chatData, - action: chatData.action, parent: chatData.parent, targetMode: chatData.targetMode, areas: chatData.action?.areas, - metagamingSettings, - automationSettings + metagamingSettings }); } diff --git a/module/dice/die/_module.mjs b/module/dice/die/_module.mjs index b84cef86..19ca951a 100644 --- a/module/dice/die/_module.mjs +++ b/module/dice/die/_module.mjs @@ -3,7 +3,6 @@ import HopeDie from './hopeDie.mjs'; import FearDie from './fearDie.mjs'; import AdvantageDie from './advantageDie.mjs'; import DisadvantageDie from './disadvantageDie.mjs'; -export { default as BaseDie } from './baseDie.mjs'; export const diceTypes = { DualityDie, diff --git a/module/dice/die/advantageDie.mjs b/module/dice/die/advantageDie.mjs index 66b6f124..9c2f0b03 100644 --- a/module/dice/die/advantageDie.mjs +++ b/module/dice/die/advantageDie.mjs @@ -1,6 +1,4 @@ -import BaseDie from './baseDie.mjs'; - -export default class AdvantageDie extends BaseDie { +export default class AdvantageDie extends foundry.dice.terms.Die { constructor(options) { super(options); diff --git a/module/dice/die/baseDie.mjs b/module/dice/die/baseDie.mjs deleted file mode 100644 index cc88f753..00000000 --- a/module/dice/die/baseDie.mjs +++ /dev/null @@ -1,12 +0,0 @@ -export default class BaseDie extends foundry.dice.terms.Die { - async rerollResult(resultIndex) { - const result = this.results[resultIndex]; - result.rerolled = true; - result.active = false; - await this.roll({ reroll: true }); - - const rerolledResult = this.results[this.results.length - 1]; - this.results.splice(this.results.length - 1, 1); - this.results.splice(resultIndex, 0, rerolledResult); - } -} \ No newline at end of file diff --git a/module/dice/die/disadvantageDie.mjs b/module/dice/die/disadvantageDie.mjs index e79845f3..f56ebe96 100644 --- a/module/dice/die/disadvantageDie.mjs +++ b/module/dice/die/disadvantageDie.mjs @@ -1,6 +1,4 @@ -import BaseDie from './baseDie.mjs'; - -export default class DisadvantageDie extends BaseDie { +export default class DisadvantageDie extends foundry.dice.terms.Die { constructor(options) { super(options); diff --git a/module/dice/die/dualityDie.mjs b/module/dice/die/dualityDie.mjs index 2f4dae77..cc7ee75e 100644 --- a/module/dice/die/dualityDie.mjs +++ b/module/dice/die/dualityDie.mjs @@ -1,7 +1,6 @@ -import BaseDie from './baseDie.mjs'; import { updateResourcesForDualityReroll } from '../helpers.mjs'; -export default class DualityDie extends BaseDie { +export default class DualityDie extends foundry.dice.terms.Die { constructor(options) { super(options); diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 6503efb1..1cfed094 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -1,6 +1,6 @@ import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; import D20Roll from './d20Roll.mjs'; -import { parseRallyDice, setDiceSoNiceForDualityRoll, shouldUseHopeFearAutomation } from '../helpers/utils.mjs'; +import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs'; import { getDiceSoNicePresets } from '../config/generalConfig.mjs'; import { updateResourcesForDualityReroll } from './helpers.mjs'; @@ -232,41 +232,9 @@ export default class DualityRoll extends D20Roll { return changeKeys; } - /** @inheritdoc */ static async buildEvaluate(roll, config = {}, message = {}) { await super.buildEvaluate(roll, config, message); - config.roll.hope = { - dice: roll.dHope.denomination, - value: this.guaranteedCritical ? 0 : roll.dHope.total, - rerolled: { - any: roll.dHope.results.some(x => x.rerolled), - rerolls: roll.dHope.results.filter(x => x.rerolled) - } - }; - config.roll.fear = { - dice: roll.dFear.denomination, - value: this.guaranteedCritical ? 0 : roll.dFear.total, - rerolled: { - any: roll.dFear.results.some(x => x.rerolled), - rerolls: roll.dFear.results.filter(x => x.rerolled) - } - }; - config.roll.rally = { - dice: roll.dRally?.denomination, - value: roll.dRally?.total - }; - config.roll.result = { - duality: roll.withHope ? 1 : roll.withFear ? -1 : 0, - total: this.guaranteedCritical ? 0 : roll.dHope.total + roll.dFear.total, - label: roll.totalLabel - }; - if (roll._rallyIndex && roll.data?.parent) - roll.data.parent.deleteEmbeddedDocuments('ActiveEffect', [roll._rallyIndex]); - } - - /** @inheritdoc */ - static async buildPost(roll, config, message) { await setDiceSoNiceForDualityRoll( roll, config.roll.advantage.type, @@ -274,7 +242,44 @@ export default class DualityRoll extends D20Roll { config.roll.fear.dice, config.roll.advantage.dice ); + } + static postEvaluate(roll, config = {}) { + const data = super.postEvaluate(roll, config); + + data.hope = { + dice: roll.dHope.denomination, + value: this.guaranteedCritical ? 0 : roll.dHope.total, + rerolled: { + any: roll.dHope.results.some(x => x.rerolled), + rerolls: roll.dHope.results.filter(x => x.rerolled) + } + }; + data.fear = { + dice: roll.dFear.denomination, + value: this.guaranteedCritical ? 0 : roll.dFear.total, + rerolled: { + any: roll.dFear.results.some(x => x.rerolled), + rerolls: roll.dFear.results.filter(x => x.rerolled) + } + }; + data.rally = { + dice: roll.dRally?.denomination, + value: roll.dRally?.total + }; + data.result = { + duality: roll.withHope ? 1 : roll.withFear ? -1 : 0, + total: this.guaranteedCritical ? 0 : roll.dHope.total + roll.dFear.total, + label: roll.totalLabel + }; + + if (roll._rallyIndex && roll.data?.parent) + roll.data.parent.deleteEmbeddedDocuments('ActiveEffect', [roll._rallyIndex]); + + return data; + } + + static async buildPost(roll, config, message) { await super.buildPost(roll, config, message); await DualityRoll.dualityUpdate(config); @@ -307,9 +312,11 @@ export default class DualityRoll extends D20Roll { } static async addDualityResourceUpdates(config) { + const automationSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); + const hopeFearAutomation = automationSettings.hopeFear; if ( !config.source?.actor || - !shouldUseHopeFearAutomation() || + (game.user.isGM ? !hopeFearAutomation.gm : !hopeFearAutomation.players) || config.actionType === 'reaction' || config.skips?.resources ) @@ -327,15 +334,15 @@ export default class DualityRoll extends D20Roll { const fear = (config.roll.result.duality === -1 ? 1 : 0) - (config.rerolledRoll.result.duality === -1 ? 1 : 0); - if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true }); - if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true }); - if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true }); + if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true }); + if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true }); + if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true }); } } else { if (config.roll.isCritical || config.roll.result.duality === 1) - updates.push({ key: 'hope', value: 1, enabled: true }); - if (config.roll.isCritical) updates.push({ key: 'stress', value: -1, enabled: true }); - if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, enabled: true }); + updates.push({ key: 'hope', value: 1, total: -1, enabled: true }); + if (config.roll.isCritical) updates.push({ key: 'stress', value: -1, total: 1, enabled: true }); + if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, total: -1, enabled: true }); } if (updates.length) { @@ -409,4 +416,8 @@ export default class DualityRoll extends D20Roll { return rerolled; } + + fromJSON(json) { + return super.fromJSON(json); + } } diff --git a/module/dice/fateRoll.mjs b/module/dice/fateRoll.mjs index f8276ce1..114fad59 100644 --- a/module/dice/fateRoll.mjs +++ b/module/dice/fateRoll.mjs @@ -75,23 +75,25 @@ export default class FateRoll extends D20Roll { this.terms[0] = new foundry.dice.terms.Die({ faces: 12 }); } - /** @inheritdoc */ static async buildEvaluate(roll, config = {}, message = {}) { await super.buildEvaluate(roll, config, message); - config.roll.fate = { - dice: roll.fateDie === 'Hope' ? roll.dHope.denomination : roll.dFear.denomination, - value: roll.fateDie === 'Hope' ? roll.dHope.total : roll.dFear.total, - fateDie: roll.fateDie - }; - } - /** @inheritdoc */ - static async buildPost(roll, config, message) { if (roll.fateDie === 'Hope') { await setDiceSoNiceForHopeFateRoll(roll, config.roll.fate.dice); } else { await setDiceSoNiceForFearFateRoll(roll, config.roll.fate.dice); } - return super.buildPost(roll, config, message); + } + + static postEvaluate(roll, config = {}) { + const data = super.postEvaluate(roll, config); + + data.fate = { + dice: roll.fateDie === 'Hope' ? roll.dHope.denomination : roll.dFear.denomination, + value: roll.fateDie === 'Hope' ? roll.dHope.total : roll.dFear.total, + fateDie: roll.fateDie + }; + + return data; } } diff --git a/module/dice/helpers.mjs b/module/dice/helpers.mjs index d03970d0..35adb8b7 100644 --- a/module/dice/helpers.mjs +++ b/module/dice/helpers.mjs @@ -1,28 +1,19 @@ import { ResourceUpdateMap } from '../data/action/baseAction.mjs'; export function updateResourcesForDualityReroll(oldDuality, newDuality, actor) { + const { hopeFear } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); + if (game.user.isGM ? !hopeFear.gm : !hopeFear.players) return; + + const updates = []; const hope = (newDuality >= 0 ? 1 : 0) - (oldDuality >= 0 ? 1 : 0); const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0); const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0); - const { hopeFear, countdownAutomation } = - game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); + if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true }); + if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true }); + if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true }); - if (game.user.isGM ? hopeFear.gm : hopeFear.players) { - const updates = []; - if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true }); - if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true }); - if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true }) - - const resourceUpdates = new ResourceUpdateMap(actor); - resourceUpdates.addResources(updates); - resourceUpdates.updateResources(); - } - - if (countdownAutomation && fear !== 0) { - game.system.api.applications.ui.DhCountdowns.updateCountdowns({ - type: CONFIG.DH.GENERAL.countdownProgressionTypes.fear.id, - undo: fear === 1 ? false : true - }); - } + const resourceUpdates = new ResourceUpdateMap(actor); + resourceUpdates.addResources(updates); + resourceUpdates.updateResources(); } diff --git a/module/documents/_types.d.ts b/module/documents/_types.d.ts deleted file mode 100644 index a3af1b33..00000000 --- a/module/documents/_types.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -import BaseDataActor from '../data/actor/base.mjs' -import DHItem from './item.mjs'; -import BaseDataItem from '../data/item/base.mjs'; -import DhActiveEffect from './activeEffect.mjs'; -import EmbeddedCollection from '@common/abstract/embedded-collection.mjs'; -import DHToken from './token.mjs'; -import Actor from '@client/documents/actor.mjs'; -import Item from '@client/documents/item.mjs'; - -declare module './actor.mjs' { - export default interface DhpActor extends Actor { - system: T; - items: EmbeddedCollection; - effects: EmbeddedCollection; - get token(): DHToken | null; - - /** @inheritdoc */ - getActiveTokens(linked?: boolean, document?: boolean): (DHToken | foundry.canvas.placeables.Token)[]; - getActiveTokens(linked?: boolean, document: true): DHToken[]; - getActiveTokens(linked?: boolean, document: false): foundry.canvas.placeables.Token[]; - } -} - -declare module './item.mjs' { - export default interface DHItem extends Item { - parent: DhpActor; - actor: DhpActor; - system: T; - effects: EmbeddedCollection; - } -} \ No newline at end of file diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index 4a9f3cc4..3518210b 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -65,10 +65,6 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { ); } - get hasDescription() { - return Boolean(this.description); - } - /* -------------------------------------------- */ /* Event Handlers */ /* -------------------------------------------- */ @@ -216,7 +212,7 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { try { const evl = new Function('sandbox', `with (sandbox) { return ${expression}}`); result = evl(Roll.MATH_PROXY); - } catch { + } catch (err) { return expression; } @@ -228,13 +224,12 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { * @returns {string[]} An array of localized tag strings. */ _getTags() { - const tags = []; - const originActor = DhActiveEffect.#resolveParentDocument(fromUuidSync(this.origin, { strict: false }), Actor); - if (originActor && originActor !== this.actor) { - tags.push(_loc('DAGGERHEART.EFFECTS.OriginTag', { name: originActor.name })); - } else if (!(this.parent instanceof Actor)) { - tags.push(`${_loc(this.parent.system.metadata.label)}: ${this.parent.name}`); - } + const tags = [ + `${game.i18n.localize(this.parent.system.metadata.label)}: ${this.parent.name}`, + game.i18n.localize( + this.isTemporary ? 'DAGGERHEART.EFFECTS.Duration.temporary' : 'DAGGERHEART.EFFECTS.Duration.passive' + ) + ]; for (const statusId of this.statuses) { const status = CONFIG.statusEffects.find(s => s.id === statusId); diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 666d9ac1..fb10435f 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -34,14 +34,12 @@ export default class DhpActor extends Actor { super.prepareData(); // Update effects if it is the user's character or is controlled - // A timeout avoids an infinite loop when accessing token actors before the delta is finished constructing - window.setTimeout(() => { - if (!canvas.ready) return; + if (canvas.ready) { const controlled = canvas.tokens.controlled.some(t => t.actor === this); if (game.user.character === this || controlled) { - ui.effectsDisplay.refresh(); + ui.effectsDisplay.render(); } - }, 0); + } } /* -------------------------------------------- */ @@ -533,7 +531,21 @@ export default class DhpActor extends Actor { } /** - * @param {Partial} config + * @param {object} config + * @param {Event} config.event + * @param {string} config.title + * @param {object} config.roll + * @param {number} config.roll.modifier + * @param {boolean} [config.roll.simple=false] + * @param {string} [config.roll.type] + * @param {number} [config.roll.difficulty] + * @param {boolean} [config.hasDamage] + * @param {boolean} [config.hasEffect] + * @param {object} [config.chatMessage] + * @param {string} config.chatMessage.template + * @param {boolean} [config.chatMessage.mute] + * @param {object} [config.targets] + * @param {object} [config.costs] */ async diceRoll(config) { config.source = { ...(config.source ?? {}), actor: this.uuid }; @@ -551,7 +563,7 @@ export default class DhpActor extends Actor { headerTitle: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { ability: abilityLabel }), - effects: await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects(this), + effects: await game.system.api.data.actions.actionsTypes.base.getEffects(this), roll: { trait: trait, type: 'trait' @@ -622,63 +634,53 @@ export default class DhpActor extends Actor { return rollData; } - /** - * Checks to see if damage can be reduced in one way or another. - * @param {number} hpDamage the amount of marked hp that will be marked - * @param {Set} types a list of damage types - */ - #canReduceDamage(hpDamage, types) { - const { stressDamageReduction, disabledArmor, reduceSeverity, thresholdImmunities } = - this.system.rules.damageReduction; + #canReduceDamage(hpDamage, type) { + const { stressDamageReduction, disabledArmor } = this.system.rules.damageReduction; if (disabledArmor) return false; const availableStress = this.system.resources.stress.max - this.system.resources.stress.value; const canUseArmor = this.system.armorScore.value < this.system.armorScore.max && - types.every(t => this.system.armorApplicableDamageTypes[t] === true); - + type.every(t => this.system.armorApplicableDamageTypes[t] === true); const canUseStress = Object.keys(stressDamageReduction).reduce((acc, x) => { const rule = stressDamageReduction[x]; if (damageKeyToNumber(x) <= hpDamage) return acc || (rule.enabled && availableStress >= rule.cost); return acc; }, false); - const hasReduceSeverity = types.some(t => reduceSeverity[t]); - - const hasThresholdImmunity = Object.entries(thresholdImmunities) - .filter(([key, value]) => Boolean(value) && damageKeyToNumber(key) === hpDamage) - .length; - - return canUseArmor || canUseStress || hasReduceSeverity || hasThresholdImmunity; + return canUseArmor || canUseStress; } - async takeDamage(args, isDirect = false) { - args = this.#parseDamageArgs(args); - if (Hooks.call(`${CONFIG.DH.id}.preTakeDamage`, this, args) === false) return null; + async takeDamage(damages, isDirect = false) { + if (Hooks.call(`${CONFIG.DH.id}.preTakeDamage`, this, damages) === false) return null; if (this.type === 'companion') { await this.modifyResource([{ value: 1, key: 'stress' }]); return; } - const updates = args.resourceUpdates; - if (args.main) { - // todo: avoid side effects, but hook currently requires it - args.main.value = this.calculateDamage(args.main.value, args.main.damageTypes); - } + const updates = []; - if (Hooks.call(`${CONFIG.DH.id}.postCalculateDamage`, this, args) === false) return null; + Object.entries(damages).forEach(([key, damage]) => { + damage.parts.forEach(part => { + if (part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) + part.total = this.calculateDamage(part.total, part.damageTypes); + const update = updates.find(u => u.key === key); + if (update) { + update.value += part.total; + update.damageTypes.add(...new Set(part.damageTypes)); + } else updates.push({ value: part.total, key, damageTypes: new Set(part.damageTypes) }); + }); + }); - // Convert deducted resources to a record of updates. Return if nothing to do. - if (!updates.some(u => u.value) && !args.main) return; + if (Hooks.call(`${CONFIG.DH.id}.postCalculateDamage`, this, damages) === false) return null; - if (args.main) { - const hpDamage = { - value: this.convertDamageToThreshold(args.main.value), - damageTypes: new Set(args.main.damageTypes), - key: CONFIG.DH.GENERAL.healingTypes.hitPoints.id - }; + if (!updates.length) return; + + const hpDamage = updates.find(u => u.key === CONFIG.DH.GENERAL.healingTypes.hitPoints.id); + if (hpDamage?.value) { + hpDamage.value = this.convertDamageToThreshold(hpDamage.value); if (this.type === 'character' && !isDirect && this.#canReduceDamage(hpDamage.value, hpDamage.damageTypes)) { const armorSlotResult = await this.owner.query( 'armorSlot', @@ -693,7 +695,7 @@ export default class DhpActor extends Actor { ); if (armorSlotResult) { const { modifiedDamage, armorChanges, stressSpent } = armorSlotResult; - hpDamage.value = modifiedDamage; + updates.find(u => u.key === 'hitPoints').value = modifiedDamage; for (const armorChange of armorChanges) { updates.push({ value: armorChange.amount, key: 'armor', uuid: armorChange.uuid }); } @@ -703,23 +705,19 @@ export default class DhpActor extends Actor { else updates.push({ value: stressSpent, key: 'stress' }); } } - } else if (this.type === 'adversary') { + } + if (this.type === 'adversary') { const reducedSeverity = hpDamage.damageTypes.reduce((value, curr) => { return Math.max(this.system.rules.damageReduction.reduceSeverity[curr], value); }, 0); hpDamage.value = Math.max(hpDamage.value - reducedSeverity, 0); - if (this.system.rules.damageReduction.thresholdImmunities[getDamageKey(hpDamage.value)]) { - hpDamage.value = Math.max(0, hpDamage.value - 1); - } - } - // Merge existing hitPoint deduction with finalised damage deduction - const existing = updates.find(u => u.key === CONFIG.DH.GENERAL.healingTypes.hitPoints.id); - if (existing) { - existing.value += hpDamage.value; - existing.damageTypes = hpDamage.damageTypes; - } else { - updates.push(hpDamage); + if ( + hpDamage.value && + this.system.rules.damageReduction.thresholdImmunities[getDamageKey(hpDamage.value)] + ) { + hpDamage.value -= 1; + } } } @@ -735,10 +733,12 @@ export default class DhpActor extends Actor { for (var result of results) resourceMap.addResources(result.updates); resourceMap.updateResources(); } - - for (const u of updates) { - u.value = u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false ? u.value * -1 : u.value; - } + + updates.forEach( + u => + (u.value = + u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false ? u.value * -1 : u.value) + ); await this.modifyResource(updates); @@ -747,36 +747,6 @@ export default class DhpActor extends Actor { return updates; } - async takeHealing(args) { - args = this.#parseDamageArgs({ resources: 'resources' in args ? args.resources : args }); - if (Hooks.call(`${CONFIG.DH.id}.preTakeHealing`, this, args) === false) return null; - - const updates = args.resourceUpdates; - for (const u of updates) { - const shouldFlip = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false); - u.value = shouldFlip ? u.value * -1 : u.value; - } - await this.modifyResource(updates); - - if (Hooks.call(`${CONFIG.DH.id}.postTakeHealing`, this, updates) === false) return null; - - return updates; - } - - /** Parse damage args that may be coming from takeHealing or takeDamage. Used to simplify macro usage and roll vs non-roll usage */ - #parseDamageArgs(args = {}) { - const damageRoll = 'total' in args ? args : (args.main ?? args.damage); - const damageValue = typeof damageRoll === 'number' ? damageRoll : damageRoll?.total; - const damageTypes = Array.from(damageRoll?.options?.damageTypes ?? damageRoll?.damageTypes ?? []); - const main = typeof damageValue === 'number' ? { key: 'damage', value: damageValue, damageTypes } : null; - const resourceUpdates = Object.entries(args.resources ?? {}).map(([key, damage]) => ({ - key, - value: typeof damage === 'number' ? damage : damage?.total ?? 0 - })); - - return { main, resourceUpdates }; - } - calculateDamage(baseDamage, type) { if (this.canResist(type, 'immunity')) return 0; if (this.canResist(type, 'resistance')) baseDamage = Math.ceil(baseDamage / 2); @@ -801,6 +771,32 @@ export default class DhpActor extends Actor { return reduction === Infinity ? 0 : reduction; } + async takeHealing(healings) { + if (Hooks.call(`${CONFIG.DH.id}.preTakeHealing`, this, healings) === false) return null; + + const updates = []; + Object.entries(healings).forEach(([key, healing]) => { + healing.parts.forEach(part => { + const update = updates.find(u => u.key === key); + if (update) update.value += part.total; + else updates.push({ value: part.total, key }); + }); + }); + + updates.forEach( + u => + (u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false) + ? u.value * -1 + : u.value) + ); + + await this.modifyResource(updates); + + if (Hooks.call(`${CONFIG.DH.id}.postTakeHealing`, this, updates) === false) return null; + + return updates; + } + /** * Resources are modified asynchronously, so be careful not to update the same resource in * quick succession. diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs index d53a76bd..480f8c69 100644 --- a/module/documents/chatMessage.mjs +++ b/module/documents/chatMessage.mjs @@ -3,13 +3,6 @@ import { emitGMUpdate, emitGMCreate, GMUpdateEvent } from '../systemRegistration export default class DhpChatMessage extends foundry.documents.ChatMessage { targetHook = null; - static #EXPAND_SECTIONS = [ - { selector: 'roll-section [data-action="expandRoll"]', key: 'roll' }, - { selector: 'damage-section', key: 'damage' }, - { selector: 'target-section', key: 'target' }, - { selector: 'description-section', key: 'desc' } - ]; - async renderHTML() { const actor = game.actors.get(this.speaker.actor); const actorData = @@ -96,26 +89,23 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { } } - // Check registered selectors and the main item section for expanding - // Preserving during re-render is handled by core foundry on anything with [data-action=expandRoll] const autoExpandRoll = game.settings.get( - CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance - ).expandRollMessage; - for (const { selector, key } of DhpChatMessage.#EXPAND_SECTIONS) { - const elements = html.querySelectorAll(selector); - for (const element of elements) { - element.classList.toggle('expanded', autoExpandRoll[key]); - } - } - - // Auto expand the item description. These are not preserved by foundry during re-renders - const itemDesc = html.querySelector('details'); - if (itemDesc) { - const existing = document.querySelector(`.chat-message[data-message-id="${this.id}"] details`); - if (existing?.hasAttribute('open') ?? autoExpandRoll.desc) { - itemDesc.setAttribute('open', ''); - } - } + CONFIG.DH.id, + CONFIG.DH.SETTINGS.gameSettings.appearance + ).expandRollMessage, + rollSections = html.querySelectorAll('.roll-part'), + itemDesc = html.querySelector('.domain-card-move'); + rollSections.forEach(s => { + if (s.classList.contains('roll-section')) { + const toExpand = s.querySelector('[data-action="expandRoll"]'); + toExpand.classList.toggle('expanded', autoExpandRoll.roll); + } else if (s.classList.contains('damage-section')) + s.classList.toggle('expanded', autoExpandRoll.damage); + else if (s.classList.contains('target-section')) s.classList.toggle('expanded', autoExpandRoll.target); + else if (s.classList.contains('description-section')) + s.classList.toggle('expanded', autoExpandRoll.desc); + }); + if (itemDesc && autoExpandRoll.desc) itemDesc.setAttribute('open', ''); } if (!this.isAuthor && !this.speakerActor?.isOwner) { @@ -177,7 +167,7 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { if (this.system.action) { const actor = await foundry.utils.fromUuid(config.source.actor); const item = actor?.items.get(config.source.item) ?? null; - config.effects = await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects(actor, item); + config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects(actor, item); await this.system.action.workflow.get('damage')?.execute(config, this._id, true); } } @@ -286,12 +276,8 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { async onCreateAreas(event) { const createArea = async selectedArea => { const effects = selectedArea.effects.map(effect => this.system.action.item.effects.get(effect).uuid); - const { shape: shapeType, size: range, hasHole } = selectedArea; - const shapeData = CONFIG.Canvas.layers.regions.layerClass.getTemplateShape({ - shapeType, - range, - hasHole - }); + const { shape: type, size: range } = selectedArea; + const shapeData = CONFIG.Canvas.layers.regions.layerClass.getTemplateShape({ type, range }); const scene = game.scenes.get(game.user.viewedScene); const level = scene.levels.find(x => x.isView); @@ -319,10 +305,7 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { visibility: CONST.REGION_VISIBILITY.ALWAYS }; const placeRegion = data => { - canvas.regions.placeRegion(data, { - create: true, - attachToToken: selectedArea.type === CONFIG.DH.ACTIONS.areaTypes.attached.id - }); + canvas.regions.placeRegion(data, { create: true }); }; // Regions with effects must be placed by the GM diff --git a/module/documents/combat.mjs b/module/documents/combat.mjs index e74127e9..20996b77 100644 --- a/module/documents/combat.mjs +++ b/module/documents/combat.mjs @@ -46,9 +46,7 @@ export default class DhpCombat extends Combat { for (let actor of actors) { await actor.createEmbeddedDocuments( 'ActiveEffect', - effects - .filter(x => x.effectTargetTypes.includes(actor.type)) - .map(x => foundry.utils.deepClone(x)) + effects.filter(x => x.effectTargetTypes.includes(actor.type)) ); } } else { diff --git a/module/documents/item.mjs b/module/documents/item.mjs index 8112e99f..32543ebd 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -89,10 +89,6 @@ export default class DHItem extends foundry.documents.Item { return !pack?.locked && this.isOwner && isValidType && hasActions; } - get hasDescription() { - return Boolean(this.system.description) || Boolean(this.system.itemFeatures?.length); - } - /** @inheritdoc */ static async createDialog(data = {}, createOptions = {}, options = {}) { const { folders, types, template, context = {}, ...dialogOptions } = options; @@ -208,7 +204,10 @@ export default class DHItem extends foundry.documents.Item { tags: this._getTags() }, actions: item.system.actionsList, - description: await this.system.getEnrichedDescription() + description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.system.description, { + relativeTo: this.parent, + rollData: this.parent?.getRollData() ?? {} + }) }; const msg = { diff --git a/module/documents/token.mjs b/module/documents/token.mjs index d70480db..8e91d4f0 100644 --- a/module/documents/token.mjs +++ b/module/documents/token.mjs @@ -38,8 +38,7 @@ export default class DHToken extends CONFIG.Token.documentClass { tokens.filter(x => x.actor).map(x => x.actor) ); } - - await super.createCombatants(tokens, combat ?? {}); + super.createCombatants(tokens, combat ?? {}); } /**@inheritdoc */ diff --git a/module/documents/tokenManager.mjs b/module/documents/tokenManager.mjs index b21b56a0..7678d2c7 100644 --- a/module/documents/tokenManager.mjs +++ b/module/documents/tokenManager.mjs @@ -19,10 +19,10 @@ export default class DhTokenManager { } } - const placedData = await canvas.tokens.placeTokens( + return await canvas.tokens.placeTokens( [ { - ...(await actor.getTokenDocument()).toObject(), + ...actor.prototypeToken.toObject(), actorId: actor.id, displayName: 50, ...tokenData @@ -30,8 +30,6 @@ export default class DhTokenManager { ], { create: false } ); - - return placedData?.[0] ?? null; } /** @@ -48,24 +46,22 @@ export default class DhTokenManager { const createElevation = elevation ?? level.elevation.bottom; for (const tokenData of tokensData) { - const previewToken = await this.createPreview(tokenData.actor, { + const previewTokens = await this.createPreview(tokenData.actor, { name: tokenData.tokenPreviewName, level: game.user.viewedLevel, elevation: createElevation, flags: { daggerheart: { createPlacement: true } } }); - if (!previewToken) return null; - - const finalTokenData = { - ...previewToken.toObject(), - name: tokenData.actor.prototypeToken.name, - displayName: tokenData.actor.prototypeToken.displayName, - flags: tokenData.actor.prototypeToken.flags - }; + if (!previewTokens?.length) return null; await canvas.scene.createEmbeddedDocuments( 'Token', - [finalTokenData], + previewTokens.map(x => ({ + ...x.toObject(), + name: tokenData.actor.prototypeToken.name, + displayName: tokenData.actor.prototypeToken.displayName, + flags: tokenData.actor.prototypeToken.flags + })), { controlObject: true, parent: canvas.scene } ); } diff --git a/module/documents/tooltipManager.mjs b/module/documents/tooltipManager.mjs index 6e794b6a..3e3f4a16 100644 --- a/module/documents/tooltipManager.mjs +++ b/module/documents/tooltipManager.mjs @@ -4,234 +4,199 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti #wide = false; #bordered = false; - /** @inheritdoc */ async activate(element, options = {}) { - this.#wide = false; - this.#bordered = false; - - const isMacro = document.getElementById('action-bar').contains(element); - const macro = isMacro ? game.macros.get(game.user.hotbar[Number(element.dataset.slot)] ?? null) : null; - const macroItemUuid = macro?.type === 'script' ? macro.command.match(/await game\.system\.api\.applications\.ui\.DhHotbar\.useItem\("([^"]+)"\);/)?.[1] : null; - if (macroItemUuid && await fromUuid(macroItemUuid, { strict: false })) { - element.dataset.tooltip = `#item#${macroItemUuid}`; - options.direction = this.constructor.TOOLTIP_DIRECTIONS.UP; - } + const { TextEditor } = foundry.applications.ux; let html = options.html; - const key = element.dataset.tooltip?.match(/^#([\w-]+)#/)?.[1]; - switch (key) { - case 'battlepoints': - return this.#activateBattlepoints(element, options); - case 'effect-display': - html = await this.#activateEffectDisplay(element, options); - break; - case 'item': - html = await this.#activateItem(element, options); - break; - case 'attack': - html = await this.#activateAttack(element, options); - break; - case 'shortRest': - case 'longRest': - html = await this.#activateRest(element, options); - break; - case 'advantage': - case 'disadvantage': - html = await this.#activateAdvantageDisadvantage(element, options); - break; - case 'deathMove': - html = await this.#activateDeathMove(element, options); - break; + if (element.dataset.tooltip?.startsWith('#battlepoints#')) { + this.#wide = true; + this.#bordered = true; + + html = await this.getBattlepointHTML(element.dataset.combatId); + options.direction = this._determineItemTooltipDirection(element); + super.activate(element, { ...options, html: html }); + + const lockedTooltip = this.lockTooltip(); + lockedTooltip.querySelectorAll('.battlepoint-toggle-container input').forEach(element => { + element.addEventListener('input', this.toggleModifier.bind(this)); + }); + return; + } else { + this.#wide = false; + this.#bordered = false; + } + + if (element.dataset.tooltip === '#effect-display#') { + this.#bordered = true; + let effect = {}; + if (element.dataset.uuid) { + const effectItem = await foundry.utils.fromUuid(element.dataset.uuid); + const effectData = effectItem.toObject(); + + effect = { + ...effectData, + name: game.i18n.localize(effectData.name) + }; + + if (effectData.type === 'beastform') { + const beastformData = { + features: [], + advantageOn: effectData.system.advantageOn, + beastformAttackData: game.system.api.data.items.DHBeastform.getBeastformAttackData(effectItem) + }; + + const features = effectItem.parent.items.filter(x => effectItem.system.featureIds.includes(x.id)); + for (const feature of features) { + const featureData = feature.toObject(); + featureData.enrichedDescription = await feature.system.getEnrichedDescription(); + beastformData.features.push(featureData); + } + + effect.description = await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/ui/tooltip/parts/beastformData.hbs', + { + item: { system: beastformData } + } + ); + } else { + effect.description = game.i18n.localize( + effectData.description ?? effectData.parent.system.description + ); + } + } else { + const conditions = CONFIG.DH.GENERAL.conditions(); + const condition = conditions[element.dataset.condition]; + effect = { + ...condition, + name: game.i18n.localize(condition.name), + description: game.i18n.localize(condition.description), + appliedBy: element.dataset.appliedBy, + isLockedCondition: true + }; + } + + html = await foundry.applications.handlebars.renderTemplate( + `systems/daggerheart/templates/ui/tooltip/effect-display.hbs`, + { + effect + } + ); + + this.tooltip.innerHTML = html; + options.direction = this._determineItemTooltipDirection(element); + } else { + this.#bordered = false; + } + + if (element.dataset.tooltip?.startsWith('#item#')) { + const itemUuid = element.dataset.tooltip.slice(6); + const item = await foundry.utils.fromUuid(itemUuid); + if (item) { + const isAction = item instanceof game.system.api.models.actions.actionsTypes.base; + const isEffect = item instanceof ActiveEffect; + await this.enrichText(item); + + const type = isAction ? 'action' : isEffect ? 'effect' : item.type; + html = await foundry.applications.handlebars.renderTemplate( + `systems/daggerheart/templates/ui/tooltip/${type}.hbs`, + { + item: item, + description: item.system?.enrichedDescription ?? item.enrichedDescription, + config: CONFIG.DH, + allDomains: CONFIG.DH.DOMAIN.allDomains() + } + ); + + this.tooltip.innerHTML = html; + options.direction = this._determineItemTooltipDirection(element); + } + } else { + const attack = element.dataset.tooltip?.startsWith('#attack#'); + if (attack) { + const actorUuid = element.dataset.tooltip.slice(8); + const actor = await foundry.utils.fromUuid(actorUuid); + const attack = actor.system.attack; + + const description = await TextEditor.enrichHTML(attack.description); + html = await foundry.applications.handlebars.renderTemplate( + `systems/daggerheart/templates/ui/tooltip/attack.hbs`, + { + attack: attack, + description: description, + parent: actor, + config: CONFIG.DH + } + ); + + this.tooltip.innerHTML = html; + } + + const shortRest = element.dataset.tooltip?.startsWith('#shortRest#'); + const longRest = element.dataset.tooltip?.startsWith('#longRest#'); + if (shortRest || longRest) { + const key = element.dataset.tooltip.slice(shortRest ? 11 : 10); + + const moves = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).restMoves[ + element.dataset.restType + ].moves; + const move = moves[key]; + const description = await TextEditor.enrichHTML(move.description); + html = await foundry.applications.handlebars.renderTemplate( + `systems/daggerheart/templates/ui/tooltip/downtime.hbs`, + { + move: move, + description: description + } + ); + + this.tooltip.innerHTML = html; + options.direction = this._determineItemTooltipDirection( + element, + this.constructor.TOOLTIP_DIRECTIONS.RIGHT + ); + } + + const isAdvantage = element.dataset.tooltip?.startsWith('#advantage#'); + const isDisadvantage = element.dataset.tooltip?.startsWith('#disadvantage#'); + if (isAdvantage || isDisadvantage) { + const actorUuid = element.dataset.tooltip.slice(isAdvantage ? 11 : 14); + const actor = await foundry.utils.fromUuid(actorUuid); + + if (actor) { + html = await foundry.applications.handlebars.renderTemplate( + `systems/daggerheart/templates/ui/tooltip/advantage.hbs`, + { + sources: isAdvantage ? actor.system.advantageSources : actor.system.disadvantageSources + } + ); + + this.tooltip.innerHTML = html; + } + } + + const deathMove = element.dataset.tooltip?.startsWith('#deathMove#'); + if (deathMove) { + const name = element.dataset.deathName; + const img = element.dataset.deathImg; + const description = element.dataset.deathDescription; + + html = await foundry.applications.handlebars.renderTemplate( + `systems/daggerheart/templates/ui/tooltip/death-move.hbs`, + { + move: { name: name, img: img, description: description } + } + ); + + this.tooltip.innerHTML = html; + options.direction = this._determineItemTooltipDirection( + element, + this.constructor.TOOLTIP_DIRECTIONS.RIGHT + ); + } } this.noOffset = options.noOffset; - super.activate(element, { ...options, html }); - } - - async #activateBattlepoints(element, options) { - this.#wide = true; - this.#bordered = true; - - const html = await this.getBattlepointHTML(element.dataset.combatId); - options.direction = this._determineItemTooltipDirection(element); super.activate(element, { ...options, html: html }); - - const lockedTooltip = this.lockTooltip(); - lockedTooltip.querySelectorAll('.battlepoint-toggle-container input').forEach(element => { - element.addEventListener('input', this.toggleModifier.bind(this)); - }); - } - - async #activateEffectDisplay(element, options) { - this.#bordered = true; - let effect = {}; - if (element.dataset.uuid) { - const effectItem = await foundry.utils.fromUuid(element.dataset.uuid); - const effectData = effectItem.toObject(); - - effect = { - ...effectData, - name: game.i18n.localize(effectData.name) - }; - - if (effectData.type === 'beastform') { - const beastformData = { - features: [], - advantageOn: effectData.system.advantageOn, - beastformAttackData: game.system.api.data.items.DHBeastform.getBeastformAttackData(effectItem) - }; - - const features = effectItem.parent.items.filter(x => effectItem.system.featureIds.includes(x.id)); - for (const feature of features) { - const featureData = feature.toObject(); - featureData.enrichedDescription = await feature.system.getEnrichedDescription(); - beastformData.features.push(featureData); - } - - effect.description = await foundry.applications.handlebars.renderTemplate( - 'systems/daggerheart/templates/ui/tooltip/parts/beastformData.hbs', - { - item: { system: beastformData } - } - ); - } else { - effect.description = game.i18n.localize( - effectData.description ?? effectData.parent.system.description - ); - } - } else { - const conditions = CONFIG.DH.GENERAL.conditions(); - const condition = conditions[element.dataset.condition]; - effect = { - ...condition, - name: game.i18n.localize(condition.name), - description: game.i18n.localize(condition.description), - appliedBy: element.dataset.appliedBy, - isLockedCondition: true - }; - } - - const html = await foundry.applications.handlebars.renderTemplate( - `systems/daggerheart/templates/ui/tooltip/effect-display.hbs`, - { - effect - } - ); - - this.tooltip.innerHTML = html; - options.direction = this._determineItemTooltipDirection(element); - - return html; - } - - async #activateItem(element, options) { - const itemUuid = element.dataset.tooltip.slice(6); - const item = await foundry.utils.fromUuid(itemUuid); - if (item) { - const isAction = item instanceof game.system.api.models.actions.actionsTypes.base; - const isEffect = item instanceof ActiveEffect; - await this.enrichText(item); - - const type = isAction ? 'action' : isEffect ? 'effect' : item.type; - const html = await foundry.applications.handlebars.renderTemplate( - `systems/daggerheart/templates/ui/tooltip/${type}.hbs`, - { - item: item, - description: item.system?.enrichedDescription ?? item.enrichedDescription, - config: CONFIG.DH, - allDomains: CONFIG.DH.DOMAIN.allDomains() - } - ); - - this.tooltip.innerHTML = html; - options.direction ??= this._determineItemTooltipDirection(element); - return html; - } - - return null; - } - - async #activateAttack(element, options) { - const actorUuid = element.dataset.tooltip.slice(8); - const actor = await foundry.utils.fromUuid(actorUuid); - const attack = actor.system.attack; - - const description = await foundry.applications.ux.TextEditor.enrichHTML(attack.description); - const html = await foundry.applications.handlebars.renderTemplate( - `systems/daggerheart/templates/ui/tooltip/attack.hbs`, - { - attack: attack, - description: description, - parent: actor, - config: CONFIG.DH - } - ); - - this.tooltip.innerHTML = html; - return html; - } - - async #activateAdvantageDisadvantage(element, options) { - const isAdvantage = element.dataset.tooltip?.startsWith('#advantage#'); - const actorUuid = element.dataset.tooltip.slice(isAdvantage ? 11 : 14); - const actor = await foundry.utils.fromUuid(actorUuid); - - if (actor) { - const html = await foundry.applications.handlebars.renderTemplate( - `systems/daggerheart/templates/ui/tooltip/advantage.hbs`, - { - sources: isAdvantage ? actor.system.advantageSources : actor.system.disadvantageSources - } - ); - - this.tooltip.innerHTML = html; - return html; - } - return null; - } - - async #activateDeathMove(element, options) { - const name = element.dataset.deathName; - const img = element.dataset.deathImg; - const description = element.dataset.deathDescription; - - const html = await foundry.applications.handlebars.renderTemplate( - `systems/daggerheart/templates/ui/tooltip/death-move.hbs`, - { - move: { name: name, img: img, description: description } - } - ); - - this.tooltip.innerHTML = html; - options.direction = this._determineItemTooltipDirection( - element, - this.constructor.TOOLTIP_DIRECTIONS.RIGHT - ); - return html; - } - - async #activateRest(element, options) { - const isShortRest = element.dataset.tooltip?.startsWith('#shortRest#'); - const key = element.dataset.tooltip.slice(isShortRest ? 11 : 10); - const moves = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).restMoves[ - element.dataset.restType - ].moves; - const move = moves[key]; - const description = await foundry.applications.ux.TextEditor.enrichHTML(move.description); - const html = await foundry.applications.handlebars.renderTemplate( - `systems/daggerheart/templates/ui/tooltip/downtime.hbs`, - { - move: move, - description: description - } - ); - - this.tooltip.innerHTML = html; - options.direction = this._determineItemTooltipDirection( - element, - this.constructor.TOOLTIP_DIRECTIONS.RIGHT - ); - return html; } _setAnchor(direction) { diff --git a/module/enrichers/FateRollEnricher.mjs b/module/enrichers/FateRollEnricher.mjs index 8513ed94..c82bbcb2 100644 --- a/module/enrichers/FateRollEnricher.mjs +++ b/module/enrichers/FateRollEnricher.mjs @@ -49,7 +49,7 @@ export const renderFateButton = async event => { const fateTypeData = getFateTypeData(button.dataset?.fatetype); if (!fateTypeData) ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.fateTypeParsing')); - const { value: fateType } = fateTypeData; + const { value: fateType, label: fateTypeLabel } = fateTypeData; await enrichedFateRoll( { diff --git a/module/enrichers/TemplateEnricher.mjs b/module/enrichers/TemplateEnricher.mjs index b951f41e..bbe93b17 100644 --- a/module/enrichers/TemplateEnricher.mjs +++ b/module/enrichers/TemplateEnricher.mjs @@ -58,11 +58,10 @@ export const renderMeasuredTemplate = async event => { if (!type || !range || !game.canvas.scene) return; const shapeData = CONFIG.Canvas.layers.regions.layerClass.getTemplateShape({ - shapeType: type, + type, angle, range, - direction, - hasHole: false + direction }); await canvas.regions.placeRegion( diff --git a/module/enrichers/_module.mjs b/module/enrichers/_module.mjs index 02002884..b80f166c 100644 --- a/module/enrichers/_module.mjs +++ b/module/enrichers/_module.mjs @@ -35,24 +35,23 @@ export const enricherConfig = [ ]; export const enricherRenderSetup = element => { - const clickWrapper = func => event => { - event.stopPropagation(); - func(event); - }; - element .querySelectorAll('.enriched-damage-button') - .forEach(element => element.addEventListener('click', clickWrapper(renderDamageButton))); + .forEach(element => element.addEventListener('click', renderDamageButton)); element .querySelectorAll('.duality-roll-button') - .forEach(element => element.addEventListener('click', clickWrapper(renderDualityButton))); + .forEach(element => element.addEventListener('click', renderDualityButton)); element .querySelectorAll('.fate-roll-button') - .forEach(element => element.addEventListener('click', clickWrapper(renderFateButton))); + .forEach(element => element.addEventListener('click', renderFateButton)); element .querySelectorAll('.measured-template-button') - .forEach(element => element.addEventListener('click', clickWrapper(renderMeasuredTemplate))); + .forEach(element => element.addEventListener('click', renderMeasuredTemplate)); + + // element + // .querySelectorAll('.enriched-effect') + // .forEach(element => element.addEventListener('dragstart', dragEnrichedEffect)); }; diff --git a/module/helpers/handlebarsHelper.mjs b/module/helpers/handlebarsHelper.mjs index dbcc50dc..7f30d970 100644 --- a/module/helpers/handlebarsHelper.mjs +++ b/module/helpers/handlebarsHelper.mjs @@ -48,8 +48,9 @@ export default class RegisterHandlebarsHelpers { return formula; } - static damageSymbols(damageData) { - const symbols = damageData.type.map(p => CONFIG.DH.GENERAL.damageTypes[p].icon); + static damageSymbols(damageParts) { + const allTypes = [...new Set([...damageParts].flatMap(x => Array.from(x.type)))]; + const symbols = allTypes.map(p => CONFIG.DH.GENERAL.damageTypes[p].icon); return new Handlebars.SafeString(Array.from(symbols).map(symbol => ``)); } diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index f600eae6..90a5c29d 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -1,10 +1,6 @@ import { diceTypes, getDiceSoNicePresets, getDiceSoNicePreset, range } from '../config/generalConfig.mjs'; import Tagify from '@yaireo/tagify'; -/** - * @import DhpActor from '../documents/actor.mjs'; - */ - export const capitalize = string => { return string.charAt(0).toUpperCase() + string.slice(1); }; @@ -322,7 +318,7 @@ export function getDocFromElementSync(element) { const target = element.closest('[data-item-uuid]'); try { return foundry.utils.fromUuidSync(target.dataset.itemUuid) ?? null; - } catch { + } catch (_) { return null; } } @@ -381,7 +377,7 @@ export const itemAbleRollParse = (value, actor, item) => { try { return Roll.replaceFormulaData(slicedValue, rollData); - } catch { + } catch (_) { return ''; } }; @@ -700,6 +696,19 @@ export async function RefreshFeatures( return refreshedActors; } +export function getUnusedDamageTypes(parts) { + const usedKeys = Object.keys(parts); + return Object.keys(CONFIG.DH.GENERAL.healingTypes).reduce((acc, key) => { + if (!usedKeys.includes(key)) + acc.push({ + value: key, + label: game.i18n.localize(CONFIG.DH.GENERAL.healingTypes[key].label) + }); + + return acc; + }, []); +} + /** Returns resolved armor sources ordered by application order */ export function getArmorSources(actor) { const rawArmorSources = Array.from(actor.allApplicableEffects()).filter(x => x.system.armorData); @@ -876,37 +885,3 @@ export async function triggerChatRollFx(rolls, options = { whisper: false, blind foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice }); } } - -export function shouldUseHopeFearAutomation(options = { gmAsPlayer: true }) { - const { hopeFear } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); - return (!game.user.isGM || options.gmAsPlayer) ? hopeFear.players : hopeFear.gm; -} - -/** - * Returns the given actor if its a world actor, - * finds a world actor equivalent, - * or imports the actor and returns the imported actor. - * @param {DhpActor} baseActor - * @returns {Promise} a world actor - */ -export async function getWorldActor(baseActor) { - if (baseActor.inCompendium) { - const worldActorCandidates = game.actors.filter(x => - x._stats.compendiumSource === baseActor.uuid && - x.prototypeToken.actorLink === baseActor.prototypeToken.actorLink - ); - const worldActorCopy = worldActorCandidates.find(a => a.name === baseActor.name) ?? worldActorCandidates[0]; - if (worldActorCopy) return worldActorCopy; - - const baseActorData = baseActor; - return await game.system.api.documents.DhpActor.create({ - ...baseActorData, - _stats: { - ...baseActorData._stats, - compendiumSource: baseActor.uuid - } - }); - } - - return baseActor; -} \ No newline at end of file diff --git a/module/systemRegistration/handlebars.mjs b/module/systemRegistration/handlebars.mjs index bf315358..1b08e0ad 100644 --- a/module/systemRegistration/handlebars.mjs +++ b/module/systemRegistration/handlebars.mjs @@ -50,7 +50,6 @@ export const preloadHandlebarsTemplates = async function () { 'systems/daggerheart/templates/ui/chat/parts/target-part.hbs', 'systems/daggerheart/templates/ui/chat/parts/button-part.hbs', 'systems/daggerheart/templates/ui/itemBrowser/itemContainer.hbs', - 'systems/daggerheart/templates/ui/countdowns/parts/countdowns.hbs', 'systems/daggerheart/templates/scene/dh-config.hbs', 'systems/daggerheart/templates/settings/appearance-settings/diceSoNiceTab.hbs', 'systems/daggerheart/templates/sheets/activeEffect/typeChanges/armorChange.hbs' diff --git a/module/systemRegistration/migration-handlers/2_5_2.mjs b/module/systemRegistration/migration-handlers/2_5_2.mjs deleted file mode 100644 index 096f4bb7..00000000 --- a/module/systemRegistration/migration-handlers/2_5_2.mjs +++ /dev/null @@ -1,39 +0,0 @@ -import { MigrationHandlerBase } from './base.mjs'; - -export class Migration_2_5_2 extends MigrationHandlerBase { - version = '2.5.2'; - - /** @inheritdoc */ - async updateActiveEffectSource(effectSource, item) { - let shouldUpdate = false; - const newChanges = []; - - const srdItem = item?._stats?.compendiumSource ? - await foundry.utils.fromUuid(item?._stats.compendiumSource) : - null; - for (let i = 0; i < effectSource.system.changes.length; i++) { - const change = effectSource.system.changes[i]; - const srdEffect = srdItem?.effects.find(x => x.name === effectSource.name); - if (change.type === 'custom') { - const srdChange = srdEffect ? srdEffect.system.changes[i] : null; - if (srdChange && - change.key === srdChange.key && - change.value === srdChange.value && - change.type !== srdChange.type - ) { - shouldUpdate = true; - newChanges.push(srdChange); - } - } else { - newChanges.push(change); - } - } - - if (shouldUpdate) { - return { - _id: effectSource._id, - system: { changes: newChanges } - } - } - } -} \ No newline at end of file diff --git a/module/systemRegistration/migration-handlers/2_6_0.mjs b/module/systemRegistration/migration-handlers/2_6_0.mjs deleted file mode 100644 index 9edda9a2..00000000 --- a/module/systemRegistration/migration-handlers/2_6_0.mjs +++ /dev/null @@ -1,20 +0,0 @@ -import { MigrationHandlerBase } from './base.mjs'; - -export class Migration_2_6_0 extends MigrationHandlerBase { - version = '2.6.0'; - - /** @inheritdoc */ - async updateActorSource(actor) { - if (actor.type === 'party' && Object.keys(actor.system.tagTeam.members).length) { - return { - _id: actor._id, - system: { - tagTeam: { - initiator: null, - members: _replace({}) - } - } - }; - } - } -} \ No newline at end of file diff --git a/module/systemRegistration/migration-handlers/base.mjs b/module/systemRegistration/migration-handlers/base.mjs deleted file mode 100644 index 29c181ce..00000000 --- a/module/systemRegistration/migration-handlers/base.mjs +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @import DHItem from "../../documents/item.mjs"; -* @import DhActor from "../../documents/actor.mjs"; - */ -/** - - * The base class of an async migration. - * These are generally run between versions for things that require compendiums or must be done in post. - * The migrate() functions calls the various updateXSource() functions. - * Generally a subclass will override the version and the updateXSource() functions. - */ -export class MigrationHandlerBase { - version = null; - - /** - * Gets change data for an active effect's source, or null if no changes - * @param {object} effectSource - * @param {DHItem} item - * @returns {Promise} - * @protected - */ - async updateActiveEffectSource(effectSource, item) { - return null; - } - - /** - * Update a world actor - * @param {DhActor} actor - * @returns {Promise} - * @protected - */ - async updateActorSource(actor) { - return null; - } - - async migrate() { - // todo: handle more than just migrating effects. Right now this can only migrate effects - // NOTE: the preload is hardcoded, we should not hardcode it - - const numActors = game.actors.size; - const numItems = game.items.size; - const finalUpdateProgress = 5; - const DhProgress = game.system.api.applications.ui.DhProgress; - const preRunProgress = game.packs.size; - - const progress = DhProgress.createMigrationProgress( - preRunProgress + numActors + numItems + finalUpdateProgress - ); - - // Preload. Avoid hardcoding in the future - for (const pack of game.packs) { - await pack.getDocuments(); - progress.advance(); - } - - const batch = []; - - const updateItem = async item => { - const itemUpdates = []; - for (const effect of item.effects) { - const changes = await this.updateActiveEffectSource(effect.toObject(), item); - if (changes) itemUpdates.push(changes); - } - if (itemUpdates.length) { - batch.push({ - action: 'update', - documentName: 'ActiveEffect', - updates: itemUpdates, - parent: item - }); - } - }; - - const updateActor = async actor => { - const actorUpdate = await this.updateActorSource(actor); - if (actorUpdate) { - batch.push({ - action: 'update', - documentName: 'Actor', - updates: [actorUpdate] - }); - } - - const aeUpdates = []; - for (const item of actor.items) { - await updateItem(item); - } - - for (const effect of actor.effects) { - const changes = await this.updateActiveEffectSource(effect.toObject(), { parent: actor }); - if (changes) aeUpdates.push(changes); - } - if (aeUpdates.length) { - batch.push({ - action: 'update', - documentName: 'ActiveEffect', - updates: aeUpdates, - parent: actor - }); - } - } - - - for (const actor of game.actors) { - await updateActor(actor); - - progress.advance(); - } - for (const item of game.items) { - await updateItem(item); - progress.advance(); - } - - await foundry.documents.modifyBatch(batch); - progress.advance({ by: finalUpdateProgress }); - } -} \ No newline at end of file diff --git a/module/systemRegistration/migrations.mjs b/module/systemRegistration/migrations.mjs index af11cd2c..b718a127 100644 --- a/module/systemRegistration/migrations.mjs +++ b/module/systemRegistration/migrations.mjs @@ -1,6 +1,5 @@ import { defaultRestOptions } from '../config/generalConfig.mjs'; -import { Migration_2_5_2 } from './migration-handlers/2_5_2.mjs'; -import { Migration_2_6_0 } from './migration-handlers/2_6_0.mjs'; +import { RefreshType, socketEvent } from './socket.mjs'; export async function runMigrations() { let lastMigrationVersion = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion); @@ -154,26 +153,61 @@ export async function runMigrations() { await pack.configure({ locked: true }); } + /* Migrate old countdown structure */ + const countdownSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); + const getCountdowns = (data, type) => { + return Object.keys(data.countdowns).reduce((acc, key) => { + const countdown = data.countdowns[key]; + acc[key] = { + ...countdown, + type: type, + ownership: Object.keys(countdown.ownership.players).reduce((acc, key) => { + acc[key] = + countdown.ownership.players[key].type === 1 ? 2 : countdown.ownership.players[key].type; + return acc; + }, {}), + progress: { + ...countdown.progress, + type: countdown.progress.type.value + } + }; + + return acc; + }, {}); + }; + + await countdownSettings.updateSource({ + countdowns: { + ...getCountdowns(countdownSettings.narrative, CONFIG.DH.GENERAL.countdownBaseTypes.narrative.id), + ...getCountdowns(countdownSettings.encounter, CONFIG.DH.GENERAL.countdownBaseTypes.encounter.id) + } + }); + await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, countdownSettings); + + game.socket.emit(`system.${CONFIG.DH.id}`, { + action: socketEvent.Refresh, + data: { refreshType: RefreshType.Countdown } + }); + Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown }); + lastMigrationVersion = '1.2.0'; } if (foundry.utils.isNewerVersion('1.2.7', lastMigrationVersion)) { - try { - const tagTeam = game.settings.get(CONFIG.DH.id, 'TagTeamRoll'); - const initatorMissing = tagTeam.initiator && !game.actors.some(actor => actor.id === tagTeam.initiator); - const missingMembers = Object.keys(tagTeam.members).reduce((acc, id) => { - if (!game.actors.some(actor => actor.id === id)) { - acc[id] = _del; - } - return acc; - }, {}); + const tagTeam = game.settings.get(CONFIG.DH.id, 'TagTeamRoll'); + const initatorMissing = tagTeam.initiator && !game.actors.some(actor => actor.id === tagTeam.initiator); + const missingMembers = Object.keys(tagTeam.members).reduce((acc, id) => { + if (!game.actors.some(actor => actor.id === id)) { + acc[id] = _del; + } + return acc; + }, {}); - await tagTeam.updateSource({ - initiator: initatorMissing ? null : tagTeam.initiator, - members: missingMembers - }); - await game.settings.set(CONFIG.DH.id, 'TagTeamRoll', tagTeam); - } catch { } + await tagTeam.updateSource({ + initiator: initatorMissing ? null : tagTeam.initiator, + members: missingMembers + }); + await game.settings.set(CONFIG.DH.id, 'TagTeamRoll', tagTeam); lastMigrationVersion = '1.2.7'; } @@ -269,8 +303,6 @@ export async function runMigrations() { /* Migrate existing effects modifying armor, creating new Armor Effects instead */ const migrateEffects = async entity => { - if (!entity?.effects) return; - for (const effect of entity.effects) { if (effect.system.changes.every(x => x.key !== 'system.armorScore')) continue; @@ -322,20 +354,7 @@ export async function runMigrations() { lastMigrationVersion = '2.1.0'; } + //#endregion await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion, lastMigrationVersion); - - /* -------------------------------------------- */ - /* New Style migrations below this point */ - /* -------------------------------------------- */ - - const migrations = [ - new Migration_2_5_2(), - new Migration_2_6_0() - ].filter(m => m.version && foundry.utils.isNewerVersion(m.version, lastMigrationVersion)); - - for (const handler of migrations) { - await handler.migrate(); - await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion, handler.version); - } } diff --git a/module/systemRegistration/settings.mjs b/module/systemRegistration/settings.mjs index 1a985274..a66323c7 100644 --- a/module/systemRegistration/settings.mjs +++ b/module/systemRegistration/settings.mjs @@ -199,10 +199,7 @@ const registerNonConfigSettings = () => { game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, { scope: 'world', config: false, - type: DhCountdowns, - onChange: value => { - value.handleChange(); - } + type: DhCountdowns }); game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.CompendiumBrowserSettings, { diff --git a/module/systemRegistration/socket.mjs b/module/systemRegistration/socket.mjs index 10206ab5..de9bf00c 100644 --- a/module/systemRegistration/socket.mjs +++ b/module/systemRegistration/socket.mjs @@ -1,5 +1,5 @@ import DamageReductionDialog from '../applications/dialogs/damageReductionDialog.mjs'; -import PartySheet from '../applications/sheets/actors/party.mjs'; +import Party from '../applications/sheets/actors/party.mjs'; export function handleSocketEvent({ action = null, data = {} } = {}) { switch (action) { @@ -16,7 +16,7 @@ export function handleSocketEvent({ action = null, data = {} } = {}) { Hooks.call(socketEvent.Refresh, data); break; case socketEvent.DowntimeTrigger: - PartySheet.downtimeMoveQuery(data); + Party.downtimeMoveQuery(data); break; case socketEvent.TagTeamStart: Hooks.callAll(CONFIG.DH.HOOKS.hooksConfig.tagTeamStart, data); diff --git a/src/packs/adversaries/adversary_Acid_Burrower_89yAh30vaNQOALlz.json b/src/packs/adversaries/adversary_Acid_Burrower_89yAh30vaNQOALlz.json index 4261a261..d3c8c955 100644 --- a/src/packs/adversaries/adversary_Acid_Burrower_89yAh30vaNQOALlz.json +++ b/src/packs/adversaries/adversary_Acid_Burrower_89yAh30vaNQOALlz.json @@ -403,6 +403,12 @@ "_id": "9PsnogEPsp1OOK64", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "act" diff --git a/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json b/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json index ad558d43..ecb93d1b 100644 --- a/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json +++ b/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json @@ -322,23 +322,32 @@ "_id": "ia0NUIOxE3RHb45P", "type": "base", "system": { - "changes": [ - { - "key": "system.evasion", - "type": "override", - "value": "@system.evasion / 2", - "priority": 10 - } - ] - }, - "duration": { - "value": null, - "units": "seconds", - "expiry": null, - "expired": false + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.evasion", + "mode": 5, + "value": "@system.evasion / 2", + "priority": 10 + } + ], "disabled": false, - "description": "When the Flickerfly makes an attack, the target’s Evasion is halved against the attack.", + "duration": { + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null + }, + "description": "When the Flickerfl y makes an attack, the target’s Evasion is halved against the attack.", "tint": "#ffffff", "statuses": [], "sort": 0, diff --git a/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json b/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json index 6cb0c95d..5da74eb3 100644 --- a/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json +++ b/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json @@ -491,6 +491,12 @@ "_id": "KGdf2eqcXkdigg0u", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Archer_Guard_JRhrrEg5UroURiAD.json b/src/packs/adversaries/adversary_Archer_Guard_JRhrrEg5UroURiAD.json index d9399007..965c5168 100644 --- a/src/packs/adversaries/adversary_Archer_Guard_JRhrrEg5UroURiAD.json +++ b/src/packs/adversaries/adversary_Archer_Guard_JRhrrEg5UroURiAD.json @@ -325,15 +325,21 @@ "_id": "wGuxOLokMqdxVSOo", "type": "base", "system": { - "changes": [ - { - "key": "system.disadvantageSources", - "type": "add", - "value": "Agility Rolls", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.disadvantageSources", + "mode": 2, + "value": "Agility Rolls", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Archer_Squadron_0ts6CGd93lLqGZI5.json b/src/packs/adversaries/adversary_Archer_Squadron_0ts6CGd93lLqGZI5.json index 24b7c6eb..1e45b90a 100644 --- a/src/packs/adversaries/adversary_Archer_Squadron_0ts6CGd93lLqGZI5.json +++ b/src/packs/adversaries/adversary_Archer_Squadron_0ts6CGd93lLqGZI5.json @@ -472,8 +472,14 @@ "disabled": true, "_id": "bq8hTzQoCXmA3xad", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "duration": { "startTime": 0, "combat": null diff --git a/src/packs/adversaries/adversary_Assassin_Poisoner_h5RuhzGL17dW5FBT.json b/src/packs/adversaries/adversary_Assassin_Poisoner_h5RuhzGL17dW5FBT.json index 51eb7273..c1bce57b 100644 --- a/src/packs/adversaries/adversary_Assassin_Poisoner_h5RuhzGL17dW5FBT.json +++ b/src/packs/adversaries/adversary_Assassin_Poisoner_h5RuhzGL17dW5FBT.json @@ -270,6 +270,12 @@ "_id": "2iBVUGHtGW3I9VIj", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", @@ -335,17 +341,23 @@ "name": "Out of Nowhere", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "On attacks if they are Hidden.", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "qT5nh7OcQ6aGdiWS", "img": "icons/magic/perception/shadow-stealth-eyes-purple.webp", + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "On attacks if they are Hidden.", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -440,6 +452,12 @@ "_id": "yP4ot8VqS56RnxnE", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [] }, "disabled": false, diff --git a/src/packs/adversaries/adversary_Battle_Box_dgH3fW9FTYLaIDvS.json b/src/packs/adversaries/adversary_Battle_Box_dgH3fW9FTYLaIDvS.json index 5625ff0f..be47829b 100644 --- a/src/packs/adversaries/adversary_Battle_Box_dgH3fW9FTYLaIDvS.json +++ b/src/packs/adversaries/adversary_Battle_Box_dgH3fW9FTYLaIDvS.json @@ -680,6 +680,12 @@ "_id": "9NQcCXMhjyBReJRd", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", @@ -921,6 +927,12 @@ "_id": "S7kJlhnV8Nexzi8l", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Bear_71qKDLKO3CsrNkdy.json b/src/packs/adversaries/adversary_Bear_71qKDLKO3CsrNkdy.json index 8dd7fb95..cfc71120 100644 --- a/src/packs/adversaries/adversary_Bear_71qKDLKO3CsrNkdy.json +++ b/src/packs/adversaries/adversary_Bear_71qKDLKO3CsrNkdy.json @@ -363,6 +363,12 @@ "_id": "U50Ccm9emMqAxma6", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Bladed_Guard_B4LZcGuBAHzyVdzy.json b/src/packs/adversaries/adversary_Bladed_Guard_B4LZcGuBAHzyVdzy.json index 2083208f..a315f91a 100644 --- a/src/packs/adversaries/adversary_Bladed_Guard_B4LZcGuBAHzyVdzy.json +++ b/src/packs/adversaries/adversary_Bladed_Guard_B4LZcGuBAHzyVdzy.json @@ -371,6 +371,12 @@ "_id": "LmzztuktRkwOCy1a", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Brawny_Zombie_2UeZ0tEe7AzgSJNd.json b/src/packs/adversaries/adversary_Brawny_Zombie_2UeZ0tEe7AzgSJNd.json index 94862545..8863641d 100644 --- a/src/packs/adversaries/adversary_Brawny_Zombie_2UeZ0tEe7AzgSJNd.json +++ b/src/packs/adversaries/adversary_Brawny_Zombie_2UeZ0tEe7AzgSJNd.json @@ -447,6 +447,12 @@ "_id": "CjMrSdL6kgD8mKRQ", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/adversaries/adversary_Chaos_Skull_jDmHqGvzg5wjgmxE.json b/src/packs/adversaries/adversary_Chaos_Skull_jDmHqGvzg5wjgmxE.json index 3db27edd..876519cf 100644 --- a/src/packs/adversaries/adversary_Chaos_Skull_jDmHqGvzg5wjgmxE.json +++ b/src/packs/adversaries/adversary_Chaos_Skull_jDmHqGvzg5wjgmxE.json @@ -232,17 +232,23 @@ "name": "Levitation", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.conditionImmunities.restrained", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "k6iaQVfMZhrpwYQj", "img": "icons/magic/air/fog-gas-smoke-blue-gray.webp", + "changes": [ + { + "key": "system.rules.conditionImmunities.restrained", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -295,17 +301,23 @@ "name": "Wards", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.magical.resistance", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "4rj6PM0AGrrlbxSc", "img": "icons/magic/defensive/barrier-shield-dome-blue-purple.webp", + "changes": [ + { + "key": "system.resistance.magical.resistance", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Construct_uOP5oT9QzXPlnf3p.json b/src/packs/adversaries/adversary_Construct_uOP5oT9QzXPlnf3p.json index 02f6d587..3bd154ef 100644 --- a/src/packs/adversaries/adversary_Construct_uOP5oT9QzXPlnf3p.json +++ b/src/packs/adversaries/adversary_Construct_uOP5oT9QzXPlnf3p.json @@ -459,15 +459,21 @@ "_id": "xkDIZk9u2ipDHvOL", "img": "icons/creatures/magical/construct-golem-stone-blue.webp", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "10", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "10", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Courtesan_ZxWaWPdzFIUPNC62.json b/src/packs/adversaries/adversary_Courtesan_ZxWaWPdzFIUPNC62.json index 14de1b12..aba9ea46 100644 --- a/src/packs/adversaries/adversary_Courtesan_ZxWaWPdzFIUPNC62.json +++ b/src/packs/adversaries/adversary_Courtesan_ZxWaWPdzFIUPNC62.json @@ -315,6 +315,12 @@ "_id": "blcRqns0PHqiuPac", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Courtier_CBBuEXAlLKFMJdjg.json b/src/packs/adversaries/adversary_Courtier_CBBuEXAlLKFMJdjg.json index 1e4f4140..8777ee06 100644 --- a/src/packs/adversaries/adversary_Courtier_CBBuEXAlLKFMJdjg.json +++ b/src/packs/adversaries/adversary_Courtier_CBBuEXAlLKFMJdjg.json @@ -331,6 +331,12 @@ "_id": "YNMhgBZW8ndrCjIp", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "scene" diff --git a/src/packs/adversaries/adversary_Cult_Adept_0NxCSugvKQ4W8OYZ.json b/src/packs/adversaries/adversary_Cult_Adept_0NxCSugvKQ4W8OYZ.json index e191c11e..27553d32 100644 --- a/src/packs/adversaries/adversary_Cult_Adept_0NxCSugvKQ4W8OYZ.json +++ b/src/packs/adversaries/adversary_Cult_Adept_0NxCSugvKQ4W8OYZ.json @@ -415,6 +415,12 @@ "_id": "U9lWz1LgeAiK5L85", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.resistance.magical.resistance", @@ -540,6 +546,12 @@ "_id": "lNH6srSPyEprXZ4o", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Cult_Fang_tyBOpLfigAhI9bU3.json b/src/packs/adversaries/adversary_Cult_Fang_tyBOpLfigAhI9bU3.json index 0bb00b6b..e65f3202 100644 --- a/src/packs/adversaries/adversary_Cult_Fang_tyBOpLfigAhI9bU3.json +++ b/src/packs/adversaries/adversary_Cult_Fang_tyBOpLfigAhI9bU3.json @@ -379,6 +379,12 @@ "_id": "LwWxRz7FTMA80VdA", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/adversaries/adversary_Deeproot_Defender_9x2xY9zwc3xzbXo5.json b/src/packs/adversaries/adversary_Deeproot_Defender_9x2xY9zwc3xzbXo5.json index a4aca10d..9ff0a161 100644 --- a/src/packs/adversaries/adversary_Deeproot_Defender_9x2xY9zwc3xzbXo5.json +++ b/src/packs/adversaries/adversary_Deeproot_Defender_9x2xY9zwc3xzbXo5.json @@ -410,6 +410,12 @@ "_id": "F3E7fiz01AbF2kr5", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Demon_of_Avarice_pnyjIGxxvurcWmTv.json b/src/packs/adversaries/adversary_Demon_of_Avarice_pnyjIGxxvurcWmTv.json index ebd41544..1a3538da 100644 --- a/src/packs/adversaries/adversary_Demon_of_Avarice_pnyjIGxxvurcWmTv.json +++ b/src/packs/adversaries/adversary_Demon_of_Avarice_pnyjIGxxvurcWmTv.json @@ -270,17 +270,23 @@ "name": "Numbers Must Go Up", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.attack.bonus", - "type": "add", - "value": "ITEM.@system.resource.value", - "priority": 21 - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "iLeiOlUtWvYsgbDQ", "img": "icons/magic/control/fear-fright-monster-grin-red-orange.webp", + "changes": [ + { + "key": "system.bonuses.roll.attack.bonus", + "mode": 2, + "value": "ITEM.@system.resource.value", + "priority": 21 + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json b/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json index 219136ff..6468c1aa 100644 --- a/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json +++ b/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json @@ -238,17 +238,23 @@ "name": "Depths Of Despair", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.attack.damage.hpDamageMultiplier", - "type": "override", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "nofxm1vGZ2TmceA2", "img": "icons/magic/death/skull-horned-worn-fire-blue.webp", + "changes": [ + { + "key": "system.rules.attack.damage.hpDamageMultiplier", + "mode": 5, + "value": "2", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, @@ -350,6 +356,12 @@ "_id": "6WSx03mFbpbPWnOI", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.rules.dualityRoll.defaultHopeDice", diff --git a/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json b/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json index a158b2b7..0bc6bf2d 100644 --- a/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json +++ b/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json @@ -319,6 +319,12 @@ "_id": "gFeHLGgeRoDdd3VG", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.rules.dualityRoll.defaultFearDice", diff --git a/src/packs/adversaries/adversary_Demonic_Hound_Pack_NoRZ1PqB8N5wcIw0.json b/src/packs/adversaries/adversary_Demonic_Hound_Pack_NoRZ1PqB8N5wcIw0.json index 09bca946..b534562b 100644 --- a/src/packs/adversaries/adversary_Demonic_Hound_Pack_NoRZ1PqB8N5wcIw0.json +++ b/src/packs/adversaries/adversary_Demonic_Hound_Pack_NoRZ1PqB8N5wcIw0.json @@ -440,8 +440,14 @@ "disabled": true, "_id": "dPZ7PwvTERjtG92P", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "duration": { "startTime": 0, "combat": null diff --git a/src/packs/adversaries/adversary_Dire_Bat_tBWHW00epmMnkawe.json b/src/packs/adversaries/adversary_Dire_Bat_tBWHW00epmMnkawe.json index bc1ab981..a1107f7c 100644 --- a/src/packs/adversaries/adversary_Dire_Bat_tBWHW00epmMnkawe.json +++ b/src/packs/adversaries/adversary_Dire_Bat_tBWHW00epmMnkawe.json @@ -238,6 +238,12 @@ "name": "Flying", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.difficulty", diff --git a/src/packs/adversaries/adversary_Dire_Wolf_wNzeuQLfLUMvgHlQ.json b/src/packs/adversaries/adversary_Dire_Wolf_wNzeuQLfLUMvgHlQ.json index 41ca7129..939a5307 100644 --- a/src/packs/adversaries/adversary_Dire_Wolf_wNzeuQLfLUMvgHlQ.json +++ b/src/packs/adversaries/adversary_Dire_Wolf_wNzeuQLfLUMvgHlQ.json @@ -430,6 +430,12 @@ "_id": "YNKHEFQ4ucGr4Rmc", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Electric_Eels_TLzY1nDw0Bu9Ud40.json b/src/packs/adversaries/adversary_Electric_Eels_TLzY1nDw0Bu9Ud40.json index 88a0dddb..1909a74a 100644 --- a/src/packs/adversaries/adversary_Electric_Eels_TLzY1nDw0Bu9Ud40.json +++ b/src/packs/adversaries/adversary_Electric_Eels_TLzY1nDw0Bu9Ud40.json @@ -358,8 +358,14 @@ "disabled": true, "_id": "xoal60Ed3Ih7saBJ", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "duration": { "startTime": 0, "combat": null diff --git a/src/packs/adversaries/adversary_Failed_Experiment_ChwwVqowFw8hJQwT.json b/src/packs/adversaries/adversary_Failed_Experiment_ChwwVqowFw8hJQwT.json index fa963fce..70e56980 100644 --- a/src/packs/adversaries/adversary_Failed_Experiment_ChwwVqowFw8hJQwT.json +++ b/src/packs/adversaries/adversary_Failed_Experiment_ChwwVqowFw8hJQwT.json @@ -240,17 +240,23 @@ "name": "Warped Fortitude", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.physical.resistance", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "3QLH2EEtcUEZolFz", "img": "icons/creatures/magical/humanoid-silhouette-glowing-pink.webp", + "changes": [ + { + "key": "system.resistance.physical.resistance", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -303,17 +309,23 @@ "name": "Overwhelm", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.attack.damage.hpDamageMultiplier", - "type": "override", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "eGB9G0ljYCcdGbOx", "img": "icons/skills/melee/strike-slashes-orange.webp", + "changes": [ + { + "key": "system.rules.attack.damage.hpDamageMultiplier", + "mode": 5, + "value": "2", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json b/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json index 0f335dcb..975cf6aa 100644 --- a/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json +++ b/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json @@ -388,6 +388,12 @@ "_id": "Q99saHj6NOY2PSXf", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", @@ -590,6 +596,12 @@ "_id": "pWDg0MADoohKu40O", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Fallen_Warlord__Undefeated_Champion_RXkZTwBRi4dJ3JE5.json b/src/packs/adversaries/adversary_Fallen_Warlord__Undefeated_Champion_RXkZTwBRi4dJ3JE5.json index fb616c4c..6cb1c0ce 100644 --- a/src/packs/adversaries/adversary_Fallen_Warlord__Undefeated_Champion_RXkZTwBRi4dJ3JE5.json +++ b/src/packs/adversaries/adversary_Fallen_Warlord__Undefeated_Champion_RXkZTwBRi4dJ3JE5.json @@ -656,6 +656,12 @@ "vulnerable" ], "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "description": "", diff --git a/src/packs/adversaries/adversary_Giant_Beastmaster_8VZIgU12cB3cvlyH.json b/src/packs/adversaries/adversary_Giant_Beastmaster_8VZIgU12cB3cvlyH.json index 9563c287..c6a482dd 100644 --- a/src/packs/adversaries/adversary_Giant_Beastmaster_8VZIgU12cB3cvlyH.json +++ b/src/packs/adversaries/adversary_Giant_Beastmaster_8VZIgU12cB3cvlyH.json @@ -347,6 +347,12 @@ "_id": "vb1sZCOLwDNLsr3j", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Giant_Eagle_OMQ0v6PE8s1mSU0K.json b/src/packs/adversaries/adversary_Giant_Eagle_OMQ0v6PE8s1mSU0K.json index 044d51a0..a8a33586 100644 --- a/src/packs/adversaries/adversary_Giant_Eagle_OMQ0v6PE8s1mSU0K.json +++ b/src/packs/adversaries/adversary_Giant_Eagle_OMQ0v6PE8s1mSU0K.json @@ -265,17 +265,23 @@ "name": "Flying", "type": "base", "system": { - "changes": [ - { - "key": "system.difficulty", - "type": "add", - "value": "3", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "odAyKY0BSAkcO3Dd", "img": "icons/creatures/birds/raptor-hawk-flying.webp", + "changes": [ + { + "key": "system.difficulty", + "mode": 2, + "value": "3", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -419,6 +425,12 @@ "_id": "m6qqQZxukDPVcGdQ", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "act" @@ -567,8 +579,14 @@ "_id": "Sd34xywRqiF5w9sX", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Giant_Mosquitoes_IIWV4ysJPFPnTP7W.json b/src/packs/adversaries/adversary_Giant_Mosquitoes_IIWV4ysJPFPnTP7W.json index fef1d858..a74cb88d 100644 --- a/src/packs/adversaries/adversary_Giant_Mosquitoes_IIWV4ysJPFPnTP7W.json +++ b/src/packs/adversaries/adversary_Giant_Mosquitoes_IIWV4ysJPFPnTP7W.json @@ -269,15 +269,21 @@ "_id": "aATxfjeOzUYtKuU6", "img": "icons/commodities/biological/wing-insect-green.webp", "system": { - "changes": [ - { - "key": "system.difficulty", - "type": "add", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.difficulty", + "mode": 2, + "value": "2", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, @@ -379,8 +385,14 @@ "disabled": true, "_id": "dQgcYTz5vmV25Y6G", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "duration": { "startTime": 0, "combat": null diff --git a/src/packs/adversaries/adversary_Giant_Scorpion_fmfntuJ8mHRCAktP.json b/src/packs/adversaries/adversary_Giant_Scorpion_fmfntuJ8mHRCAktP.json index cb815547..03a0272d 100644 --- a/src/packs/adversaries/adversary_Giant_Scorpion_fmfntuJ8mHRCAktP.json +++ b/src/packs/adversaries/adversary_Giant_Scorpion_fmfntuJ8mHRCAktP.json @@ -433,6 +433,12 @@ "_id": "oILkLJlGNZl7KI1R", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "shortRest" diff --git a/src/packs/adversaries/adversary_Glass_Snake_8KWVLWXFhlY2kYx0.json b/src/packs/adversaries/adversary_Glass_Snake_8KWVLWXFhlY2kYx0.json index fd832332..f290875d 100644 --- a/src/packs/adversaries/adversary_Glass_Snake_8KWVLWXFhlY2kYx0.json +++ b/src/packs/adversaries/adversary_Glass_Snake_8KWVLWXFhlY2kYx0.json @@ -597,6 +597,12 @@ "_id": "Mchd23xNQ4nSWw9X", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [] }, "disabled": false, diff --git a/src/packs/adversaries/adversary_Gorgon_8mJYMpbLTb8qIOrr.json b/src/packs/adversaries/adversary_Gorgon_8mJYMpbLTb8qIOrr.json index 1a971a21..1fcfcce4 100644 --- a/src/packs/adversaries/adversary_Gorgon_8mJYMpbLTb8qIOrr.json +++ b/src/packs/adversaries/adversary_Gorgon_8mJYMpbLTb8qIOrr.json @@ -330,6 +330,12 @@ "_id": "bYBrgiSwHwYfQyjn", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.rules.conditionImmunities.hidden", diff --git a/src/packs/adversaries/adversary_Greater_Earth_Elemental_dsfB3YhoL5SudvS2.json b/src/packs/adversaries/adversary_Greater_Earth_Elemental_dsfB3YhoL5SudvS2.json index 2fe67f24..72ad8ae2 100644 --- a/src/packs/adversaries/adversary_Greater_Earth_Elemental_dsfB3YhoL5SudvS2.json +++ b/src/packs/adversaries/adversary_Greater_Earth_Elemental_dsfB3YhoL5SudvS2.json @@ -340,17 +340,23 @@ "name": "Immovable Object", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.physical.reduction", - "type": "add", - "value": "7", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "7V7qMq9in3AArwiM", "img": "icons/magic/defensive/shield-barrier-glowing-triangle-green.webp", + "changes": [ + { + "key": "system.resistance.physical.reduction", + "mode": 2, + "value": "7", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -504,6 +510,12 @@ "_id": "38MUzfbH64EMLVse", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Greater_Water_Elemental_xIICT6tEdnA7dKDV.json b/src/packs/adversaries/adversary_Greater_Water_Elemental_xIICT6tEdnA7dKDV.json index ef2cf6d5..db73a536 100644 --- a/src/packs/adversaries/adversary_Greater_Water_Elemental_xIICT6tEdnA7dKDV.json +++ b/src/packs/adversaries/adversary_Greater_Water_Elemental_xIICT6tEdnA7dKDV.json @@ -323,15 +323,21 @@ "_id": "WYqjt1tVqPEdVV5l", "type": "base", "system": { - "changes": [ - { - "key": "system.disadvantageSources", - "type": "add", - "value": "Your next action", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.disadvantageSources", + "mode": 2, + "value": "Your next action", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -456,6 +462,12 @@ "_id": "X8NF2OB23mSpDvlx", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Green_Ooze_SHXedd9zZPVfUgUa.json b/src/packs/adversaries/adversary_Green_Ooze_SHXedd9zZPVfUgUa.json index 9714a3a2..a3a76d7a 100644 --- a/src/packs/adversaries/adversary_Green_Ooze_SHXedd9zZPVfUgUa.json +++ b/src/packs/adversaries/adversary_Green_Ooze_SHXedd9zZPVfUgUa.json @@ -460,6 +460,12 @@ "_id": "yk5kR5OVLCgDWfgY", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Hallowed_Archer_kabueAo6BALApWqp.json b/src/packs/adversaries/adversary_Hallowed_Archer_kabueAo6BALApWqp.json index 64a4dfb6..eb7eafc1 100644 --- a/src/packs/adversaries/adversary_Hallowed_Archer_kabueAo6BALApWqp.json +++ b/src/packs/adversaries/adversary_Hallowed_Archer_kabueAo6BALApWqp.json @@ -234,17 +234,23 @@ "name": "Punish the Guilty", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.attack.damage.hpDamageMultiplier", - "type": "override", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "ID85zoIa5GfhNMti", "img": "icons/magic/control/buff-flight-wings-runes-red-yellow.webp", + "changes": [ + { + "key": "system.rules.attack.damage.hpDamageMultiplier", + "mode": 5, + "value": "2", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_High_Seraph_r1mbfSSwKWdcFdAU.json b/src/packs/adversaries/adversary_High_Seraph_r1mbfSSwKWdcFdAU.json index 874330d4..3dc96fd5 100644 --- a/src/packs/adversaries/adversary_High_Seraph_r1mbfSSwKWdcFdAU.json +++ b/src/packs/adversaries/adversary_High_Seraph_r1mbfSSwKWdcFdAU.json @@ -386,6 +386,12 @@ "_id": "O8G0oOf9f3qzNOAT", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Huge_Green_Ooze_6hbqmxDXFOzZJDk4.json b/src/packs/adversaries/adversary_Huge_Green_Ooze_6hbqmxDXFOzZJDk4.json index 986f3146..183719f2 100644 --- a/src/packs/adversaries/adversary_Huge_Green_Ooze_6hbqmxDXFOzZJDk4.json +++ b/src/packs/adversaries/adversary_Huge_Green_Ooze_6hbqmxDXFOzZJDk4.json @@ -429,6 +429,12 @@ "_id": "EwZ8owroJxFpg81e", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Hydra_MI126iMOOobQ1Obn.json b/src/packs/adversaries/adversary_Hydra_MI126iMOOobQ1Obn.json index 4ebd5735..9c53487a 100644 --- a/src/packs/adversaries/adversary_Hydra_MI126iMOOobQ1Obn.json +++ b/src/packs/adversaries/adversary_Hydra_MI126iMOOobQ1Obn.json @@ -510,6 +510,12 @@ "_id": "iBJ3YhEkVsGKEIVk", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.resistance.magical.immunity", diff --git a/src/packs/adversaries/adversary_Jagged_Knife_Hexer_MbBPIOxaxXYNApXz.json b/src/packs/adversaries/adversary_Jagged_Knife_Hexer_MbBPIOxaxXYNApXz.json index f42433f0..c6b2554e 100644 --- a/src/packs/adversaries/adversary_Jagged_Knife_Hexer_MbBPIOxaxXYNApXz.json +++ b/src/packs/adversaries/adversary_Jagged_Knife_Hexer_MbBPIOxaxXYNApXz.json @@ -273,6 +273,12 @@ "_id": "ihy3kvEGSOEKdNfT", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/adversaries/adversary_Jagged_Knife_Kneebreaker_CBKixLH3yhivZZuL.json b/src/packs/adversaries/adversary_Jagged_Knife_Kneebreaker_CBKixLH3yhivZZuL.json index 262d2954..3ce6a165 100644 --- a/src/packs/adversaries/adversary_Jagged_Knife_Kneebreaker_CBKixLH3yhivZZuL.json +++ b/src/packs/adversaries/adversary_Jagged_Knife_Kneebreaker_CBKixLH3yhivZZuL.json @@ -329,6 +329,12 @@ "_id": "d7sB1Qa1kJMnglqu", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.rules.attack.damage.hpDamageTakenMultiplier", diff --git a/src/packs/adversaries/adversary_Jagged_Knife_Shadow_XF4tYTq9nPJAy2ox.json b/src/packs/adversaries/adversary_Jagged_Knife_Shadow_XF4tYTq9nPJAy2ox.json index 6b005769..81b95d8b 100644 --- a/src/packs/adversaries/adversary_Jagged_Knife_Shadow_XF4tYTq9nPJAy2ox.json +++ b/src/packs/adversaries/adversary_Jagged_Knife_Shadow_XF4tYTq9nPJAy2ox.json @@ -375,15 +375,21 @@ "_id": "w5VTwlHmUjl8XCQ4", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Attacks made while Hidden", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Attacks made while Hidden", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json b/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json index 72f4626d..24683a37 100644 --- a/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json +++ b/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json @@ -346,15 +346,21 @@ "_id": "pZUEkMkCus4U7h8W", "type": "base", "system": { - "changes": [ - { - "key": "system.evasion", - "type": "override", - "value": "@system.evasion / 2", - "priority": 10 - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.evasion", + "mode": 5, + "value": "@system.evasion / 2", + "priority": 10 + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Knight_of_the_Realm_7ai2opemrclQe3VF.json b/src/packs/adversaries/adversary_Knight_of_the_Realm_7ai2opemrclQe3VF.json index f86717fc..01435922 100644 --- a/src/packs/adversaries/adversary_Knight_of_the_Realm_7ai2opemrclQe3VF.json +++ b/src/packs/adversaries/adversary_Knight_of_the_Realm_7ai2opemrclQe3VF.json @@ -250,17 +250,23 @@ "name": "Chevalier", "type": "base", "system": { - "changes": [ - { - "key": "system.difficulty", - "type": "add", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "w8wLcSsTiTU3mS7e", "img": "icons/environment/people/cavalry-heavy.webp", + "changes": [ + { + "key": "system.difficulty", + "mode": 2, + "value": "2", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -313,17 +319,23 @@ "name": "Heavily Armored", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.physical.reduction", - "type": "add", - "value": "3", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "xZjvrNRRjskY3n3j", "img": "icons/equipment/chest/breastplate-cuirass-steel-grey.webp", + "changes": [ + { + "key": "system.resistance.physical.reduction", + "mode": 2, + "value": "3", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Kraken_4nqv3ZwJGjnmic8j.json b/src/packs/adversaries/adversary_Kraken_4nqv3ZwJGjnmic8j.json index f03b6408..4bcdc15d 100644 --- a/src/packs/adversaries/adversary_Kraken_4nqv3ZwJGjnmic8j.json +++ b/src/packs/adversaries/adversary_Kraken_4nqv3ZwJGjnmic8j.json @@ -378,6 +378,12 @@ "_id": "Xes6ZIE01CCN67KF", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Masked_Thief_niBpVU7yeo5ccskE.json b/src/packs/adversaries/adversary_Masked_Thief_niBpVU7yeo5ccskE.json index 1d9b30b2..77d48be3 100644 --- a/src/packs/adversaries/adversary_Masked_Thief_niBpVU7yeo5ccskE.json +++ b/src/packs/adversaries/adversary_Masked_Thief_niBpVU7yeo5ccskE.json @@ -402,6 +402,12 @@ "_id": "zMut1PRphlwE0xOa", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Minor_Chaos_Elemental_sRn4bqerfARvhgSV.json b/src/packs/adversaries/adversary_Minor_Chaos_Elemental_sRn4bqerfARvhgSV.json index 7c4bbdba..9ddfb4f3 100644 --- a/src/packs/adversaries/adversary_Minor_Chaos_Elemental_sRn4bqerfARvhgSV.json +++ b/src/packs/adversaries/adversary_Minor_Chaos_Elemental_sRn4bqerfARvhgSV.json @@ -235,15 +235,21 @@ "_id": "vwc93gtzFoFZj4XT", "img": "icons/magic/defensive/shield-barrier-flaming-diamond-blue.webp", "system": { - "changes": [ - { - "key": "system.resistance.magical.resistance", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.resistance.magical.resistance", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -377,6 +383,12 @@ "_id": "KIyV2eXDmmymXY5y", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "shortRest" diff --git a/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json b/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json index 8bc19d39..33677263 100644 --- a/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json +++ b/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json @@ -447,6 +447,12 @@ "_id": "YznseQP43jNrk07h", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "scene" diff --git a/src/packs/adversaries/adversary_Oak_Treant_XK78QUfY8c8Go8Uv.json b/src/packs/adversaries/adversary_Oak_Treant_XK78QUfY8c8Go8Uv.json index edc0ea82..c5feed37 100644 --- a/src/packs/adversaries/adversary_Oak_Treant_XK78QUfY8c8Go8Uv.json +++ b/src/packs/adversaries/adversary_Oak_Treant_XK78QUfY8c8Go8Uv.json @@ -394,6 +394,12 @@ "_id": "3PY5KIG6d3dr3dty", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + }, "changes": [ { "key": "system.resistance.physical.resistance", diff --git a/src/packs/adversaries/adversary_Outer_Realms_Abomination_A0SeeDzwjvqOsyof.json b/src/packs/adversaries/adversary_Outer_Realms_Abomination_A0SeeDzwjvqOsyof.json index e9a0b5f7..3e5bacf3 100644 --- a/src/packs/adversaries/adversary_Outer_Realms_Abomination_A0SeeDzwjvqOsyof.json +++ b/src/packs/adversaries/adversary_Outer_Realms_Abomination_A0SeeDzwjvqOsyof.json @@ -313,15 +313,21 @@ "_id": "rpkjVdlJYI5dB99B", "type": "base", "system": { - "changes": [ - { - "key": "system.disadvantageSources", - "type": "add", - "value": "On your next action roll.", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.disadvantageSources", + "mode": 2, + "value": "On your next action roll.", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -439,6 +445,12 @@ "_id": "edEZER9ImWicMwRb", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "scene" diff --git a/src/packs/adversaries/adversary_Perfected_Zombie_CP6iRfHdyFWniTHY.json b/src/packs/adversaries/adversary_Perfected_Zombie_CP6iRfHdyFWniTHY.json index 5753337e..06a18345 100644 --- a/src/packs/adversaries/adversary_Perfected_Zombie_CP6iRfHdyFWniTHY.json +++ b/src/packs/adversaries/adversary_Perfected_Zombie_CP6iRfHdyFWniTHY.json @@ -446,6 +446,12 @@ "_id": "Q5eeh0B6qaXFS1Ck", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "shortRest", diff --git a/src/packs/adversaries/adversary_Pirate_Raiders_5YgEajn0wa4i85kC.json b/src/packs/adversaries/adversary_Pirate_Raiders_5YgEajn0wa4i85kC.json index ccd07cf1..94137c2f 100644 --- a/src/packs/adversaries/adversary_Pirate_Raiders_5YgEajn0wa4i85kC.json +++ b/src/packs/adversaries/adversary_Pirate_Raiders_5YgEajn0wa4i85kC.json @@ -337,8 +337,14 @@ "disabled": true, "_id": "OU05YZwFQffawtna", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "duration": { "startTime": 0, "combat": null diff --git a/src/packs/adversaries/adversary_Red_Ooze_9rVlbJVrDNn1x7PS.json b/src/packs/adversaries/adversary_Red_Ooze_9rVlbJVrDNn1x7PS.json index 3b54337a..f74da475 100644 --- a/src/packs/adversaries/adversary_Red_Ooze_9rVlbJVrDNn1x7PS.json +++ b/src/packs/adversaries/adversary_Red_Ooze_9rVlbJVrDNn1x7PS.json @@ -404,6 +404,12 @@ "_id": "9UBLk9M87VIUziAQ", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Siren_BK4jwyXSRx7IOQiO.json b/src/packs/adversaries/adversary_Siren_BK4jwyXSRx7IOQiO.json index 43af1f43..39f6a5b9 100644 --- a/src/packs/adversaries/adversary_Siren_BK4jwyXSRx7IOQiO.json +++ b/src/packs/adversaries/adversary_Siren_BK4jwyXSRx7IOQiO.json @@ -411,6 +411,12 @@ "_id": "xrm5786ckKbMYHjn", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Skeleton_Archer_7X5q7a6ueeHs5oA9.json b/src/packs/adversaries/adversary_Skeleton_Archer_7X5q7a6ueeHs5oA9.json index 5e2e8200..f0dde9f0 100644 --- a/src/packs/adversaries/adversary_Skeleton_Archer_7X5q7a6ueeHs5oA9.json +++ b/src/packs/adversaries/adversary_Skeleton_Archer_7X5q7a6ueeHs5oA9.json @@ -235,17 +235,23 @@ "name": "Opportunist", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.attack.damage.hpDamageMultiplier", - "type": "override", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "O03vYbyNLO3YPZGo", "img": "icons/skills/targeting/crosshair-triple-strike-orange.webp", + "changes": [ + { + "key": "system.rules.attack.damage.hpDamageMultiplier", + "mode": 5, + "value": "2", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Skeleton_Warrior_10YIQl0lvCJXZLfX.json b/src/packs/adversaries/adversary_Skeleton_Warrior_10YIQl0lvCJXZLfX.json index 4cf72b0b..726b06e1 100644 --- a/src/packs/adversaries/adversary_Skeleton_Warrior_10YIQl0lvCJXZLfX.json +++ b/src/packs/adversaries/adversary_Skeleton_Warrior_10YIQl0lvCJXZLfX.json @@ -237,15 +237,21 @@ "_id": "zTepuF1Z5OObQdSi", "img": "icons/magic/death/bones-crossed-orange.webp", "system": { - "changes": [ - { - "key": "system.resistance.physical.resistance", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.resistance.physical.resistance", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Spectral_Archer_5tCkhnBByUIN5UdG.json b/src/packs/adversaries/adversary_Spectral_Archer_5tCkhnBByUIN5UdG.json index bda82248..5b9cbb65 100644 --- a/src/packs/adversaries/adversary_Spectral_Archer_5tCkhnBByUIN5UdG.json +++ b/src/packs/adversaries/adversary_Spectral_Archer_5tCkhnBByUIN5UdG.json @@ -270,17 +270,23 @@ "name": "Ghost", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.physical.resistance", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "xNkkl7nwKFkiB9Rv", "img": "icons/magic/death/undead-ghost-scream-teal.webp", + "changes": [ + { + "key": "system.resistance.physical.resistance", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Spectral_Captain_65cSO3EQEh6ZH6Xk.json b/src/packs/adversaries/adversary_Spectral_Captain_65cSO3EQEh6ZH6Xk.json index 20668427..0572e018 100644 --- a/src/packs/adversaries/adversary_Spectral_Captain_65cSO3EQEh6ZH6Xk.json +++ b/src/packs/adversaries/adversary_Spectral_Captain_65cSO3EQEh6ZH6Xk.json @@ -270,17 +270,23 @@ "name": "Ghost", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.physical.resistance", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "kZhvwDvfcYQ10reO", "img": "icons/magic/death/undead-ghost-scream-teal.webp", + "changes": [ + { + "key": "system.resistance.physical.resistance", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Spectral_Guardian_UFVGl1osOsJTneLf.json b/src/packs/adversaries/adversary_Spectral_Guardian_UFVGl1osOsJTneLf.json index e9792485..85893254 100644 --- a/src/packs/adversaries/adversary_Spectral_Guardian_UFVGl1osOsJTneLf.json +++ b/src/packs/adversaries/adversary_Spectral_Guardian_UFVGl1osOsJTneLf.json @@ -270,17 +270,23 @@ "name": "Ghost", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.physical.resistance", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "QDXyAMk33kJGe6hU", "img": "icons/magic/death/undead-ghost-scream-teal.webp", + "changes": [ + { + "key": "system.resistance.physical.resistance", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json b/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json index 45093ea7..52869085 100644 --- a/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json +++ b/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json @@ -352,6 +352,12 @@ "_id": "6UgMuuJ8ZygbCsDh", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/adversaries/adversary_Swarm_of_Rats_qNgs3AbLyJrY19nt.json b/src/packs/adversaries/adversary_Swarm_of_Rats_qNgs3AbLyJrY19nt.json index 49b75790..28d5dabe 100644 --- a/src/packs/adversaries/adversary_Swarm_of_Rats_qNgs3AbLyJrY19nt.json +++ b/src/packs/adversaries/adversary_Swarm_of_Rats_qNgs3AbLyJrY19nt.json @@ -278,8 +278,14 @@ "disabled": true, "_id": "FOV6AzngiR0PZyuN", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "duration": { "startTime": 0, "combat": null diff --git a/src/packs/adversaries/adversary_Sylvan_Soldier_VtFBt9XBE0WrGGxP.json b/src/packs/adversaries/adversary_Sylvan_Soldier_VtFBt9XBE0WrGGxP.json index dfb6fd42..f3ce03c3 100644 --- a/src/packs/adversaries/adversary_Sylvan_Soldier_VtFBt9XBE0WrGGxP.json +++ b/src/packs/adversaries/adversary_Sylvan_Soldier_VtFBt9XBE0WrGGxP.json @@ -489,8 +489,14 @@ "_id": "xyXPmPIOtqXYF1TJ", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Tangle_Bramble_Swarm_PKSXFuaIHUCoH63A.json b/src/packs/adversaries/adversary_Tangle_Bramble_Swarm_PKSXFuaIHUCoH63A.json index 6ad802aa..f8f93cf2 100644 --- a/src/packs/adversaries/adversary_Tangle_Bramble_Swarm_PKSXFuaIHUCoH63A.json +++ b/src/packs/adversaries/adversary_Tangle_Bramble_Swarm_PKSXFuaIHUCoH63A.json @@ -421,8 +421,14 @@ "_id": "PdkhaTw2j15KJwBf", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, @@ -467,8 +473,14 @@ "disabled": true, "_id": "ki4vrzrFcEYtGeJu", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "duration": { "startTime": 0, "combat": null diff --git a/src/packs/adversaries/adversary_Vault_Guardian_Gaoler_JqYraOqNmmhHk4Yy.json b/src/packs/adversaries/adversary_Vault_Guardian_Gaoler_JqYraOqNmmhHk4Yy.json index 23a6048a..97c493a8 100644 --- a/src/packs/adversaries/adversary_Vault_Guardian_Gaoler_JqYraOqNmmhHk4Yy.json +++ b/src/packs/adversaries/adversary_Vault_Guardian_Gaoler_JqYraOqNmmhHk4Yy.json @@ -323,6 +323,12 @@ "_id": "6TZlstmWJPbeoL7i", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json b/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json index 8afe5f9e..ba3f5c33 100644 --- a/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json +++ b/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json @@ -297,15 +297,21 @@ "_id": "Fo5bLYlmYGtQFAGg", "type": "base", "system": { - "changes": [ - { - "key": "system.disadvantageSources", - "type": "add", - "value": "On attack rolls while you're within Very Close range of the Sentinel", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.disadvantageSources", + "mode": 2, + "value": "On attack rolls while you're within Very Close range of the Sentinel", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Vault_Guardian_Turret_c5hGdvY5UnSjlHws.json b/src/packs/adversaries/adversary_Vault_Guardian_Turret_c5hGdvY5UnSjlHws.json index 906e05ff..018d5b58 100644 --- a/src/packs/adversaries/adversary_Vault_Guardian_Turret_c5hGdvY5UnSjlHws.json +++ b/src/packs/adversaries/adversary_Vault_Guardian_Turret_c5hGdvY5UnSjlHws.json @@ -302,15 +302,21 @@ "_id": "yQ85C0JHRG1pwu8a", "type": "base", "system": { - "changes": [ - { - "key": "system.evasion", - "type": "override", - "value": "@system.evasion / 2", - "priority": 10 - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.evasion", + "mode": 5, + "value": "@system.evasion / 2", + "priority": 10 + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/adversaries/adversary_Volcanic_Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json b/src/packs/adversaries/adversary_Volcanic_Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json index 04663981..e360f0c8 100644 --- a/src/packs/adversaries/adversary_Volcanic_Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json +++ b/src/packs/adversaries/adversary_Volcanic_Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json @@ -376,17 +376,23 @@ "name": "Injured Wings", "type": "base", "system": { - "changes": [ - { - "key": "system.difficulty", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "zCi90lgFAaA7yrJG", "img": "icons/commodities/biological/wing-green.webp", + "changes": [ + { + "key": "system.difficulty", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -867,6 +873,12 @@ "_id": "YUjdwrEZ4zn7WR9X", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Volcanic_Dragon__Molten_Scourge_eArAPuB38CNR0ZIM.json b/src/packs/adversaries/adversary_Volcanic_Dragon__Molten_Scourge_eArAPuB38CNR0ZIM.json index cce2c07e..d4babd71 100644 --- a/src/packs/adversaries/adversary_Volcanic_Dragon__Molten_Scourge_eArAPuB38CNR0ZIM.json +++ b/src/packs/adversaries/adversary_Volcanic_Dragon__Molten_Scourge_eArAPuB38CNR0ZIM.json @@ -734,6 +734,12 @@ "_id": "xmzA6NC9zrulhzQs", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Volcanic_Dragon__Obsidian_Predator_ladm7wykhZczYzrQ.json b/src/packs/adversaries/adversary_Volcanic_Dragon__Obsidian_Predator_ladm7wykhZczYzrQ.json index 29117035..82daed6a 100644 --- a/src/packs/adversaries/adversary_Volcanic_Dragon__Obsidian_Predator_ladm7wykhZczYzrQ.json +++ b/src/packs/adversaries/adversary_Volcanic_Dragon__Obsidian_Predator_ladm7wykhZczYzrQ.json @@ -321,17 +321,23 @@ "name": "Flying", "type": "base", "system": { - "changes": [ - { - "key": "system.difficulty", - "type": "add", - "value": "3", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "8o8yG73ZfrZ3hb5i", "img": "icons/commodities/biological/wing-green.webp", + "changes": [ + { + "key": "system.difficulty", + "mode": 2, + "value": "3", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -384,17 +390,23 @@ "name": "Obsidian Scales", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.physical.resistance", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "Jr9SlkRnkroulYhy", "img": "icons/commodities/leather/scale-chitin-grey.webp", + "changes": [ + { + "key": "system.resistance.physical.resistance", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -539,6 +551,12 @@ "_id": "qtIaAZDW8QsjILgb", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [] }, "disabled": false, diff --git a/src/packs/adversaries/adversary_Weaponmaster_ZNbQ2jg35LG4t9eH.json b/src/packs/adversaries/adversary_Weaponmaster_ZNbQ2jg35LG4t9eH.json index f06a2c72..8eaf56f9 100644 --- a/src/packs/adversaries/adversary_Weaponmaster_ZNbQ2jg35LG4t9eH.json +++ b/src/packs/adversaries/adversary_Weaponmaster_ZNbQ2jg35LG4t9eH.json @@ -319,6 +319,12 @@ "_id": "j2jYmYbtWXvq32yX", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Young_Dryad_8yUj2Mzvnifhxegm.json b/src/packs/adversaries/adversary_Young_Dryad_8yUj2Mzvnifhxegm.json index 30db7ff7..9d7f66d0 100644 --- a/src/packs/adversaries/adversary_Young_Dryad_8yUj2Mzvnifhxegm.json +++ b/src/packs/adversaries/adversary_Young_Dryad_8yUj2Mzvnifhxegm.json @@ -362,6 +362,12 @@ "_id": "k8LzBWRZo6VPqvpH", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/adversaries/adversary_Young_Ice_Dragon_UGPiPLJsPvMTSKEF.json b/src/packs/adversaries/adversary_Young_Ice_Dragon_UGPiPLJsPvMTSKEF.json index f5324abd..6c55ba15 100644 --- a/src/packs/adversaries/adversary_Young_Ice_Dragon_UGPiPLJsPvMTSKEF.json +++ b/src/packs/adversaries/adversary_Young_Ice_Dragon_UGPiPLJsPvMTSKEF.json @@ -500,6 +500,12 @@ "_id": "g9bUvmw3jet6T99e", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [] }, "disabled": false, @@ -628,6 +634,12 @@ "_id": "40cFHuNdEvbUZ9rs", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", @@ -756,6 +768,12 @@ "_id": "1JlRxa07i8T1a9x6", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.disadvantageSources", diff --git a/src/packs/adversaries/adversary_Zombie_Legion_YhJrP7rTBiRdX5Fp.json b/src/packs/adversaries/adversary_Zombie_Legion_YhJrP7rTBiRdX5Fp.json index ee324e16..2c3495ff 100644 --- a/src/packs/adversaries/adversary_Zombie_Legion_YhJrP7rTBiRdX5Fp.json +++ b/src/packs/adversaries/adversary_Zombie_Legion_YhJrP7rTBiRdX5Fp.json @@ -259,17 +259,23 @@ "name": "Unyielding", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.physical.resistance", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "D1lCoe9WVr6vYuD9", "img": "icons/magic/defensive/shield-barrier-blue.webp", + "changes": [ + { + "key": "system.resistance.physical.resistance", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -428,8 +434,14 @@ "disabled": true, "_id": "9D6SteWlhbfMPhvt", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "duration": { "startTime": 0, "combat": null diff --git a/src/packs/adversaries/adversary_Zombie_Pack_Nf0v43rtflV56V2T.json b/src/packs/adversaries/adversary_Zombie_Pack_Nf0v43rtflV56V2T.json index 0b6d0177..f418758a 100644 --- a/src/packs/adversaries/adversary_Zombie_Pack_Nf0v43rtflV56V2T.json +++ b/src/packs/adversaries/adversary_Zombie_Pack_Nf0v43rtflV56V2T.json @@ -309,8 +309,14 @@ "disabled": true, "_id": "aWWZTlNS9zYoUay7", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "duration": { "startTime": 0, "combat": null diff --git a/src/packs/ancestries/feature_Celestial_Trance_TfolXWFG2W2hx6sK.json b/src/packs/ancestries/feature_Celestial_Trance_TfolXWFG2W2hx6sK.json index 0321223a..7cbe132e 100644 --- a/src/packs/ancestries/feature_Celestial_Trance_TfolXWFG2W2hx6sK.json +++ b/src/packs/ancestries/feature_Celestial_Trance_TfolXWFG2W2hx6sK.json @@ -24,21 +24,27 @@ "_id": "LqQvZJJLNMnFkt1D", "img": "icons/magic/perception/orb-crystal-ball-scrying-blue.webp", "system": { - "changes": [ - { - "key": "system.bonuses.rest.shortRest.shortMoves", - "type": "add", - "value": "1", - "priority": null - }, - { - "key": "system.bonuses.rest.longRest.longMoves", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.rest.shortRest.shortMoves", + "mode": 2, + "value": "1", + "priority": null + }, + { + "key": "system.bonuses.rest.longRest.longMoves", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_Dread_Visage_i92lYjDhVB0LyPid.json b/src/packs/ancestries/feature_Dread_Visage_i92lYjDhVB0LyPid.json index 5d72e579..bbe35d19 100644 --- a/src/packs/ancestries/feature_Dread_Visage_i92lYjDhVB0LyPid.json +++ b/src/packs/ancestries/feature_Dread_Visage_i92lYjDhVB0LyPid.json @@ -24,15 +24,21 @@ "_id": "2Gd6iHQX521aAZqC", "img": "icons/magic/control/fear-fright-monster-red.webp", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Dread Visage: Rolls to intimidate hostile creatures", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Dread Visage: Rolls to intimidate hostile creatures", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_Efficient_2xlqKOkDxWHbuj4t.json b/src/packs/ancestries/feature_Efficient_2xlqKOkDxWHbuj4t.json index 5a567695..81f19a2f 100644 --- a/src/packs/ancestries/feature_Efficient_2xlqKOkDxWHbuj4t.json +++ b/src/packs/ancestries/feature_Efficient_2xlqKOkDxWHbuj4t.json @@ -24,21 +24,27 @@ "_id": "EEryWN2nE33ppGHi", "img": "icons/magic/time/clock-stopwatch-white-blue.webp", "system": { - "changes": [ - { - "key": "system.bonuses.rest.shortRest.longMoves", - "type": "add", - "value": "1", - "priority": null - }, - { - "key": "system.bonuses.rest.shortRest.shortMoves", - "type": "add", - "value": "-1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.rest.shortRest.longMoves", + "mode": 2, + "value": "1", + "priority": null + }, + { + "key": "system.bonuses.rest.shortRest.shortMoves", + "mode": 2, + "value": "-1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_Endurance_tXWEMdLXafUSZTbK.json b/src/packs/ancestries/feature_Endurance_tXWEMdLXafUSZTbK.json index ecf3d148..3e64fece 100644 --- a/src/packs/ancestries/feature_Endurance_tXWEMdLXafUSZTbK.json +++ b/src/packs/ancestries/feature_Endurance_tXWEMdLXafUSZTbK.json @@ -24,15 +24,21 @@ "_id": "db8W2Q0Qty84XV0x", "img": "icons/magic/control/buff-strength-muscle-damage.webp", "system": { - "changes": [ - { - "key": "system.resources.hitPoints.max", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.resources.hitPoints.max", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_High_Stamina_HMXNJZ7ynzajR2KT.json b/src/packs/ancestries/feature_High_Stamina_HMXNJZ7ynzajR2KT.json index c653d13b..769bec96 100644 --- a/src/packs/ancestries/feature_High_Stamina_HMXNJZ7ynzajR2KT.json +++ b/src/packs/ancestries/feature_High_Stamina_HMXNJZ7ynzajR2KT.json @@ -24,15 +24,21 @@ "_id": "Xl3TsKUJcl6vi1ly", "img": "icons/magic/control/buff-flight-wings-runes-purple-orange.webp", "system": { - "changes": [ - { - "key": "system.resources.stress.max", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.resources.stress.max", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_Natural_Climber_soQvPL0MrTLLcc31.json b/src/packs/ancestries/feature_Natural_Climber_soQvPL0MrTLLcc31.json index 3817b5bd..fd02b72f 100644 --- a/src/packs/ancestries/feature_Natural_Climber_soQvPL0MrTLLcc31.json +++ b/src/packs/ancestries/feature_Natural_Climber_soQvPL0MrTLLcc31.json @@ -24,15 +24,21 @@ "_id": "HQeQH9gUfrjlWWcg", "img": "icons/magic/nature/root-vine-barrier-wall-brown.webp", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Agility Rolls that involve balancing and climbing", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Agility Rolls that involve balancing and climbing", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_Nimble_3lNqft3LmOlEIEkw.json b/src/packs/ancestries/feature_Nimble_3lNqft3LmOlEIEkw.json index d7bf9dd4..d56ab3ac 100644 --- a/src/packs/ancestries/feature_Nimble_3lNqft3LmOlEIEkw.json +++ b/src/packs/ancestries/feature_Nimble_3lNqft3LmOlEIEkw.json @@ -24,15 +24,21 @@ "_id": "zaxVYqKzUYDJ3SDq", "img": "icons/skills/movement/arrows-up-trio-red.webp", "system": { - "changes": [ - { - "key": "system.evasion", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.evasion", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_Retract_UFR67BUOhNGLFyg9.json b/src/packs/ancestries/feature_Retract_UFR67BUOhNGLFyg9.json index 89cf8b9e..eb9696b2 100644 --- a/src/packs/ancestries/feature_Retract_UFR67BUOhNGLFyg9.json +++ b/src/packs/ancestries/feature_Retract_UFR67BUOhNGLFyg9.json @@ -63,6 +63,12 @@ "_id": "3V4FPoyjJUnFP9WS", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.resistance.physical.resistance", diff --git a/src/packs/ancestries/feature_Retracting_Claws_Zj69cAeb3NjIa8Hn.json b/src/packs/ancestries/feature_Retracting_Claws_Zj69cAeb3NjIa8Hn.json index 4f8a7158..b9b000f4 100644 --- a/src/packs/ancestries/feature_Retracting_Claws_Zj69cAeb3NjIa8Hn.json +++ b/src/packs/ancestries/feature_Retracting_Claws_Zj69cAeb3NjIa8Hn.json @@ -78,6 +78,12 @@ "_id": "pO76svFkmWmZ6LjC", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/ancestries/feature_Scales_u8ZhV962rNmUlzkp.json b/src/packs/ancestries/feature_Scales_u8ZhV962rNmUlzkp.json index 956d4aa3..fbf63533 100644 --- a/src/packs/ancestries/feature_Scales_u8ZhV962rNmUlzkp.json +++ b/src/packs/ancestries/feature_Scales_u8ZhV962rNmUlzkp.json @@ -24,15 +24,21 @@ "_id": "b6Pkwwk7pgBeeUTe", "img": "icons/commodities/leather/scales-brown.webp", "system": { - "changes": [ - { - "key": "system.rules.damageReduction.stressDamageReduction.severe.cost", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.rules.damageReduction.stressDamageReduction.severe.cost", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_Shell_A6a87OWA3tx16g9V.json b/src/packs/ancestries/feature_Shell_A6a87OWA3tx16g9V.json index 3063966e..f07fff69 100644 --- a/src/packs/ancestries/feature_Shell_A6a87OWA3tx16g9V.json +++ b/src/packs/ancestries/feature_Shell_A6a87OWA3tx16g9V.json @@ -24,21 +24,27 @@ "_id": "41uiZKXzSSomf9YD", "img": "icons/creatures/reptiles/turtle-shell-glowing-green.webp", "system": { - "changes": [ - { - "key": "system.damageThresholds.major", - "type": "add", - "value": "@prof", - "priority": 21 - }, - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "@prof", - "priority": 21 - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.damageThresholds.major", + "mode": 2, + "value": "@prof", + "priority": 21 + }, + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "@prof", + "priority": 21 + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_Thick_Skin_S0Ww7pYOSREt8qKg.json b/src/packs/ancestries/feature_Thick_Skin_S0Ww7pYOSREt8qKg.json index e3712cd5..7bc10752 100644 --- a/src/packs/ancestries/feature_Thick_Skin_S0Ww7pYOSREt8qKg.json +++ b/src/packs/ancestries/feature_Thick_Skin_S0Ww7pYOSREt8qKg.json @@ -24,15 +24,21 @@ "_id": "4Lc40mNnRInTKMC5", "img": "icons/magic/defensive/shield-barrier-glowing-triangle-orange.webp", "system": { - "changes": [ - { - "key": "system.rules.damageReduction.stressDamageReduction.minor.cost", - "type": "override", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.rules.damageReduction.stressDamageReduction.minor.cost", + "mode": 5, + "value": "2", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_Tusks_YhxD1ujZpftPu19w.json b/src/packs/ancestries/feature_Tusks_YhxD1ujZpftPu19w.json index 53c3de82..6038f2c6 100644 --- a/src/packs/ancestries/feature_Tusks_YhxD1ujZpftPu19w.json +++ b/src/packs/ancestries/feature_Tusks_YhxD1ujZpftPu19w.json @@ -87,21 +87,27 @@ "_id": "klEyAxQa5YHXVnrl", "img": "icons/creatures/abilities/fang-tooth-blood-red.webp", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.dice", - "type": "add", - "value": "1d6", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.dice", - "type": "add", - "value": "1d6", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.dice", + "mode": 2, + "value": "1d6", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.dice", + "mode": 2, + "value": "1d6", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/ancestries/feature_Wings_WquAjoOcso8lwySW.json b/src/packs/ancestries/feature_Wings_WquAjoOcso8lwySW.json index b90b6076..9941432e 100644 --- a/src/packs/ancestries/feature_Wings_WquAjoOcso8lwySW.json +++ b/src/packs/ancestries/feature_Wings_WquAjoOcso8lwySW.json @@ -54,15 +54,21 @@ "_id": "zD3xVdwkEQi2ivOn", "img": "icons/creatures/abilities/wing-batlike-white-blue.webp", "system": { - "changes": [ - { - "key": "system.evasion", - "type": "add", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.evasion", + "mode": 2, + "value": "2", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/beastforms/beastform_Agile_Scout_a9UoCwtrbgKk02mK.json b/src/packs/beastforms/beastform_Agile_Scout_a9UoCwtrbgKk02mK.json index 0fc7a23d..bd9bfffb 100644 --- a/src/packs/beastforms/beastform_Agile_Scout_a9UoCwtrbgKk02mK.json +++ b/src/packs/beastforms/beastform_Agile_Scout_a9UoCwtrbgKk02mK.json @@ -62,25 +62,25 @@ "changes": [ { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "0", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "agility", "priority": null } diff --git a/src/packs/beastforms/beastform_Aquatic_Predator_ItBVeCl2u5uetgy7.json b/src/packs/beastforms/beastform_Aquatic_Predator_ItBVeCl2u5uetgy7.json index 9cf209e2..5287de84 100644 --- a/src/packs/beastforms/beastform_Aquatic_Predator_ItBVeCl2u5uetgy7.json +++ b/src/packs/beastforms/beastform_Aquatic_Predator_ItBVeCl2u5uetgy7.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "4", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "6", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "agility", "priority": null } diff --git a/src/packs/beastforms/beastform_Aquatic_Scout_qqzdFCxyYupWZK23.json b/src/packs/beastforms/beastform_Aquatic_Scout_qqzdFCxyYupWZK23.json index 7816fd93..95bea914 100644 --- a/src/packs/beastforms/beastform_Aquatic_Scout_qqzdFCxyYupWZK23.json +++ b/src/packs/beastforms/beastform_Aquatic_Scout_qqzdFCxyYupWZK23.json @@ -62,25 +62,25 @@ "changes": [ { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "0", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "agility", "priority": null } diff --git a/src/packs/beastforms/beastform_Armored_Sentry_8pUHJv3BYdjA4Qdf.json b/src/packs/beastforms/beastform_Armored_Sentry_8pUHJv3BYdjA4Qdf.json index bc9187f5..ba18c05f 100644 --- a/src/packs/beastforms/beastform_Armored_Sentry_8pUHJv3BYdjA4Qdf.json +++ b/src/packs/beastforms/beastform_Armored_Sentry_8pUHJv3BYdjA4Qdf.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "2", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "strength", "priority": null } diff --git a/src/packs/beastforms/beastform_Epic_Aquatic_Beast_wT4xbF99I55yjKZV.json b/src/packs/beastforms/beastform_Epic_Aquatic_Beast_wT4xbF99I55yjKZV.json index 5131fd69..0dfe9c20 100644 --- a/src/packs/beastforms/beastform_Epic_Aquatic_Beast_wT4xbF99I55yjKZV.json +++ b/src/packs/beastforms/beastform_Epic_Aquatic_Beast_wT4xbF99I55yjKZV.json @@ -65,31 +65,31 @@ "changes": [ { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "10", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "agility", "priority": null } diff --git a/src/packs/beastforms/beastform_Great_Predator_afbMt4Ld6nY3mw0N.json b/src/packs/beastforms/beastform_Great_Predator_afbMt4Ld6nY3mw0N.json index d8d41890..450a1312 100644 --- a/src/packs/beastforms/beastform_Great_Predator_afbMt4Ld6nY3mw0N.json +++ b/src/packs/beastforms/beastform_Great_Predator_afbMt4Ld6nY3mw0N.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "4", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "8", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "strength", "priority": null } diff --git a/src/packs/beastforms/beastform_Great_Winged_Beast_b4BMnTbJ3iPPidSb.json b/src/packs/beastforms/beastform_Great_Winged_Beast_b4BMnTbJ3iPPidSb.json index e3842c7e..c04b2182 100644 --- a/src/packs/beastforms/beastform_Great_Winged_Beast_b4BMnTbJ3iPPidSb.json +++ b/src/packs/beastforms/beastform_Great_Winged_Beast_b4BMnTbJ3iPPidSb.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "6", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "finesse", "priority": null } diff --git a/src/packs/beastforms/beastform_Household_Friend_iDmOtiHJJ80AIAVT.json b/src/packs/beastforms/beastform_Household_Friend_iDmOtiHJJ80AIAVT.json index ff7daa91..cfb6aea7 100644 --- a/src/packs/beastforms/beastform_Household_Friend_iDmOtiHJJ80AIAVT.json +++ b/src/packs/beastforms/beastform_Household_Friend_iDmOtiHJJ80AIAVT.json @@ -62,25 +62,25 @@ "changes": [ { "key": "system.traits.instinct.value", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "1", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "instinct", "priority": null } diff --git a/src/packs/beastforms/beastform_Legendary_Beast_mqP6z4Wg4K3oDAom.json b/src/packs/beastforms/beastform_Legendary_Beast_mqP6z4Wg4K3oDAom.json index dd35735b..60ba7cd0 100644 --- a/src/packs/beastforms/beastform_Legendary_Beast_mqP6z4Wg4K3oDAom.json +++ b/src/packs/beastforms/beastform_Legendary_Beast_mqP6z4Wg4K3oDAom.json @@ -49,13 +49,13 @@ "changes": [ { "key": "system.bonuses.damage.physical.bonus", - "type": "add", + "mode": 2, "value": "6", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "2", "priority": null } diff --git a/src/packs/beastforms/beastform_Legendary_Hybrid_rRUtgcUjimlpPhnn.json b/src/packs/beastforms/beastform_Legendary_Hybrid_rRUtgcUjimlpPhnn.json index 58edfabc..4575820e 100644 --- a/src/packs/beastforms/beastform_Legendary_Hybrid_rRUtgcUjimlpPhnn.json +++ b/src/packs/beastforms/beastform_Legendary_Hybrid_rRUtgcUjimlpPhnn.json @@ -49,31 +49,31 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "8", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "strength", "priority": null } diff --git a/src/packs/beastforms/beastform_Massive_Behemoth_qjwMzPn33aKZACkv.json b/src/packs/beastforms/beastform_Massive_Behemoth_qjwMzPn33aKZACkv.json index 1b34daf9..35715056 100644 --- a/src/packs/beastforms/beastform_Massive_Behemoth_qjwMzPn33aKZACkv.json +++ b/src/packs/beastforms/beastform_Massive_Behemoth_qjwMzPn33aKZACkv.json @@ -66,31 +66,31 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "4", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "12", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "strength", "priority": null } diff --git a/src/packs/beastforms/beastform_Mighty_Lizard_94tvcC3D5Kp4lzuN.json b/src/packs/beastforms/beastform_Mighty_Lizard_94tvcC3D5Kp4lzuN.json index 8f76f675..390bf054 100644 --- a/src/packs/beastforms/beastform_Mighty_Lizard_94tvcC3D5Kp4lzuN.json +++ b/src/packs/beastforms/beastform_Mighty_Lizard_94tvcC3D5Kp4lzuN.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.instinct.value", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "7", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "instinct", "priority": null } diff --git a/src/packs/beastforms/beastform_Mighty_Strider_zRLjqKx4Rn2TjivL.json b/src/packs/beastforms/beastform_Mighty_Strider_zRLjqKx4Rn2TjivL.json index 5393c188..adb9627b 100644 --- a/src/packs/beastforms/beastform_Mighty_Strider_zRLjqKx4Rn2TjivL.json +++ b/src/packs/beastforms/beastform_Mighty_Strider_zRLjqKx4Rn2TjivL.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "1", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "agility", "priority": null } diff --git a/src/packs/beastforms/beastform_Mythic_Aerial_Hunter_jV6EuEacyQlHW4SN.json b/src/packs/beastforms/beastform_Mythic_Aerial_Hunter_jV6EuEacyQlHW4SN.json index 80571c43..dc373c27 100644 --- a/src/packs/beastforms/beastform_Mythic_Aerial_Hunter_jV6EuEacyQlHW4SN.json +++ b/src/packs/beastforms/beastform_Mythic_Aerial_Hunter_jV6EuEacyQlHW4SN.json @@ -65,31 +65,31 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "4", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "11", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "finesse", "priority": null } diff --git a/src/packs/beastforms/beastform_Mythic_Beast_kObobka52JdpWBSu.json b/src/packs/beastforms/beastform_Mythic_Beast_kObobka52JdpWBSu.json index 84dfb32b..cd879ac0 100644 --- a/src/packs/beastforms/beastform_Mythic_Beast_kObobka52JdpWBSu.json +++ b/src/packs/beastforms/beastform_Mythic_Beast_kObobka52JdpWBSu.json @@ -49,19 +49,19 @@ "changes": [ { "key": "system.bonuses.damage.physical.bonus", - "type": "add", + "mode": 2, "value": "9", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "add", + "mode": 2, "value": "1", "priority": 60 } diff --git a/src/packs/beastforms/beastform_Mythic_Hybrid_WAbxCf2An8qmxyJ1.json b/src/packs/beastforms/beastform_Mythic_Hybrid_WAbxCf2An8qmxyJ1.json index 691d9972..fa35eaac 100644 --- a/src/packs/beastforms/beastform_Mythic_Hybrid_WAbxCf2An8qmxyJ1.json +++ b/src/packs/beastforms/beastform_Mythic_Hybrid_WAbxCf2An8qmxyJ1.json @@ -49,31 +49,31 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "4", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "10", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "strength", "priority": null } diff --git a/src/packs/beastforms/beastform_Nimble_Grazer_CItO8yX6amQaqyk7.json b/src/packs/beastforms/beastform_Nimble_Grazer_CItO8yX6amQaqyk7.json index 30523e41..183ad150 100644 --- a/src/packs/beastforms/beastform_Nimble_Grazer_CItO8yX6amQaqyk7.json +++ b/src/packs/beastforms/beastform_Nimble_Grazer_CItO8yX6amQaqyk7.json @@ -62,25 +62,25 @@ "changes": [ { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "1", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "agility", "priority": null } diff --git a/src/packs/beastforms/beastform_Pack_Predator_YLisKYYhAGca50WM.json b/src/packs/beastforms/beastform_Pack_Predator_YLisKYYhAGca50WM.json index 82a0dded..834493bb 100644 --- a/src/packs/beastforms/beastform_Pack_Predator_YLisKYYhAGca50WM.json +++ b/src/packs/beastforms/beastform_Pack_Predator_YLisKYYhAGca50WM.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "2", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "strength", "priority": null } diff --git a/src/packs/beastforms/beastform_Pouncing_Predator_33oFSZ1PwFqInHPe.json b/src/packs/beastforms/beastform_Pouncing_Predator_33oFSZ1PwFqInHPe.json index f058d649..d172d8f3 100644 --- a/src/packs/beastforms/beastform_Pouncing_Predator_33oFSZ1PwFqInHPe.json +++ b/src/packs/beastforms/beastform_Pouncing_Predator_33oFSZ1PwFqInHPe.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.instinct.value", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "6", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "instinct", "priority": null } diff --git a/src/packs/beastforms/beastform_Powerful_Beast_m8BVTuJI1wCvzTcf.json b/src/packs/beastforms/beastform_Powerful_Beast_m8BVTuJI1wCvzTcf.json index 6ad91eed..7fa832e6 100644 --- a/src/packs/beastforms/beastform_Powerful_Beast_m8BVTuJI1wCvzTcf.json +++ b/src/packs/beastforms/beastform_Powerful_Beast_m8BVTuJI1wCvzTcf.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "4", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "strength", "priority": null } diff --git a/src/packs/beastforms/beastform_Stalking_Arachnid_A4TVRY0D5r9EiVwA.json b/src/packs/beastforms/beastform_Stalking_Arachnid_A4TVRY0D5r9EiVwA.json index cf6f49f2..16520a9c 100644 --- a/src/packs/beastforms/beastform_Stalking_Arachnid_A4TVRY0D5r9EiVwA.json +++ b/src/packs/beastforms/beastform_Stalking_Arachnid_A4TVRY0D5r9EiVwA.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "1", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "1", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "finesse", "priority": null } diff --git a/src/packs/beastforms/beastform_Striking_Serpent_1XrZWGDttBAAUxR1.json b/src/packs/beastforms/beastform_Striking_Serpent_1XrZWGDttBAAUxR1.json index 16111887..f78500c9 100644 --- a/src/packs/beastforms/beastform_Striking_Serpent_1XrZWGDttBAAUxR1.json +++ b/src/packs/beastforms/beastform_Striking_Serpent_1XrZWGDttBAAUxR1.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "4", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "finesse", "priority": null } diff --git a/src/packs/beastforms/beastform_Terrible_Lizard_5BABxRe2XVrYTj8N.json b/src/packs/beastforms/beastform_Terrible_Lizard_5BABxRe2XVrYTj8N.json index e9993526..49818b74 100644 --- a/src/packs/beastforms/beastform_Terrible_Lizard_5BABxRe2XVrYTj8N.json +++ b/src/packs/beastforms/beastform_Terrible_Lizard_5BABxRe2XVrYTj8N.json @@ -65,31 +65,31 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "4", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "10", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "strength", "priority": null } diff --git a/src/packs/beastforms/beastform_Winged_Beast_mZ4Wlqtss2FlNNvL.json b/src/packs/beastforms/beastform_Winged_Beast_mZ4Wlqtss2FlNNvL.json index ccb67283..4ca44471 100644 --- a/src/packs/beastforms/beastform_Winged_Beast_mZ4Wlqtss2FlNNvL.json +++ b/src/packs/beastforms/beastform_Winged_Beast_mZ4Wlqtss2FlNNvL.json @@ -62,31 +62,31 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.rules.attack.damage.diceIndex", - "type": "override", + "mode": 5, "value": "0", "priority": null }, { "key": "system.rules.attack.damage.bonus", - "type": "override", + "mode": 5, "value": "2", "priority": null }, { "key": "system.rules.attack.roll.trait", - "type": "override", + "mode": 5, "value": "finesse", "priority": null } diff --git a/src/packs/beastforms/feature_Armored_Shell_nDQZdIF2epKlhauX.json b/src/packs/beastforms/feature_Armored_Shell_nDQZdIF2epKlhauX.json index 395a1d7d..7aaefef8 100644 --- a/src/packs/beastforms/feature_Armored_Shell_nDQZdIF2epKlhauX.json +++ b/src/packs/beastforms/feature_Armored_Shell_nDQZdIF2epKlhauX.json @@ -60,7 +60,7 @@ "changes": [ { "key": "system.resistance.physical.resistance", - "type": "override", + "mode": 5, "value": "1", "priority": null } @@ -98,7 +98,7 @@ "changes": [ { "key": "system.resistance.physical.reduction", - "type": "add", + "mode": 2, "value": "@system.armorScore", "priority": 21 } diff --git a/src/packs/beastforms/feature_Hollow_Bones_xVgmXhj2YgeqS1KK.json b/src/packs/beastforms/feature_Hollow_Bones_xVgmXhj2YgeqS1KK.json index 23b2317f..d047a501 100644 --- a/src/packs/beastforms/feature_Hollow_Bones_xVgmXhj2YgeqS1KK.json +++ b/src/packs/beastforms/feature_Hollow_Bones_xVgmXhj2YgeqS1KK.json @@ -25,13 +25,13 @@ "changes": [ { "key": "system.damageThresholds.major", - "type": "add", + "mode": 2, "value": "-2", "priority": null }, { "key": "system.damageThresholds.severe", - "type": "add", + "mode": 2, "value": "-2", "priority": null } diff --git a/src/packs/beastforms/feature_Physical_Defense_StabkQ3BzWRZa8Tz.json b/src/packs/beastforms/feature_Physical_Defense_StabkQ3BzWRZa8Tz.json index 6edc64da..f4c86b8c 100644 --- a/src/packs/beastforms/feature_Physical_Defense_StabkQ3BzWRZa8Tz.json +++ b/src/packs/beastforms/feature_Physical_Defense_StabkQ3BzWRZa8Tz.json @@ -25,13 +25,13 @@ "changes": [ { "key": "system.damageThresholds.major", - "type": "add", + "mode": 2, "value": "3", "priority": null }, { "key": "system.damageThresholds.severe", - "type": "add", + "mode": 2, "value": "3", "priority": null } diff --git a/src/packs/beastforms/feature_Rampage_8upqfcZvi7b5hRLE.json b/src/packs/beastforms/feature_Rampage_8upqfcZvi7b5hRLE.json index 8c86458b..ecc46058 100644 --- a/src/packs/beastforms/feature_Rampage_8upqfcZvi7b5hRLE.json +++ b/src/packs/beastforms/feature_Rampage_8upqfcZvi7b5hRLE.json @@ -59,15 +59,21 @@ "_id": "A7l4JEBC1FFQajsN", "type": "base", "system": { - "changes": [ - { - "key": "system.proficiency", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.proficiency", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/beastforms/feature_Takedown_0ey4kM9ssj2otHvb.json b/src/packs/beastforms/feature_Takedown_0ey4kM9ssj2otHvb.json index 591f4857..531b30ea 100644 --- a/src/packs/beastforms/feature_Takedown_0ey4kM9ssj2otHvb.json +++ b/src/packs/beastforms/feature_Takedown_0ey4kM9ssj2otHvb.json @@ -108,7 +108,7 @@ "changes": [ { "key": "system.proficiency", - "type": "add", + "mode": 2, "value": "2", "priority": null } diff --git a/src/packs/beastforms/feature_Thick_Hide_ZYbdXaWVj2zdcmaK.json b/src/packs/beastforms/feature_Thick_Hide_ZYbdXaWVj2zdcmaK.json index 932749bf..6eba9342 100644 --- a/src/packs/beastforms/feature_Thick_Hide_ZYbdXaWVj2zdcmaK.json +++ b/src/packs/beastforms/feature_Thick_Hide_ZYbdXaWVj2zdcmaK.json @@ -25,13 +25,13 @@ "changes": [ { "key": "system.damageThresholds.major", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.damageThresholds.severe", - "type": "add", + "mode": 2, "value": "2", "priority": null } diff --git a/src/packs/beastforms/feature_Undaunted_ODudjX88Te4vDP57.json b/src/packs/beastforms/feature_Undaunted_ODudjX88Te4vDP57.json index d13c8a1c..092efe51 100644 --- a/src/packs/beastforms/feature_Undaunted_ODudjX88Te4vDP57.json +++ b/src/packs/beastforms/feature_Undaunted_ODudjX88Te4vDP57.json @@ -25,13 +25,13 @@ "changes": [ { "key": "system.damageThresholds.major", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.damageThresholds.severe", - "type": "add", + "mode": 2, "value": "2", "priority": null } diff --git a/src/packs/beastforms/feature_Vicious_Maul_jYUBi7yLHap5ljpa.json b/src/packs/beastforms/feature_Vicious_Maul_jYUBi7yLHap5ljpa.json index f9ec4933..a3494ed0 100644 --- a/src/packs/beastforms/feature_Vicious_Maul_jYUBi7yLHap5ljpa.json +++ b/src/packs/beastforms/feature_Vicious_Maul_jYUBi7yLHap5ljpa.json @@ -10,7 +10,7 @@ "type": "damage", "_id": "Cc53vyYz5ggKdIbx", "systemPath": "actions", - "description": "", + "description": "When you succeed on an attack against a target within Melee range, you can spend a Hope to clamp that opponent in your jaws, making them temporarily Restrained and Vulnerable.", "chatDisplay": true, "actionType": "action", "cost": [ @@ -23,7 +23,7 @@ ], "uses": { "value": null, - "max": "", + "max": null, "recovery": null }, "damage": { diff --git a/src/packs/classes/feature_Combat_Training_eoSmuAJmgHUyULtp.json b/src/packs/classes/feature_Combat_Training_eoSmuAJmgHUyULtp.json index 34f242ed..d28f360c 100644 --- a/src/packs/classes/feature_Combat_Training_eoSmuAJmgHUyULtp.json +++ b/src/packs/classes/feature_Combat_Training_eoSmuAJmgHUyULtp.json @@ -21,23 +21,29 @@ "name": "Combat Training", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "@system.levelData.level.current", - "priority": null - }, - { - "key": "system.rules.burden.ignore", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "Y7sTM0tw0VpgU6pC", "img": "icons/skills/melee/spear-tips-quintuple-orange.webp", + "changes": [ + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "@system.levelData.level.current", + "priority": null + }, + { + "key": "system.rules.burden.ignore", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/classes/feature_Make_a_Scene_N9E5skDDK2VgvohR.json b/src/packs/classes/feature_Make_a_Scene_N9E5skDDK2VgvohR.json index 3ae763da..5f28c048 100644 --- a/src/packs/classes/feature_Make_a_Scene_N9E5skDDK2VgvohR.json +++ b/src/packs/classes/feature_Make_a_Scene_N9E5skDDK2VgvohR.json @@ -59,6 +59,12 @@ "_id": "8G9zDv1gac6dEHmS", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.difficulty", diff --git a/src/packs/classes/feature_No_Mercy_njj2C3tMDeCHHOoh.json b/src/packs/classes/feature_No_Mercy_njj2C3tMDeCHHOoh.json index 184085bf..5b770e5d 100644 --- a/src/packs/classes/feature_No_Mercy_njj2C3tMDeCHHOoh.json +++ b/src/packs/classes/feature_No_Mercy_njj2C3tMDeCHHOoh.json @@ -62,6 +62,12 @@ "_id": "XK4cCcz9sRGDJr0q", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.bonuses.roll.attack.bonus", diff --git a/src/packs/classes/feature_Rally_PydiMnNCKpd44SGS.json b/src/packs/classes/feature_Rally_PydiMnNCKpd44SGS.json index 9ecb926b..e2a0b5bb 100644 --- a/src/packs/classes/feature_Rally_PydiMnNCKpd44SGS.json +++ b/src/packs/classes/feature_Rally_PydiMnNCKpd44SGS.json @@ -52,15 +52,21 @@ "_id": "FrSJH9vzDHkFGYQL", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.rally", - "type": "add", - "value": "6 + min((floor(@system.levelData.level.current / 5)*2), 2)", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.rally", + "mode": 2, + "value": "6 + min((floor(@system.levelData.level.current / 5)*2), 2)", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/classes/feature_Ranger_s_Focus_ncLx2P8BOUtrAD38.json b/src/packs/classes/feature_Ranger_s_Focus_ncLx2P8BOUtrAD38.json index b82954a5..b744c4c5 100644 --- a/src/packs/classes/feature_Ranger_s_Focus_ncLx2P8BOUtrAD38.json +++ b/src/packs/classes/feature_Ranger_s_Focus_ncLx2P8BOUtrAD38.json @@ -60,8 +60,14 @@ "_id": "SXi2dQWqpwY9fap4", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/classes/feature_Rogue_s_Dodge_hVaaPIjxoextIgSL.json b/src/packs/classes/feature_Rogue_s_Dodge_hVaaPIjxoextIgSL.json index 4a7e0cac..b886b079 100644 --- a/src/packs/classes/feature_Rogue_s_Dodge_hVaaPIjxoextIgSL.json +++ b/src/packs/classes/feature_Rogue_s_Dodge_hVaaPIjxoextIgSL.json @@ -60,6 +60,12 @@ "_id": "hhVjBro2osGDTT5g", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + }, "changes": [ { "key": "system.evasion", diff --git a/src/packs/classes/feature_Sneak_Attack_5QqpEwmwkPfZHpMW.json b/src/packs/classes/feature_Sneak_Attack_5QqpEwmwkPfZHpMW.json index 83db7d06..505a96cb 100644 --- a/src/packs/classes/feature_Sneak_Attack_5QqpEwmwkPfZHpMW.json +++ b/src/packs/classes/feature_Sneak_Attack_5QqpEwmwkPfZHpMW.json @@ -25,21 +25,27 @@ "_id": "380jFzw756qSy5ae", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.dice", - "type": "add", - "value": "@tierd6", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.dice", - "type": "add", - "value": "@tierd6", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.dice", + "mode": 2, + "value": "@tierd6", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.dice", + "mode": 2, + "value": "@tierd6", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/classes/feature_Unstoppable_PnD2UCgzIlwX6cY3.json b/src/packs/classes/feature_Unstoppable_PnD2UCgzIlwX6cY3.json index 5477f2c4..9c9ecf61 100644 --- a/src/packs/classes/feature_Unstoppable_PnD2UCgzIlwX6cY3.json +++ b/src/packs/classes/feature_Unstoppable_PnD2UCgzIlwX6cY3.json @@ -62,39 +62,45 @@ "_id": "xzQtFSuDS48kUdAZ", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "ORIGIN.@item.resource.value", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "ORIGIN.@item.resource.value", - "priority": null - }, - { - "key": "system.rules.damageReduction.reduceSeverity.physical", - "type": "add", - "value": "1", - "priority": null - }, - { - "key": "system.rules.conditionImmunities.vulnerable", - "type": "override", - "value": "1", - "priority": null - }, - { - "key": "system.rules.conditionImmunities.restrained", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "ORIGIN.@item.resource.value", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "ORIGIN.@item.resource.value", + "priority": null + }, + { + "key": "system.rules.damageReduction.reduceSeverity.physical", + "mode": 2, + "value": "1", + "priority": null + }, + { + "key": "system.rules.conditionImmunities.vulnerable", + "mode": 5, + "value": "1", + "priority": null + }, + { + "key": "system.rules.conditionImmunities.restrained", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/communities/feature_Lightfoot_TQ1AIQjndC4mYmmU.json b/src/packs/communities/feature_Lightfoot_TQ1AIQjndC4mYmmU.json index 84134bbb..a18b4689 100644 --- a/src/packs/communities/feature_Lightfoot_TQ1AIQjndC4mYmmU.json +++ b/src/packs/communities/feature_Lightfoot_TQ1AIQjndC4mYmmU.json @@ -24,15 +24,21 @@ "_id": "4my9X5XC3uwDSx7B", "img": "icons/magic/control/debuff-energy-snare-blue.webp", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Move without being heard.", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Move without being heard.", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/communities/feature_Low_Light_Living_aMla3xQuCHEwORGD.json b/src/packs/communities/feature_Low_Light_Living_aMla3xQuCHEwORGD.json index b02ef4d6..c95d9132 100644 --- a/src/packs/communities/feature_Low_Light_Living_aMla3xQuCHEwORGD.json +++ b/src/packs/communities/feature_Low_Light_Living_aMla3xQuCHEwORGD.json @@ -24,6 +24,12 @@ "_id": "pCp32u7UwqxCI4WW", "img": "icons/environment/settlement/temple-night.webp", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.advantageSources", diff --git a/src/packs/communities/feature_Privilege_C7NR6qRatawZusmg.json b/src/packs/communities/feature_Privilege_C7NR6qRatawZusmg.json index 85ef1ec3..171f4d50 100644 --- a/src/packs/communities/feature_Privilege_C7NR6qRatawZusmg.json +++ b/src/packs/communities/feature_Privilege_C7NR6qRatawZusmg.json @@ -24,27 +24,33 @@ "_id": "xgtjykfgvg142urA", "img": "icons/commodities/currency/coins-plain-stack-gold.webp", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Consort with nobles", - "priority": null - }, - { - "key": "system.advantageSources", - "type": "add", - "value": "Negotiate prices", - "priority": null - }, - { - "key": "system.advantageSources", - "type": "add", - "value": "Leverage your reputation to get what you want", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Consort with nobles", + "priority": null + }, + { + "key": "system.advantageSources", + "mode": 2, + "value": "Negotiate prices", + "priority": null + }, + { + "key": "system.advantageSources", + "mode": 2, + "value": "Leverage your reputation to get what you want", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/communities/feature_Scoundrel_ZmEuBdL0JrvuA8le.json b/src/packs/communities/feature_Scoundrel_ZmEuBdL0JrvuA8le.json index 7f7a34ae..d91a7638 100644 --- a/src/packs/communities/feature_Scoundrel_ZmEuBdL0JrvuA8le.json +++ b/src/packs/communities/feature_Scoundrel_ZmEuBdL0JrvuA8le.json @@ -24,27 +24,33 @@ "_id": "snkYmZ22Q8HHLY9M", "img": "icons/equipment/head/hood-cloth-teal-gold.webp", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Negotiate with criminals", - "priority": null - }, - { - "key": "system.advantageSources", - "type": "add", - "value": "Detect lies", - "priority": null - }, - { - "key": "system.advantageSources", - "type": "add", - "value": "Find a safe place to hide", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Negotiate with criminals", + "priority": null + }, + { + "key": "system.advantageSources", + "mode": 2, + "value": "Detect lies", + "priority": null + }, + { + "key": "system.advantageSources", + "mode": 2, + "value": "Find a safe place to hide", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/communities/feature_Steady_DYmmr5CknLtHnwuj.json b/src/packs/communities/feature_Steady_DYmmr5CknLtHnwuj.json index 292fd773..497854ac 100644 --- a/src/packs/communities/feature_Steady_DYmmr5CknLtHnwuj.json +++ b/src/packs/communities/feature_Steady_DYmmr5CknLtHnwuj.json @@ -24,27 +24,33 @@ "_id": "QDf9LD8Mhd0Cw0CB", "img": "icons/equipment/feet/boots-collared-simple-leather.webp", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Traverse dangerous cliffs and ledges", - "priority": null - }, - { - "key": "system.advantageSources", - "type": "add", - "value": "Navigate harsh environment", - "priority": null - }, - { - "key": "system.advantageSources", - "type": "add", - "value": "Use your survival knowledge", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Traverse dangerous cliffs and ledges", + "priority": null + }, + { + "key": "system.advantageSources", + "mode": 2, + "value": "Navigate harsh environment", + "priority": null + }, + { + "key": "system.advantageSources", + "mode": 2, + "value": "Use your survival knowledge", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/communities/feature_Well_Read_JBZJmywisJg5X3tH.json b/src/packs/communities/feature_Well_Read_JBZJmywisJg5X3tH.json index 28d4c962..dd40b33b 100644 --- a/src/packs/communities/feature_Well_Read_JBZJmywisJg5X3tH.json +++ b/src/packs/communities/feature_Well_Read_JBZJmywisJg5X3tH.json @@ -24,15 +24,21 @@ "_id": "RwhxYOAAKKlYZiz0", "img": "icons/sundries/books/book-open-brown.webp", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "History, culture, or politics of a prominent person or place", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "History, culture, or politics of a prominent person or place", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Arcana_Touched_5PvMQKCjrgSxzstn.json b/src/packs/domains/domainCard_Arcana_Touched_5PvMQKCjrgSxzstn.json index 361558d3..556d5074 100644 --- a/src/packs/domains/domainCard_Arcana_Touched_5PvMQKCjrgSxzstn.json +++ b/src/packs/domains/domainCard_Arcana_Touched_5PvMQKCjrgSxzstn.json @@ -65,17 +65,23 @@ "name": "Arcana-Touched", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.spellcast.bonus", - "type": "add", - "value": "+1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "vTW98Xha0HP8ITrs", "img": "systems/daggerheart/assets/icons/domains/domain-card/arcana.png", + "changes": [ + { + "key": "system.bonuses.roll.spellcast.bonus", + "mode": 2, + "value": "+1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Battle_Cry_Ef1JsUG50LIoKx2F.json b/src/packs/domains/domainCard_Battle_Cry_Ef1JsUG50LIoKx2F.json index 000437b7..1fde286d 100644 --- a/src/packs/domains/domainCard_Battle_Cry_Ef1JsUG50LIoKx2F.json +++ b/src/packs/domains/domainCard_Battle_Cry_Ef1JsUG50LIoKx2F.json @@ -127,6 +127,12 @@ "_id": "s7ma4TNgAvt0ZgEW", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.advantageSources", diff --git a/src/packs/domains/domainCard_Blade_Touched_Gb5bqpFSBiuBxUix.json b/src/packs/domains/domainCard_Blade_Touched_Gb5bqpFSBiuBxUix.json index ba8c56a9..ebb95570 100644 --- a/src/packs/domains/domainCard_Blade_Touched_Gb5bqpFSBiuBxUix.json +++ b/src/packs/domains/domainCard_Blade_Touched_Gb5bqpFSBiuBxUix.json @@ -24,23 +24,29 @@ "name": "Blade-Touched", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.attack.bonus", - "type": "add", - "value": "2", - "priority": null - }, - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "4", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "fBpLkCWGsB8MbymR", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.attack.bonus", + "mode": 2, + "value": "2", + "priority": null + }, + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "4", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Body_Basher_aQz8jKkCd8M9aKMA.json b/src/packs/domains/domainCard_Body_Basher_aQz8jKkCd8M9aKMA.json index fc49b640..f0d4c988 100644 --- a/src/packs/domains/domainCard_Body_Basher_aQz8jKkCd8M9aKMA.json +++ b/src/packs/domains/domainCard_Body_Basher_aQz8jKkCd8M9aKMA.json @@ -31,22 +31,22 @@ "type": "withinRange", "target": "hostile", "range": "melee" - }, - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "@system.traits.strength.value", - "priority": 21 - }, - { - "key": "system.bonuses.damage.secondaryWeapon.bonus", - "type": "add", - "value": "@system.traits.strength.value", - "priority": 21 - } - ] + } }, + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "@system.traits.strength.value", + "priority": 21 + }, + { + "key": "system.bonuses.damage.secondaryWeapon.bonus", + "mode": 2, + "value": "@system.traits.strength.value", + "priority": 21 + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Bold_Presence_tdsL00yTSLNgZWs6.json b/src/packs/domains/domainCard_Bold_Presence_tdsL00yTSLNgZWs6.json index 3d7a26e2..aaf070fc 100644 --- a/src/packs/domains/domainCard_Bold_Presence_tdsL00yTSLNgZWs6.json +++ b/src/packs/domains/domainCard_Bold_Presence_tdsL00yTSLNgZWs6.json @@ -85,15 +85,21 @@ "_id": "2XEYhuAcRGTtqvED", "type": "base", "system": { - "changes": [ - { - "key": "system.traits.presence.value", - "type": "add", - "value": "@system.traits.strength.value", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.traits.presence.value", + "mode": 2, + "value": "@system.traits.strength.value", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Bolt_Beacon_BNevJyGk7hmN7XOY.json b/src/packs/domains/domainCard_Bolt_Beacon_BNevJyGk7hmN7XOY.json index ce01f6b0..df7d36a4 100644 --- a/src/packs/domains/domainCard_Bolt_Beacon_BNevJyGk7hmN7XOY.json +++ b/src/packs/domains/domainCard_Bolt_Beacon_BNevJyGk7hmN7XOY.json @@ -114,6 +114,12 @@ "_id": "veZpnhnF8NRRhKG4", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Bone_Touched_ON5bvnoQBy0SYc9Y.json b/src/packs/domains/domainCard_Bone_Touched_ON5bvnoQBy0SYc9Y.json index 3fc45037..8880bb07 100644 --- a/src/packs/domains/domainCard_Bone_Touched_ON5bvnoQBy0SYc9Y.json +++ b/src/packs/domains/domainCard_Bone_Touched_ON5bvnoQBy0SYc9Y.json @@ -57,17 +57,23 @@ "name": "Bone Touched", "type": "base", "system": { - "changes": [ - { - "key": "system.traits.agility.value", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "P6hYkkI64FqIcMoP", "img": "icons/magic/death/bones-crossed-orange.webp", + "changes": [ + { + "key": "system.traits.agility.value", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Book_of_Ava_YtZzYBtR0yLPPA93.json b/src/packs/domains/domainCard_Book_of_Ava_YtZzYBtR0yLPPA93.json index e218e771..fa247c89 100644 --- a/src/packs/domains/domainCard_Book_of_Ava_YtZzYBtR0yLPPA93.json +++ b/src/packs/domains/domainCard_Book_of_Ava_YtZzYBtR0yLPPA93.json @@ -255,6 +255,12 @@ "_id": "ptYT10JZ2WJHvFMd", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "type": "armor", diff --git a/src/packs/domains/domainCard_Book_of_Illiat_df4iRqQzRntrF6Qw.json b/src/packs/domains/domainCard_Book_of_Illiat_df4iRqQzRntrF6Qw.json index e7b4dd8b..b34fa000 100644 --- a/src/packs/domains/domainCard_Book_of_Illiat_df4iRqQzRntrF6Qw.json +++ b/src/packs/domains/domainCard_Book_of_Illiat_df4iRqQzRntrF6Qw.json @@ -172,6 +172,12 @@ "_id": "zAEaETYSOE2fmcyB", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "shortRest" @@ -212,6 +218,12 @@ "_id": "gfZTHSgwYSDKsePW", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/domains/domainCard_Book_of_Norai_WtwSWXTRZa7QVvmo.json b/src/packs/domains/domainCard_Book_of_Norai_WtwSWXTRZa7QVvmo.json index 31d869be..78028bab 100644 --- a/src/packs/domains/domainCard_Book_of_Norai_WtwSWXTRZa7QVvmo.json +++ b/src/packs/domains/domainCard_Book_of_Norai_WtwSWXTRZa7QVvmo.json @@ -243,6 +243,12 @@ "_id": "iPnT02apql16Zhjf", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Book_of_Ronin_SZMNR3uGNinJcN4N.json b/src/packs/domains/domainCard_Book_of_Ronin_SZMNR3uGNinJcN4N.json index ad01a99a..88bb759d 100644 --- a/src/packs/domains/domainCard_Book_of_Ronin_SZMNR3uGNinJcN4N.json +++ b/src/packs/domains/domainCard_Book_of_Ronin_SZMNR3uGNinJcN4N.json @@ -131,8 +131,14 @@ "_id": "ntQfpTcXyEL76vCK", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, @@ -161,8 +167,14 @@ "_id": "y44r3c91m06WKSiq", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Book_of_Sitil_eq8VNqYMRHhF9xw9.json b/src/packs/domains/domainCard_Book_of_Sitil_eq8VNqYMRHhF9xw9.json index d3fe6b1a..16b7a63b 100644 --- a/src/packs/domains/domainCard_Book_of_Sitil_eq8VNqYMRHhF9xw9.json +++ b/src/packs/domains/domainCard_Book_of_Sitil_eq8VNqYMRHhF9xw9.json @@ -136,8 +136,14 @@ "_id": "klUaU5KeQCu7KCBI", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, @@ -166,8 +172,14 @@ "_id": "wnrHSvvB6pydTVcC", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Book_of_Vyola_VOIgm2j2Ijszwc5m.json b/src/packs/domains/domainCard_Book_of_Vyola_VOIgm2j2Ijszwc5m.json index e36936f5..522a8f7c 100644 --- a/src/packs/domains/domainCard_Book_of_Vyola_VOIgm2j2Ijszwc5m.json +++ b/src/packs/domains/domainCard_Book_of_Vyola_VOIgm2j2Ijszwc5m.json @@ -109,8 +109,14 @@ "_id": "6PPapwuwgKy23oHg", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Book_of_Yarrow_J1ovx2FpNDvPq1o6.json b/src/packs/domains/domainCard_Book_of_Yarrow_J1ovx2FpNDvPq1o6.json index 4bcdc349..45fbc77f 100644 --- a/src/packs/domains/domainCard_Book_of_Yarrow_J1ovx2FpNDvPq1o6.json +++ b/src/packs/domains/domainCard_Book_of_Yarrow_J1ovx2FpNDvPq1o6.json @@ -118,6 +118,12 @@ "_id": "HWJYhSegVLeAa3dE", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.resistance.magical.immunity", diff --git a/src/packs/domains/domainCard_Brace_QXs4vssSqNGQu5b8.json b/src/packs/domains/domainCard_Brace_QXs4vssSqNGQu5b8.json index 321de80a..bc2e59e5 100644 --- a/src/packs/domains/domainCard_Brace_QXs4vssSqNGQu5b8.json +++ b/src/packs/domains/domainCard_Brace_QXs4vssSqNGQu5b8.json @@ -23,17 +23,23 @@ "name": "Brace", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.damageReduction.maxArmorMarked.stressExtra", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "xSjqLOHfi5lImDHS", "img": "icons/magic/defensive/shield-barrier-blue.webp", + "changes": [ + { + "key": "system.rules.damageReduction.maxArmorMarked.stressExtra", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Breaking_Blow_8UANBgSdhMZ0sqfO.json b/src/packs/domains/domainCard_Breaking_Blow_8UANBgSdhMZ0sqfO.json index 1e11b8a9..24b3d661 100644 --- a/src/packs/domains/domainCard_Breaking_Blow_8UANBgSdhMZ0sqfO.json +++ b/src/packs/domains/domainCard_Breaking_Blow_8UANBgSdhMZ0sqfO.json @@ -65,8 +65,14 @@ "_id": "ETIeXRAib3DFBHpX", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Chokehold_R5GYUalYXLLFRlNl.json b/src/packs/domains/domainCard_Chokehold_R5GYUalYXLLFRlNl.json index b9d576e3..73424902 100644 --- a/src/packs/domains/domainCard_Chokehold_R5GYUalYXLLFRlNl.json +++ b/src/packs/domains/domainCard_Chokehold_R5GYUalYXLLFRlNl.json @@ -96,8 +96,14 @@ "_id": "yzGem7IfViJdAv1H", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Cinder_Grasp_5EP2Lgf7ojfrc0Is.json b/src/packs/domains/domainCard_Cinder_Grasp_5EP2Lgf7ojfrc0Is.json index 384e4834..e3df986e 100644 --- a/src/packs/domains/domainCard_Cinder_Grasp_5EP2Lgf7ojfrc0Is.json +++ b/src/packs/domains/domainCard_Cinder_Grasp_5EP2Lgf7ojfrc0Is.json @@ -162,6 +162,12 @@ "_id": "HNKkaWi507whJuYN", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Cloaking_Blast_Zhw7PtK8nMPlsOqD.json b/src/packs/domains/domainCard_Cloaking_Blast_Zhw7PtK8nMPlsOqD.json index 143e7e17..a2a06889 100644 --- a/src/packs/domains/domainCard_Cloaking_Blast_Zhw7PtK8nMPlsOqD.json +++ b/src/packs/domains/domainCard_Cloaking_Blast_Zhw7PtK8nMPlsOqD.json @@ -65,6 +65,12 @@ "_id": "twCBqXytmRkMz0kV", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/domains/domainCard_Codex_Touched_7Pu83ABdMukTxu3e.json b/src/packs/domains/domainCard_Codex_Touched_7Pu83ABdMukTxu3e.json index 3eb4da35..6443ed6a 100644 --- a/src/packs/domains/domainCard_Codex_Touched_7Pu83ABdMukTxu3e.json +++ b/src/packs/domains/domainCard_Codex_Touched_7Pu83ABdMukTxu3e.json @@ -86,15 +86,21 @@ "_id": "oWs00mBY3onxGjF9", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.spellcast.bonus", - "type": "add", - "value": "@system.proficiency", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.roll.spellcast.bonus", + "mode": 2, + "value": "@system.proficiency", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Conjure_Swarm_rZPH0BY8Sznc9sFG.json b/src/packs/domains/domainCard_Conjure_Swarm_rZPH0BY8Sznc9sFG.json index 7b0b7fb8..d9e8da6d 100644 --- a/src/packs/domains/domainCard_Conjure_Swarm_rZPH0BY8Sznc9sFG.json +++ b/src/packs/domains/domainCard_Conjure_Swarm_rZPH0BY8Sznc9sFG.json @@ -208,6 +208,12 @@ "_id": "dImnF8ZT2rVybiIP", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.rules.damageReduction.reduceSeverity.magical", diff --git a/src/packs/domains/domainCard_Conjured_Steeds_Jkp6cMDiHHaBZQRS.json b/src/packs/domains/domainCard_Conjured_Steeds_Jkp6cMDiHHaBZQRS.json index 0b581925..31ad8612 100644 --- a/src/packs/domains/domainCard_Conjured_Steeds_Jkp6cMDiHHaBZQRS.json +++ b/src/packs/domains/domainCard_Conjured_Steeds_Jkp6cMDiHHaBZQRS.json @@ -63,27 +63,33 @@ "_id": "cNSlGBGPKKBNnlH8", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.attack.bonus", - "type": "add", - "value": "-2", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.dice", - "type": "add", - "value": "+2", - "priority": null - }, - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "+2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.roll.attack.bonus", + "mode": 2, + "value": "-2", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.dice", + "mode": 2, + "value": "+2", + "priority": null + }, + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "+2", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Corrosive_Projectile_qJaSNTuDfbPVr8Lb.json b/src/packs/domains/domainCard_Corrosive_Projectile_qJaSNTuDfbPVr8Lb.json index 203e4d06..6a039bbf 100644 --- a/src/packs/domains/domainCard_Corrosive_Projectile_qJaSNTuDfbPVr8Lb.json +++ b/src/packs/domains/domainCard_Corrosive_Projectile_qJaSNTuDfbPVr8Lb.json @@ -134,6 +134,12 @@ "_id": "zB95bjSSdVlApQnR", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.difficulty", diff --git a/src/packs/domains/domainCard_Cruel_Precision_bap1eCWryPNowbyo.json b/src/packs/domains/domainCard_Cruel_Precision_bap1eCWryPNowbyo.json index fbe1d7c7..9e5c414e 100644 --- a/src/packs/domains/domainCard_Cruel_Precision_bap1eCWryPNowbyo.json +++ b/src/packs/domains/domainCard_Cruel_Precision_bap1eCWryPNowbyo.json @@ -23,23 +23,29 @@ "name": "Cruel Precision (Agi)", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "@system.traits.agility.value", - "priority": 21 - }, - { - "key": "system.bonuses.damage.secondaryWeapon.bonus", - "type": "add", - "value": "@system.traits.agility.value", - "priority": 21 - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "t5D10AL2W9LMGsX4", "img": "icons/skills/melee/strike-dagger-arcane-pink.webp", + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "@system.traits.agility.value", + "priority": 21 + }, + { + "key": "system.bonuses.damage.secondaryWeapon.bonus", + "mode": 2, + "value": "@system.traits.agility.value", + "priority": 21 + } + ], "disabled": true, "duration": { "startTime": null, @@ -66,23 +72,29 @@ "name": "Cruel Precision (Fin)", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "@system.traits.finesse.value", - "priority": null - }, - { - "key": "system.bonuses.damage.secondaryWeapon.bonus", - "type": "add", - "value": "@system.traits.finesse.value", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "Ha7c4XgmN5zGMSHG", "img": "icons/skills/melee/strike-dagger-arcane-pink.webp", + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "@system.traits.finesse.value", + "priority": null + }, + { + "key": "system.bonuses.damage.secondaryWeapon.bonus", + "mode": 2, + "value": "@system.traits.finesse.value", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Deadly_Focus_xxZOXC4tiZQ6kg1e.json b/src/packs/domains/domainCard_Deadly_Focus_xxZOXC4tiZQ6kg1e.json index e794241f..c559dfd9 100644 --- a/src/packs/domains/domainCard_Deadly_Focus_xxZOXC4tiZQ6kg1e.json +++ b/src/packs/domains/domainCard_Deadly_Focus_xxZOXC4tiZQ6kg1e.json @@ -57,15 +57,21 @@ "_id": "TFWiAUDCfGaax5MU", "type": "base", "system": { - "changes": [ - { - "key": "system.proficiency", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.proficiency", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Death_Grip_x0FVGE1YbfXalJiw.json b/src/packs/domains/domainCard_Death_Grip_x0FVGE1YbfXalJiw.json index a2aa67fd..d33b6bab 100644 --- a/src/packs/domains/domainCard_Death_Grip_x0FVGE1YbfXalJiw.json +++ b/src/packs/domains/domainCard_Death_Grip_x0FVGE1YbfXalJiw.json @@ -244,6 +244,12 @@ "_id": "wMXCIQxqLS9IbsEK", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [] }, "disabled": false, @@ -276,6 +282,12 @@ "_id": "bZ0xgZ6TT2099OYp", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [] }, "disabled": false, @@ -308,6 +320,12 @@ "_id": "Oe95zWWY41nH8y5l", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [] }, "disabled": false, diff --git a/src/packs/domains/domainCard_Deft_Deceiver_38znCh6kHTkaPwYi.json b/src/packs/domains/domainCard_Deft_Deceiver_38znCh6kHTkaPwYi.json index f8696f52..dd9c82a2 100644 --- a/src/packs/domains/domainCard_Deft_Deceiver_38znCh6kHTkaPwYi.json +++ b/src/packs/domains/domainCard_Deft_Deceiver_38znCh6kHTkaPwYi.json @@ -63,15 +63,21 @@ "_id": "qtHDKXJ1pH8Cu7by", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Deceive or trick someone into believing a lie you told them", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Deceive or trick someone into believing a lie you told them", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Deft_Maneuvers_dc4rAXlv95srZUct.json b/src/packs/domains/domainCard_Deft_Maneuvers_dc4rAXlv95srZUct.json index 671d1233..2b63b534 100644 --- a/src/packs/domains/domainCard_Deft_Maneuvers_dc4rAXlv95srZUct.json +++ b/src/packs/domains/domainCard_Deft_Maneuvers_dc4rAXlv95srZUct.json @@ -65,15 +65,21 @@ "_id": "gEDGcbsgWY2D2nOo", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.attack.bonus", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.roll.attack.bonus", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Earthquake_C0qLOwSSvZ6PG3Ws.json b/src/packs/domains/domainCard_Earthquake_C0qLOwSSvZ6PG3Ws.json index 801278a6..0a35c95f 100644 --- a/src/packs/domains/domainCard_Earthquake_C0qLOwSSvZ6PG3Ws.json +++ b/src/packs/domains/domainCard_Earthquake_C0qLOwSSvZ6PG3Ws.json @@ -118,6 +118,12 @@ "_id": "Z31XqmGUKWYcZdMY", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Eclipse_62Sj67PdPFzwWVe3.json b/src/packs/domains/domainCard_Eclipse_62Sj67PdPFzwWVe3.json index 8db164a7..e2afaf66 100644 --- a/src/packs/domains/domainCard_Eclipse_62Sj67PdPFzwWVe3.json +++ b/src/packs/domains/domainCard_Eclipse_62Sj67PdPFzwWVe3.json @@ -142,6 +142,12 @@ "_id": "ARMcw2FtKfaYr902", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.disadvantageSources", diff --git a/src/packs/domains/domainCard_Enrapture_a8lFiKX1o8T924ze.json b/src/packs/domains/domainCard_Enrapture_a8lFiKX1o8T924ze.json index 5ea36d31..284682fa 100644 --- a/src/packs/domains/domainCard_Enrapture_a8lFiKX1o8T924ze.json +++ b/src/packs/domains/domainCard_Enrapture_a8lFiKX1o8T924ze.json @@ -139,6 +139,12 @@ "_id": "EYG5dLImk6GkmfRd", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Flight_54GUjNuBEy7xdzMz.json b/src/packs/domains/domainCard_Flight_54GUjNuBEy7xdzMz.json index 91b4b172..4d1355ee 100644 --- a/src/packs/domains/domainCard_Flight_54GUjNuBEy7xdzMz.json +++ b/src/packs/domains/domainCard_Flight_54GUjNuBEy7xdzMz.json @@ -119,8 +119,14 @@ "_id": "gd8crfrvMGWXLWGP", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Floating_Eye_wOQLu7nLMQ7v6Ogw.json b/src/packs/domains/domainCard_Floating_Eye_wOQLu7nLMQ7v6Ogw.json index c82adcdb..97e94563 100644 --- a/src/packs/domains/domainCard_Floating_Eye_wOQLu7nLMQ7v6Ogw.json +++ b/src/packs/domains/domainCard_Floating_Eye_wOQLu7nLMQ7v6Ogw.json @@ -57,8 +57,14 @@ "_id": "ahKlKAc9TuGgx9Zm", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Forager_06UapZuaA5S6fAKl.json b/src/packs/domains/domainCard_Forager_06UapZuaA5S6fAKl.json index 00786add..e8919d6b 100644 --- a/src/packs/domains/domainCard_Forager_06UapZuaA5S6fAKl.json +++ b/src/packs/domains/domainCard_Forager_06UapZuaA5S6fAKl.json @@ -257,15 +257,21 @@ "_id": "cTf5gEem5Gt4fLS4", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.spellcast.bonus", - "type": "add", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.roll.spellcast.bonus", + "mode": 2, + "value": "2", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Force_of_Nature_LzVpMkD5I4QeaIHf.json b/src/packs/domains/domainCard_Force_of_Nature_LzVpMkD5I4QeaIHf.json index 913de9e0..331d19b5 100644 --- a/src/packs/domains/domainCard_Force_of_Nature_LzVpMkD5I4QeaIHf.json +++ b/src/packs/domains/domainCard_Force_of_Nature_LzVpMkD5I4QeaIHf.json @@ -92,27 +92,33 @@ "_id": "ptBC882plZW39Ld9", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "10", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "10", - "priority": null - }, - { - "key": "system.rules.conditionImmunities.restrained", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "10", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "10", + "priority": null + }, + { + "key": "system.rules.conditionImmunities.restrained", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Forceful_Push_z8FFPhDh2SdFkFfS.json b/src/packs/domains/domainCard_Forceful_Push_z8FFPhDh2SdFkFfS.json index 8fc09c1c..3d17ab5d 100644 --- a/src/packs/domains/domainCard_Forceful_Push_z8FFPhDh2SdFkFfS.json +++ b/src/packs/domains/domainCard_Forceful_Push_z8FFPhDh2SdFkFfS.json @@ -64,6 +64,12 @@ "_id": "95oX6QYPySdyyh2v", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Forest_Sprites_JrkUMTzaFmQNBHVm.json b/src/packs/domains/domainCard_Forest_Sprites_JrkUMTzaFmQNBHVm.json index 164b3a71..4fa469a6 100644 --- a/src/packs/domains/domainCard_Forest_Sprites_JrkUMTzaFmQNBHVm.json +++ b/src/packs/domains/domainCard_Forest_Sprites_JrkUMTzaFmQNBHVm.json @@ -88,15 +88,21 @@ "_id": "SuiUFAPyB37Qr6sO", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.attack.bonus", - "type": "add", - "value": "+3", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.roll.attack.bonus", + "mode": 2, + "value": "+3", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Fortified_Armor_oVa49lI107eZILZr.json b/src/packs/domains/domainCard_Fortified_Armor_oVa49lI107eZILZr.json index 90ed8d89..e755bf8d 100644 --- a/src/packs/domains/domainCard_Fortified_Armor_oVa49lI107eZILZr.json +++ b/src/packs/domains/domainCard_Fortified_Armor_oVa49lI107eZILZr.json @@ -23,23 +23,29 @@ "name": "Fortified Armor", "type": "base", "system": { - "changes": [ - { - "key": "system.damageThresholds.major", - "type": "add", - "value": "2", - "priority": null - }, - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "jx8KWAdyoPV2hV0s", "img": "icons/equipment/chest/breastplate-helmet-metal.webp", + "changes": [ + { + "key": "system.damageThresholds.major", + "mode": 2, + "value": "2", + "priority": null + }, + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "2", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Frenzy_MMl7abdGRLl7TJLO.json b/src/packs/domains/domainCard_Frenzy_MMl7abdGRLl7TJLO.json index 022cc65f..6666bc28 100644 --- a/src/packs/domains/domainCard_Frenzy_MMl7abdGRLl7TJLO.json +++ b/src/packs/domains/domainCard_Frenzy_MMl7abdGRLl7TJLO.json @@ -57,6 +57,12 @@ "_id": "1POoAgObPOWDpUco", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.bonuses.damage.physical.bonus", diff --git a/src/packs/domains/domainCard_Full_Surge_SgvjJfMyubZowPxS.json b/src/packs/domains/domainCard_Full_Surge_SgvjJfMyubZowPxS.json index 37087001..fb0bd16d 100644 --- a/src/packs/domains/domainCard_Full_Surge_SgvjJfMyubZowPxS.json +++ b/src/packs/domains/domainCard_Full_Surge_SgvjJfMyubZowPxS.json @@ -63,6 +63,12 @@ "_id": "H5q5iYImr69TfZcp", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.traits.strength.value", diff --git a/src/packs/domains/domainCard_Get_Back_Up_BFWN2cObMdlk9uVz.json b/src/packs/domains/domainCard_Get_Back_Up_BFWN2cObMdlk9uVz.json index fde3f546..571a3fb4 100644 --- a/src/packs/domains/domainCard_Get_Back_Up_BFWN2cObMdlk9uVz.json +++ b/src/packs/domains/domainCard_Get_Back_Up_BFWN2cObMdlk9uVz.json @@ -24,17 +24,23 @@ "name": "Get Back Up", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.damageReduction.stressDamageReduction.severe.cost", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "aV3KUHtXXR86PRMh", "img": "icons/magic/control/silhouette-aura-energy.webp", + "changes": [ + { + "key": "system.rules.damageReduction.stressDamageReduction.severe.cost", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Gifted_Tracker_VZ2b4zfRzV73XTuT.json b/src/packs/domains/domainCard_Gifted_Tracker_VZ2b4zfRzV73XTuT.json index ad1c1580..61d90f0c 100644 --- a/src/packs/domains/domainCard_Gifted_Tracker_VZ2b4zfRzV73XTuT.json +++ b/src/packs/domains/domainCard_Gifted_Tracker_VZ2b4zfRzV73XTuT.json @@ -63,15 +63,21 @@ "_id": "47Oh2weCdmuvKHM9", "type": "base", "system": { - "changes": [ - { - "key": "system.evasion", - "type": "add", - "value": "+1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.evasion", + "mode": 2, + "value": "+1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Glyph_of_Nightfall_B5HXqYRJiL3xMNKT.json b/src/packs/domains/domainCard_Glyph_of_Nightfall_B5HXqYRJiL3xMNKT.json index a4aa4d9f..35100187 100644 --- a/src/packs/domains/domainCard_Glyph_of_Nightfall_B5HXqYRJiL3xMNKT.json +++ b/src/packs/domains/domainCard_Glyph_of_Nightfall_B5HXqYRJiL3xMNKT.json @@ -100,6 +100,12 @@ "duration": { "description": "", "type": "temporary" + }, + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" } }, "disabled": false, diff --git a/src/packs/domains/domainCard_Goad_Them_On_HufF5KzuNfEb9RTi.json b/src/packs/domains/domainCard_Goad_Them_On_HufF5KzuNfEb9RTi.json index 884324f7..db28b8b5 100644 --- a/src/packs/domains/domainCard_Goad_Them_On_HufF5KzuNfEb9RTi.json +++ b/src/packs/domains/domainCard_Goad_Them_On_HufF5KzuNfEb9RTi.json @@ -106,15 +106,21 @@ "_id": "Jccsuc48gmA6QAni", "type": "base", "system": { - "changes": [ - { - "key": "system.disadvantageSources", - "type": "add", - "value": "Attacking the goading creature", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.disadvantageSources", + "mode": 2, + "value": "Attacking the goading creature", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Grace_Touched_KAuNb51AwhD8KEXk.json b/src/packs/domains/domainCard_Grace_Touched_KAuNb51AwhD8KEXk.json index a788e205..2e48f07b 100644 --- a/src/packs/domains/domainCard_Grace_Touched_KAuNb51AwhD8KEXk.json +++ b/src/packs/domains/domainCard_Grace_Touched_KAuNb51AwhD8KEXk.json @@ -107,10 +107,16 @@ "name": "Grace-Touched", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "KK5m2slpFuXDxFaL", "img": "systems/daggerheart/assets/icons/domains/domain-card/grace.png", + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Healing_Hands_WTlhnQMajc1r8i50.json b/src/packs/domains/domainCard_Healing_Hands_WTlhnQMajc1r8i50.json index a3657ef6..c771562c 100644 --- a/src/packs/domains/domainCard_Healing_Hands_WTlhnQMajc1r8i50.json +++ b/src/packs/domains/domainCard_Healing_Hands_WTlhnQMajc1r8i50.json @@ -385,8 +385,14 @@ "_id": "sd5liP4ZcVeTMAoW", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Hold_the_Line_kdFoLo3KXwn4LqTG.json b/src/packs/domains/domainCard_Hold_the_Line_kdFoLo3KXwn4LqTG.json index a6edb862..263220e4 100644 --- a/src/packs/domains/domainCard_Hold_the_Line_kdFoLo3KXwn4LqTG.json +++ b/src/packs/domains/domainCard_Hold_the_Line_kdFoLo3KXwn4LqTG.json @@ -91,8 +91,14 @@ "_id": "y82y3nUStyL8DIJL", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, @@ -121,6 +127,12 @@ "_id": "WTYg0b8nE1XbnMiA", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Hush_gwmYasmfgXZ7tFS6.json b/src/packs/domains/domainCard_Hush_gwmYasmfgXZ7tFS6.json index 9793c70f..28c41c7e 100644 --- a/src/packs/domains/domainCard_Hush_gwmYasmfgXZ7tFS6.json +++ b/src/packs/domains/domainCard_Hush_gwmYasmfgXZ7tFS6.json @@ -88,6 +88,12 @@ "_id": "pZ5YpjKidaj48IYF", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/domains/domainCard_Hypnotic_Shimmer_2ZeuCGVatQdPOVC6.json b/src/packs/domains/domainCard_Hypnotic_Shimmer_2ZeuCGVatQdPOVC6.json index f4f95d83..08f0d3ee 100644 --- a/src/packs/domains/domainCard_Hypnotic_Shimmer_2ZeuCGVatQdPOVC6.json +++ b/src/packs/domains/domainCard_Hypnotic_Shimmer_2ZeuCGVatQdPOVC6.json @@ -116,6 +116,12 @@ "_id": "xAG75UWUz3aDZH3m", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Inevitable_XTT8c8uJ4D7fvtbL.json b/src/packs/domains/domainCard_Inevitable_XTT8c8uJ4D7fvtbL.json index d7f1d82d..fc083136 100644 --- a/src/packs/domains/domainCard_Inevitable_XTT8c8uJ4D7fvtbL.json +++ b/src/packs/domains/domainCard_Inevitable_XTT8c8uJ4D7fvtbL.json @@ -23,17 +23,23 @@ "name": "Inevitable", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "If you failed your previous action roll", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "wX4BFGaM0bdzHPn2", "img": "icons/magic/light/explosion-beam-impact-silhouette.webp", + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "If you failed your previous action roll", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Invisibility_KHkzA4Zrw8EWN1CH.json b/src/packs/domains/domainCard_Invisibility_KHkzA4Zrw8EWN1CH.json index 9ed72705..5f67ff74 100644 --- a/src/packs/domains/domainCard_Invisibility_KHkzA4Zrw8EWN1CH.json +++ b/src/packs/domains/domainCard_Invisibility_KHkzA4Zrw8EWN1CH.json @@ -94,8 +94,14 @@ "_id": "bRJy0MoIPQEQOMzZ", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Lead_by_Example_YWCRplmtwpCjpq5i.json b/src/packs/domains/domainCard_Lead_by_Example_YWCRplmtwpCjpq5i.json index e2836d8c..a29b021f 100644 --- a/src/packs/domains/domainCard_Lead_by_Example_YWCRplmtwpCjpq5i.json +++ b/src/packs/domains/domainCard_Lead_by_Example_YWCRplmtwpCjpq5i.json @@ -63,8 +63,14 @@ "_id": "BbBs2XYXMsLwkHKh", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Life_Ward_OszbCj0jTqq2ADx9.json b/src/packs/domains/domainCard_Life_Ward_OszbCj0jTqq2ADx9.json index ec2dc590..de841ffe 100644 --- a/src/packs/domains/domainCard_Life_Ward_OszbCj0jTqq2ADx9.json +++ b/src/packs/domains/domainCard_Life_Ward_OszbCj0jTqq2ADx9.json @@ -65,6 +65,12 @@ "_id": "E7Ou4OMEy3TeK1Gf", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "longRest" diff --git a/src/packs/domains/domainCard_Mass_Disguise_dT95m0Jam8sWbeuC.json b/src/packs/domains/domainCard_Mass_Disguise_dT95m0Jam8sWbeuC.json index 4941eddd..b9fbaed9 100644 --- a/src/packs/domains/domainCard_Mass_Disguise_dT95m0Jam8sWbeuC.json +++ b/src/packs/domains/domainCard_Mass_Disguise_dT95m0Jam8sWbeuC.json @@ -93,15 +93,21 @@ "_id": "HgF4n0idPcdz8Bi7", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Presence Rolls to avoid scrutiny.", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Presence Rolls to avoid scrutiny.", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Mass_Enrapture_ubpixIgZrJXKyM3b.json b/src/packs/domains/domainCard_Mass_Enrapture_ubpixIgZrJXKyM3b.json index 48da2c58..8ada8d80 100644 --- a/src/packs/domains/domainCard_Mass_Enrapture_ubpixIgZrJXKyM3b.json +++ b/src/packs/domains/domainCard_Mass_Enrapture_ubpixIgZrJXKyM3b.json @@ -148,6 +148,12 @@ "_id": "QNbnelRylVB0yCm0", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Midnight_Touched_uSyGKVxOJcnp28po.json b/src/packs/domains/domainCard_Midnight_Touched_uSyGKVxOJcnp28po.json index e3b845c2..b859aafb 100644 --- a/src/packs/domains/domainCard_Midnight_Touched_uSyGKVxOJcnp28po.json +++ b/src/packs/domains/domainCard_Midnight_Touched_uSyGKVxOJcnp28po.json @@ -122,10 +122,16 @@ "name": "Midnight-Touched", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "sNBuI2xIZAI4RgZy", "img": "systems/daggerheart/assets/icons/domains/domain-card/midnight.png", + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Natural_Familiar_Tag303LoRNC5zGgl.json b/src/packs/domains/domainCard_Natural_Familiar_Tag303LoRNC5zGgl.json index 68ed1c54..c14116d4 100644 --- a/src/packs/domains/domainCard_Natural_Familiar_Tag303LoRNC5zGgl.json +++ b/src/packs/domains/domainCard_Natural_Familiar_Tag303LoRNC5zGgl.json @@ -139,21 +139,27 @@ "_id": "0BumAWKw2aK4A5al", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.magical.dice", - "type": "add", - "value": "d6", - "priority": null - }, - { - "key": "system.bonuses.damage.physical.dice", - "type": "add", - "value": "d6", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.magical.dice", + "mode": 2, + "value": "d6", + "priority": null + }, + { + "key": "system.bonuses.damage.physical.dice", + "mode": 2, + "value": "d6", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Nature_s_Tongue_atWLorlCOxcrq8WB.json b/src/packs/domains/domainCard_Nature_s_Tongue_atWLorlCOxcrq8WB.json index 42734531..b6c9464a 100644 --- a/src/packs/domains/domainCard_Nature_s_Tongue_atWLorlCOxcrq8WB.json +++ b/src/packs/domains/domainCard_Nature_s_Tongue_atWLorlCOxcrq8WB.json @@ -109,15 +109,21 @@ "_id": "0JYDk5CQ66bHGQO0", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.spellcast.bonus", - "type": "add", - "value": "+2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.roll.spellcast.bonus", + "mode": 2, + "value": "+2", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Never_Upstaged_McdncxmO9K1YNP7Y.json b/src/packs/domains/domainCard_Never_Upstaged_McdncxmO9K1YNP7Y.json index 396b7153..aaa2c60e 100644 --- a/src/packs/domains/domainCard_Never_Upstaged_McdncxmO9K1YNP7Y.json +++ b/src/packs/domains/domainCard_Never_Upstaged_McdncxmO9K1YNP7Y.json @@ -211,21 +211,27 @@ "_id": "C6e1T2oEx6PFoRUP", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "+5", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "+5", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "+5", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "+5", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -254,21 +260,27 @@ "_id": "bMMxsBungVYB1rI8", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "+10", - "priority": null - }, - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "+10", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "+10", + "priority": null + }, + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "+10", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -297,21 +309,27 @@ "_id": "tsQRbrurzi8iqs0o", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "+15", - "priority": null - }, - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "+15", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "+15", + "priority": null + }, + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "+15", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -340,21 +358,27 @@ "_id": "3eTaSgHlmNDcymnW", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "+20", - "priority": null - }, - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "+20", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "+20", + "priority": null + }, + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "+20", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Night_Terror_zcldCuqOg3dphUVI.json b/src/packs/domains/domainCard_Night_Terror_zcldCuqOg3dphUVI.json index 57b8f862..8eefeec4 100644 --- a/src/packs/domains/domainCard_Night_Terror_zcldCuqOg3dphUVI.json +++ b/src/packs/domains/domainCard_Night_Terror_zcldCuqOg3dphUVI.json @@ -150,6 +150,12 @@ "_id": "32j3ZeNMMCk1QLlM", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_On_the_Brink_zbxPl81kbWEegKQN.json b/src/packs/domains/domainCard_On_the_Brink_zbxPl81kbWEegKQN.json index 2dc7b95e..e5f90fe4 100644 --- a/src/packs/domains/domainCard_On_the_Brink_zbxPl81kbWEegKQN.json +++ b/src/packs/domains/domainCard_On_the_Brink_zbxPl81kbWEegKQN.json @@ -23,17 +23,23 @@ "name": "On The Brink", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.damageReduction.thresholdImmunities.minor", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "UJTsJlnhi5Zi0XQ2", "img": "systems/daggerheart/assets/icons/domains/domain-card/bone.png", + "changes": [ + { + "key": "system.rules.damageReduction.thresholdImmunities.minor", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Overwhelming_Aura_iEBLySZD9z8CLdz7.json b/src/packs/domains/domainCard_Overwhelming_Aura_iEBLySZD9z8CLdz7.json index e73171a5..9aa2f5b4 100644 --- a/src/packs/domains/domainCard_Overwhelming_Aura_iEBLySZD9z8CLdz7.json +++ b/src/packs/domains/domainCard_Overwhelming_Aura_iEBLySZD9z8CLdz7.json @@ -89,6 +89,12 @@ "_id": "ba9GO4NtQHYkaRR9", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.traits.presence.value", diff --git a/src/packs/domains/domainCard_Pick_and_Pull_HdgZUfWd7Hyj7nBW.json b/src/packs/domains/domainCard_Pick_and_Pull_HdgZUfWd7Hyj7nBW.json index 1a5e40df..35ac6ce4 100644 --- a/src/packs/domains/domainCard_Pick_and_Pull_HdgZUfWd7Hyj7nBW.json +++ b/src/packs/domains/domainCard_Pick_and_Pull_HdgZUfWd7Hyj7nBW.json @@ -23,29 +23,35 @@ "name": "Pick and Pull", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Pick nonmagical locks", - "priority": null - }, - { - "key": "system.advantageSources", - "type": "add", - "value": "Disarm nonmagical traps", - "priority": null - }, - { - "key": "system.advantageSources", - "type": "add", - "value": "Steal items from a target (either through stealth or by force)", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "6IkjF8qNR0NVvvv8", "img": "icons/tools/hand/lockpicks-steel-grey.webp", + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Pick nonmagical locks", + "priority": null + }, + { + "key": "system.advantageSources", + "mode": 2, + "value": "Disarm nonmagical traps", + "priority": null + }, + { + "key": "system.advantageSources", + "mode": 2, + "value": "Steal items from a target (either through stealth or by force)", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Rage_Up_GRL0cvs96vrTDckZ.json b/src/packs/domains/domainCard_Rage_Up_GRL0cvs96vrTDckZ.json index 13d0f540..c3493aea 100644 --- a/src/packs/domains/domainCard_Rage_Up_GRL0cvs96vrTDckZ.json +++ b/src/packs/domains/domainCard_Rage_Up_GRL0cvs96vrTDckZ.json @@ -65,6 +65,12 @@ "_id": "bq1MhcmoP6Wo5CXF", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.bonuses.damage.magical.bonus", @@ -123,6 +129,12 @@ "_id": "t6SIjQxB6UBUJ98f", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.bonuses.damage.magical.bonus", diff --git a/src/packs/domains/domainCard_Recovery_gsiQFT6q3WOgqerJ.json b/src/packs/domains/domainCard_Recovery_gsiQFT6q3WOgqerJ.json index bf6ffbf3..4cfd0b19 100644 --- a/src/packs/domains/domainCard_Recovery_gsiQFT6q3WOgqerJ.json +++ b/src/packs/domains/domainCard_Recovery_gsiQFT6q3WOgqerJ.json @@ -57,21 +57,27 @@ "_id": "smTjINqIldErFD3q", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.rest.shortRest.longMoves", - "type": "add", - "value": "1", - "priority": null - }, - { - "key": "system.bonuses.rest.shortRest.shortMoves", - "type": "add", - "value": "-1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.rest.shortRest.longMoves", + "mode": 2, + "value": "1", + "priority": null + }, + { + "key": "system.bonuses.rest.shortRest.shortMoves", + "mode": 2, + "value": "-1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -96,23 +102,29 @@ "name": "Recovery", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.rest.shortRest.longMoves", - "type": "add", - "value": "1", - "priority": null - }, - { - "key": "system.bonuses.rest.shortRest.shortMoves", - "type": "add", - "value": "-1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "7GsHTQCtNB8PEVgr", "img": "icons/magic/life/cross-beam-green.webp", + "changes": [ + { + "key": "system.bonuses.rest.shortRest.longMoves", + "mode": 2, + "value": "1", + "priority": null + }, + { + "key": "system.bonuses.rest.shortRest.shortMoves", + "mode": 2, + "value": "-1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Rejuvenation_Barrier_HtWx5IIemCoorMj2.json b/src/packs/domains/domainCard_Rejuvenation_Barrier_HtWx5IIemCoorMj2.json index bfd8fb09..6d8757f7 100644 --- a/src/packs/domains/domainCard_Rejuvenation_Barrier_HtWx5IIemCoorMj2.json +++ b/src/packs/domains/domainCard_Rejuvenation_Barrier_HtWx5IIemCoorMj2.json @@ -110,6 +110,12 @@ "_id": "obul9k0P4CjFuxJD", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.resistance.physical.resistance", diff --git a/src/packs/domains/domainCard_Rise_Up_oDIZoC4l19Nli0Fj.json b/src/packs/domains/domainCard_Rise_Up_oDIZoC4l19Nli0Fj.json index 09c82b6e..5d46562d 100644 --- a/src/packs/domains/domainCard_Rise_Up_oDIZoC4l19Nli0Fj.json +++ b/src/packs/domains/domainCard_Rise_Up_oDIZoC4l19Nli0Fj.json @@ -92,17 +92,23 @@ "name": "Rise Up", "type": "base", "system": { - "changes": [ - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "@system.proficiency", - "priority": 21 - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "ulQpnnRFwW4BwMlE", "img": "icons/magic/defensive/shield-barrier-flaming-pentagon-teal-purple.webp", + "changes": [ + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "@system.proficiency", + "priority": 21 + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Safe_Haven_lmBLMPuR8qLbuzNf.json b/src/packs/domains/domainCard_Safe_Haven_lmBLMPuR8qLbuzNf.json index 14c79df8..0d98c1f9 100644 --- a/src/packs/domains/domainCard_Safe_Haven_lmBLMPuR8qLbuzNf.json +++ b/src/packs/domains/domainCard_Safe_Haven_lmBLMPuR8qLbuzNf.json @@ -63,21 +63,27 @@ "_id": "UaqohKZnokIPLeYf", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.rest.shortRest.shortMoves", - "type": "add", - "value": "1", - "priority": null - }, - { - "key": "system.bonuses.rest.longRest.longMoves", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.rest.shortRest.shortMoves", + "mode": 2, + "value": "1", + "priority": null + }, + { + "key": "system.bonuses.rest.longRest.longMoves", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Sage_Touched_VOSFaQHZbmhMyXwi.json b/src/packs/domains/domainCard_Sage_Touched_VOSFaQHZbmhMyXwi.json index a289fd30..432ff638 100644 --- a/src/packs/domains/domainCard_Sage_Touched_VOSFaQHZbmhMyXwi.json +++ b/src/packs/domains/domainCard_Sage_Touched_VOSFaQHZbmhMyXwi.json @@ -105,17 +105,23 @@ "name": "Increase Spellcasting", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.spellcast.bonus", - "type": "add", - "value": "+2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "7zMpgedPII5GIYUl", "img": "systems/daggerheart/assets/icons/domains/domain-card/sage.png", + "changes": [ + { + "key": "system.bonuses.roll.spellcast.bonus", + "mode": 2, + "value": "+2", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -146,15 +152,21 @@ "_id": "Mmax64mlLPYxJPB7", "type": "base", "system": { - "changes": [ - { - "key": "system.traits.agility.value", - "type": "multiply", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.traits.agility.value", + "mode": 1, + "value": "2", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, @@ -183,15 +195,21 @@ "_id": "p03IjcyigL4b2WD1", "type": "base", "system": { - "changes": [ - { - "key": "system.traits.instinct.value", - "type": "multiply", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.traits.instinct.value", + "mode": 1, + "value": "2", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Shadowbind_kguhWlidhxe2GbT0.json b/src/packs/domains/domainCard_Shadowbind_kguhWlidhxe2GbT0.json index 1023b92c..a90ec0f7 100644 --- a/src/packs/domains/domainCard_Shadowbind_kguhWlidhxe2GbT0.json +++ b/src/packs/domains/domainCard_Shadowbind_kguhWlidhxe2GbT0.json @@ -89,6 +89,12 @@ "_id": "RFB4V0V4bDJ6vCL2", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Shadowhunter_A0XzD6MmBXYdk7Ps.json b/src/packs/domains/domainCard_Shadowhunter_A0XzD6MmBXYdk7Ps.json index b942cc20..a3d98039 100644 --- a/src/packs/domains/domainCard_Shadowhunter_A0XzD6MmBXYdk7Ps.json +++ b/src/packs/domains/domainCard_Shadowhunter_A0XzD6MmBXYdk7Ps.json @@ -24,10 +24,16 @@ "name": "Shadowhunter Evasion", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "A6gMv7TbMu3nV3NT", "img": "icons/skills/movement/feet-winged-boots-glowing-yellow.webp", + "changes": [], "disabled": true, "duration": { "startTime": null, @@ -54,17 +60,23 @@ "name": "Shadowhunter Advantage Hint", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Attack rolls while shrouded in low light or darkness.", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "a1hDCNYDvF4dWt58", "img": "icons/skills/targeting/crosshair-bars-yellow.webp", + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Attack rolls while shrouded in low light or darkness.", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Shield_Aura_rfIv6lln40Fh6EIl.json b/src/packs/domains/domainCard_Shield_Aura_rfIv6lln40Fh6EIl.json index 03155bf1..64544f76 100644 --- a/src/packs/domains/domainCard_Shield_Aura_rfIv6lln40Fh6EIl.json +++ b/src/packs/domains/domainCard_Shield_Aura_rfIv6lln40Fh6EIl.json @@ -65,15 +65,21 @@ "_id": "OQreUqdAfIt3V6uq", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.damageReduction.increasePerArmorMark", - "type": "add", - "value": "+1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.rules.damageReduction.increasePerArmorMark", + "mode": 2, + "value": "+1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Shrug_It_Off_JwfhtgmmuRxg4zhI.json b/src/packs/domains/domainCard_Shrug_It_Off_JwfhtgmmuRxg4zhI.json index f73deba0..3e757308 100644 --- a/src/packs/domains/domainCard_Shrug_It_Off_JwfhtgmmuRxg4zhI.json +++ b/src/packs/domains/domainCard_Shrug_It_Off_JwfhtgmmuRxg4zhI.json @@ -79,17 +79,23 @@ "name": "Shrug It Off", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.damageReduction.stressDamageReduction.any.cost", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "5DTQDVU8Jy5Nnp5V", "img": "icons/magic/defensive/shield-barrier-deflect-teal.webp", + "changes": [ + { + "key": "system.rules.damageReduction.stressDamageReduction.any.cost", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Sigil_of_Retribution_RiuN0lMlfoTAhLJz.json b/src/packs/domains/domainCard_Sigil_of_Retribution_RiuN0lMlfoTAhLJz.json index d0933e2f..a368edad 100644 --- a/src/packs/domains/domainCard_Sigil_of_Retribution_RiuN0lMlfoTAhLJz.json +++ b/src/packs/domains/domainCard_Sigil_of_Retribution_RiuN0lMlfoTAhLJz.json @@ -63,8 +63,14 @@ "_id": "pJntjutNO7bYX6td", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Smite_U1uWJE94HZVudujz.json b/src/packs/domains/domainCard_Smite_U1uWJE94HZVudujz.json index 8a6d2281..23786540 100644 --- a/src/packs/domains/domainCard_Smite_U1uWJE94HZVudujz.json +++ b/src/packs/domains/domainCard_Smite_U1uWJE94HZVudujz.json @@ -65,8 +65,14 @@ "_id": "mqZSae8J9d7o3lon", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Specter_of_the_Dark_iQhgqmLwhcSTYnvr.json b/src/packs/domains/domainCard_Specter_of_the_Dark_iQhgqmLwhcSTYnvr.json index 5291c31c..18af0877 100644 --- a/src/packs/domains/domainCard_Specter_of_the_Dark_iQhgqmLwhcSTYnvr.json +++ b/src/packs/domains/domainCard_Specter_of_the_Dark_iQhgqmLwhcSTYnvr.json @@ -63,15 +63,21 @@ "_id": "d9bZJl0yZnvOe2f3", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.physical.immunity", - "type": "override", - "value": "true", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.resistance.physical.immunity", + "mode": 5, + "value": "true", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Splendor_Touched_JT5dM3gVL6chDBYU.json b/src/packs/domains/domainCard_Splendor_Touched_JT5dM3gVL6chDBYU.json index 730ac290..6b530289 100644 --- a/src/packs/domains/domainCard_Splendor_Touched_JT5dM3gVL6chDBYU.json +++ b/src/packs/domains/domainCard_Splendor_Touched_JT5dM3gVL6chDBYU.json @@ -24,17 +24,23 @@ "name": "Splendor-Touched", "type": "base", "system": { - "changes": [ - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "+3", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "u13fiOMD8B36PkiZ", "img": "systems/daggerheart/assets/icons/domains/domain-card/splendor.png", + "changes": [ + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "+3", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Stunning_Sunlight_lRHo6ZkK1zybeEoG.json b/src/packs/domains/domainCard_Stunning_Sunlight_lRHo6ZkK1zybeEoG.json index 3ffb8821..e2d68a10 100644 --- a/src/packs/domains/domainCard_Stunning_Sunlight_lRHo6ZkK1zybeEoG.json +++ b/src/packs/domains/domainCard_Stunning_Sunlight_lRHo6ZkK1zybeEoG.json @@ -179,6 +179,12 @@ "_id": "kSLuGSI6FLhOJaGp", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Tell_No_Lies_HTv9QEPS466WsstP.json b/src/packs/domains/domainCard_Tell_No_Lies_HTv9QEPS466WsstP.json index e17842dd..1efb1374 100644 --- a/src/packs/domains/domainCard_Tell_No_Lies_HTv9QEPS466WsstP.json +++ b/src/packs/domains/domainCard_Tell_No_Lies_HTv9QEPS466WsstP.json @@ -97,10 +97,16 @@ "name": "Can't Lie", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "5L6fC80VfbPfGmcA", "img": "icons/magic/control/voodoo-doll-pain-damage-red.webp", + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Tempest_X7YaZgFieBlqaPdZ.json b/src/packs/domains/domainCard_Tempest_X7YaZgFieBlqaPdZ.json index 9bf8f2c0..e027ca8f 100644 --- a/src/packs/domains/domainCard_Tempest_X7YaZgFieBlqaPdZ.json +++ b/src/packs/domains/domainCard_Tempest_X7YaZgFieBlqaPdZ.json @@ -290,6 +290,12 @@ "_id": "oqPY3I9oO9J6l5Aj", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" @@ -332,6 +338,12 @@ "_id": "tB7AyDy0pbE9q5hM", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [] }, "disabled": false, @@ -362,6 +374,12 @@ "_id": "S4Vpgf3FMmq8MGrb", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [] }, "disabled": false, diff --git a/src/packs/domains/domainCard_Thorn_Skin_oUipGK84E2KjoKqh.json b/src/packs/domains/domainCard_Thorn_Skin_oUipGK84E2KjoKqh.json index 1f1da4dc..2f97dd84 100644 --- a/src/packs/domains/domainCard_Thorn_Skin_oUipGK84E2KjoKqh.json +++ b/src/packs/domains/domainCard_Thorn_Skin_oUipGK84E2KjoKqh.json @@ -97,8 +97,14 @@ "_id": "KPA1okccsR7AQH0x", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Thought_Delver_B4choj481tqajWb9.json b/src/packs/domains/domainCard_Thought_Delver_B4choj481tqajWb9.json index a69670d5..7c8d6235 100644 --- a/src/packs/domains/domainCard_Thought_Delver_B4choj481tqajWb9.json +++ b/src/packs/domains/domainCard_Thought_Delver_B4choj481tqajWb9.json @@ -109,8 +109,14 @@ "_id": "obbNjDhwN60YhH1s", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Through_Your_Eyes_7b0mzV5QMPjVPT4o.json b/src/packs/domains/domainCard_Through_Your_Eyes_7b0mzV5QMPjVPT4o.json index 85f435be..529950b5 100644 --- a/src/packs/domains/domainCard_Through_Your_Eyes_7b0mzV5QMPjVPT4o.json +++ b/src/packs/domains/domainCard_Through_Your_Eyes_7b0mzV5QMPjVPT4o.json @@ -56,6 +56,12 @@ "_id": "TCOHV7tWpunCZDxn", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "shortRest" diff --git a/src/packs/domains/domainCard_Towering_Stalk_n0P3VS1WfxvmXbB6.json b/src/packs/domains/domainCard_Towering_Stalk_n0P3VS1WfxvmXbB6.json index e154df8f..70a1fbda 100644 --- a/src/packs/domains/domainCard_Towering_Stalk_n0P3VS1WfxvmXbB6.json +++ b/src/packs/domains/domainCard_Towering_Stalk_n0P3VS1WfxvmXbB6.json @@ -19,20 +19,20 @@ "actionType": "action", "cost": [ { - "consumeOnSuccess": false, - "scalable": false, "key": "stress", - "value": 1, "itemId": null, - "step": null + "value": 1, + "scalable": false, + "step": null, + "consumeOnSuccess": false }, { - "consumeOnSuccess": false, - "scalable": false, "key": "resource", - "value": 1, "itemId": "n0P3VS1WfxvmXbB6", - "step": null + "value": 1, + "scalable": false, + "step": null, + "consumeOnSuccess": false } ], "uses": { @@ -119,17 +119,16 @@ "cost": [ { "scalable": false, - "key": "resource", + "key": "hitPoints", "value": 1, - "itemId": "n0P3VS1WfxvmXbB6", "step": null, "consumeOnSuccess": false } ], "uses": { "value": null, - "max": "", - "recovery": null + "max": "1", + "recovery": "shortRest" }, "effects": [], "target": { @@ -141,15 +140,7 @@ "range": "" } }, - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "recovery": "shortRest", - "progression": "decreasing", - "dieFaces": "d4", - "icon": "fa-solid fa-seedling" - }, + "resource": null, "attribution": { "source": "Daggerheart SRD", "page": 130, diff --git a/src/packs/domains/domainCard_Transcendent_Union_kVkoCLBXLAIifqpz.json b/src/packs/domains/domainCard_Transcendent_Union_kVkoCLBXLAIifqpz.json index 14bdc45f..4460a5db 100644 --- a/src/packs/domains/domainCard_Transcendent_Union_kVkoCLBXLAIifqpz.json +++ b/src/packs/domains/domainCard_Transcendent_Union_kVkoCLBXLAIifqpz.json @@ -65,6 +65,12 @@ "_id": "kMcvp2QKmBP4uinB", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "shortRest" diff --git a/src/packs/domains/domainCard_Twilight_Toll_SDjjV61TC1NceV1m.json b/src/packs/domains/domainCard_Twilight_Toll_SDjjV61TC1NceV1m.json index b21f907e..cc7f45c7 100644 --- a/src/packs/domains/domainCard_Twilight_Toll_SDjjV61TC1NceV1m.json +++ b/src/packs/domains/domainCard_Twilight_Toll_SDjjV61TC1NceV1m.json @@ -96,8 +96,14 @@ "_id": "65UMKq0epBx5DbMC", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Uncanny_Disguise_TV56wSysbU5xAlOa.json b/src/packs/domains/domainCard_Uncanny_Disguise_TV56wSysbU5xAlOa.json index e0a2d403..62953005 100644 --- a/src/packs/domains/domainCard_Uncanny_Disguise_TV56wSysbU5xAlOa.json +++ b/src/packs/domains/domainCard_Uncanny_Disguise_TV56wSysbU5xAlOa.json @@ -97,15 +97,21 @@ "_id": "ZMDyDwI5RHe427O4", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Presence Rolls to avoid scrutiny", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Presence Rolls to avoid scrutiny", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Unleash_Chaos_o62i0QdbUDIiAhSq.json b/src/packs/domains/domainCard_Unleash_Chaos_o62i0QdbUDIiAhSq.json index 20b8f00e..69049d01 100644 --- a/src/packs/domains/domainCard_Unleash_Chaos_o62i0QdbUDIiAhSq.json +++ b/src/packs/domains/domainCard_Unleash_Chaos_o62i0QdbUDIiAhSq.json @@ -151,8 +151,14 @@ "_id": "F2yHIwHeZmLlrkkS", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Untouchable_9QElncQUDSakuSdR.json b/src/packs/domains/domainCard_Untouchable_9QElncQUDSakuSdR.json index 9693b6bf..11a1a841 100644 --- a/src/packs/domains/domainCard_Untouchable_9QElncQUDSakuSdR.json +++ b/src/packs/domains/domainCard_Untouchable_9QElncQUDSakuSdR.json @@ -23,17 +23,23 @@ "name": "Untouchable", "type": "base", "system": { - "changes": [ - { - "key": "system.evasion", - "type": "add", - "value": "ceil(@system.traits.agility.value / 2)", - "priority": 21 - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "H8hazlQe4Wj4JFO6", "img": "icons/skills/movement/feet-winged-boots-glowing-yellow.webp", + "changes": [ + { + "key": "system.evasion", + "mode": 2, + "value": "ceil(@system.traits.agility.value / 2)", + "priority": 21 + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Vanishing_Dodge_GBMIElIpk4cvk1Bd.json b/src/packs/domains/domainCard_Vanishing_Dodge_GBMIElIpk4cvk1Bd.json index 14f7f970..f95c8814 100644 --- a/src/packs/domains/domainCard_Vanishing_Dodge_GBMIElIpk4cvk1Bd.json +++ b/src/packs/domains/domainCard_Vanishing_Dodge_GBMIElIpk4cvk1Bd.json @@ -63,8 +63,14 @@ "_id": "kxal5WfDr3hTHYpb", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Veil_of_Night_gV4L5ZZmfPrEbIDh.json b/src/packs/domains/domainCard_Veil_of_Night_gV4L5ZZmfPrEbIDh.json index 8eba6388..cff0c185 100644 --- a/src/packs/domains/domainCard_Veil_of_Night_gV4L5ZZmfPrEbIDh.json +++ b/src/packs/domains/domainCard_Veil_of_Night_gV4L5ZZmfPrEbIDh.json @@ -89,6 +89,12 @@ "_id": "eSfBBZ7IP8qirLu7", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.advantageSources", diff --git a/src/packs/domains/domainCard_Vicious_Entangle_qvpvTnkAoRn9vYO4.json b/src/packs/domains/domainCard_Vicious_Entangle_qvpvTnkAoRn9vYO4.json index cce6cef4..3b7358bc 100644 --- a/src/packs/domains/domainCard_Vicious_Entangle_qvpvTnkAoRn9vYO4.json +++ b/src/packs/domains/domainCard_Vicious_Entangle_qvpvTnkAoRn9vYO4.json @@ -141,6 +141,12 @@ "_id": "Xh0wrgRUuYpwChBU", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" @@ -183,6 +189,12 @@ "_id": "2xzOqTaPJQzGqFJv", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/domains/domainCard_Vitality_sWUlSPOJEaXyQLCj.json b/src/packs/domains/domainCard_Vitality_sWUlSPOJEaXyQLCj.json index 6b4f1740..ec47c9f9 100644 --- a/src/packs/domains/domainCard_Vitality_sWUlSPOJEaXyQLCj.json +++ b/src/packs/domains/domainCard_Vitality_sWUlSPOJEaXyQLCj.json @@ -66,15 +66,21 @@ "_id": "1jtgIyFvDpTb0asZ", "type": "base", "system": { - "changes": [ - { - "key": "system.resources.hitPoints.max", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.resources.hitPoints.max", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, @@ -103,15 +109,21 @@ "_id": "vj9rm1tLqqsSFOXF", "type": "base", "system": { - "changes": [ - { - "key": "system.resources.stress.max", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.resources.stress.max", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, @@ -140,21 +152,27 @@ "_id": "BcqCG9yF6l1LRYqm", "type": "base", "system": { - "changes": [ - { - "key": "system.damageThresholds.major", - "type": "add", - "value": "2", - "priority": null - }, - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.damageThresholds.major", + "mode": 2, + "value": "2", + "priority": null + }, + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "2", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Voice_of_Reason_t3RRGH6mMYYJJCcF.json b/src/packs/domains/domainCard_Voice_of_Reason_t3RRGH6mMYYJJCcF.json index 86305f00..748adec3 100644 --- a/src/packs/domains/domainCard_Voice_of_Reason_t3RRGH6mMYYJJCcF.json +++ b/src/packs/domains/domainCard_Voice_of_Reason_t3RRGH6mMYYJJCcF.json @@ -23,23 +23,29 @@ "name": "Advantage", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "De-escalate violent situations.", - "priority": null - }, - { - "key": "system.advantageSources", - "type": "add", - "value": "Convince someone to follow your lead.", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "qWDojebJXMPIP629", "img": "icons/skills/social/diplomacy-handshake.webp", + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "De-escalate violent situations.", + "priority": null + }, + { + "key": "system.advantageSources", + "mode": 2, + "value": "Convince someone to follow your lead.", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -66,17 +72,23 @@ "name": "Emboldened (activate manually)", "type": "base", "system": { - "changes": [ - { - "key": "system.proficiency", - "type": "add", - "value": "+1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "i5dnpOxTtWV1J46k", "img": "icons/skills/melee/unarmed-punch-fist-yellow-red.webp", + "changes": [ + { + "key": "system.proficiency", + "mode": 2, + "value": "+1", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Wall_Walk_1ROT08E1UVBwHLAS.json b/src/packs/domains/domainCard_Wall_Walk_1ROT08E1UVBwHLAS.json index 2a229101..066600b1 100644 --- a/src/packs/domains/domainCard_Wall_Walk_1ROT08E1UVBwHLAS.json +++ b/src/packs/domains/domainCard_Wall_Walk_1ROT08E1UVBwHLAS.json @@ -65,8 +65,14 @@ "_id": "s1q4O65vtoEDvvUF", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/domains/domainCard_Words_of_Discord_ZjAdi1FSNCDDHI3X.json b/src/packs/domains/domainCard_Words_of_Discord_ZjAdi1FSNCDDHI3X.json index eb14eead..d743f5e1 100644 --- a/src/packs/domains/domainCard_Words_of_Discord_ZjAdi1FSNCDDHI3X.json +++ b/src/packs/domains/domainCard_Words_of_Discord_ZjAdi1FSNCDDHI3X.json @@ -106,8 +106,14 @@ "_id": "DGp7TSriFWotAvP6", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/environments/environment_Abandoned_Grove_pGEdzdLkqYtBhxnG.json b/src/packs/environments/environment_Abandoned_Grove_pGEdzdLkqYtBhxnG.json index 039eafcf..25340e77 100644 --- a/src/packs/environments/environment_Abandoned_Grove_pGEdzdLkqYtBhxnG.json +++ b/src/packs/environments/environment_Abandoned_Grove_pGEdzdLkqYtBhxnG.json @@ -271,6 +271,12 @@ "_id": "LSeftEwgBbXXkLw3", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", @@ -391,7 +397,7 @@ "type": "effect", "_id": "p6V4k4yMwJ1UPZMz", "systemPath": "actions", - "description": "", + "description": "Spend a Fear to summon a @UUID[Compendium.daggerheart.adversaries.Actor.sRn4bqerfARvhgSV]{Minor Chaos Elemental} drawn to the echoes of violence and discord. They appear within Far range of a chosen PC and immediately take the spotlight.What color does the grass turn as the elemental appears? How does the chaos warp insects and small wildlife within the grove?", "chatDisplay": true, "actionType": "action", "cost": [], diff --git a/src/packs/environments/environment_Ambushers_uXZpebPR77YQ1oXI.json b/src/packs/environments/environment_Ambushers_uXZpebPR77YQ1oXI.json index 582e7ec0..e8ba889a 100644 --- a/src/packs/environments/environment_Ambushers_uXZpebPR77YQ1oXI.json +++ b/src/packs/environments/environment_Ambushers_uXZpebPR77YQ1oXI.json @@ -35,9 +35,12 @@ "src": "systems/daggerheart/assets/icons/documents/actors/forest.svg", "anchorX": 0.5, "anchorY": 0.5, + "offsetX": 0, + "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, + "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -88,7 +91,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": {}, + "detectionModes": [], "occludable": { "radius": 0 }, @@ -114,8 +117,7 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false, - "depth": 1 + "prependAdjective": false }, "items": [ { @@ -154,7 +156,7 @@ "type": "effect", "_id": "6DKa1Pm605HpChPd", "systemPath": "actions", - "description": "", + "description": "When a PC starts the ambush on unsuspecting adversaries, you lose 2 Fear and the first attack roll a PC makes has advantage.What are the adversaries in the middle of doing when the ambush starts? How does this impact their approach to the fight?", "chatDisplay": true, "actionType": "action", "cost": [ diff --git a/src/packs/environments/environment_Burning_Heart_of_the_Woods_oY69NN4rYxoRE4hl.json b/src/packs/environments/environment_Burning_Heart_of_the_Woods_oY69NN4rYxoRE4hl.json index 95266957..86d3eff4 100644 --- a/src/packs/environments/environment_Burning_Heart_of_the_Woods_oY69NN4rYxoRE4hl.json +++ b/src/packs/environments/environment_Burning_Heart_of_the_Woods_oY69NN4rYxoRE4hl.json @@ -264,6 +264,12 @@ "_id": "gCkqvBUljsOsYacB", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/environments/environment_Castle_Siege_1eZ32Esq7rfZOjlu.json b/src/packs/environments/environment_Castle_Siege_1eZ32Esq7rfZOjlu.json index 0df61deb..190d78b1 100644 --- a/src/packs/environments/environment_Castle_Siege_1eZ32Esq7rfZOjlu.json +++ b/src/packs/environments/environment_Castle_Siege_1eZ32Esq7rfZOjlu.json @@ -330,7 +330,7 @@ "type": "attack", "_id": "r5JN5oFYL5DC6Qqw", "systemPath": "actions", - "description": "", + "description": "When an adversary is defeated, you can spend a Fear to have a stray attack from a siege weapon hit a point on the battlefield. All targets within Very Close range of that point must make an Agility Reaction Roll.Targets who fail take 3d8+3 physical or magic damage and must mark a Stress.Targets who succeed must mark a Stress.What debris is scattered by the attack? What is broken by the strike that can’t be easily mended?", "chatDisplay": true, "actionType": "action", "cost": [], diff --git a/src/packs/environments/environment_Cliffside_Ascent_LPpfdlNKqiZIl04w.json b/src/packs/environments/environment_Cliffside_Ascent_LPpfdlNKqiZIl04w.json index c65ede29..ef367d67 100644 --- a/src/packs/environments/environment_Cliffside_Ascent_LPpfdlNKqiZIl04w.json +++ b/src/packs/environments/environment_Cliffside_Ascent_LPpfdlNKqiZIl04w.json @@ -45,9 +45,12 @@ "src": "systems/daggerheart/assets/icons/documents/actors/forest.svg", "anchorX": 0.5, "anchorY": 0.5, + "offsetX": 0, + "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, + "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -98,7 +101,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": {}, + "detectionModes": [], "occludable": { "radius": 0 }, @@ -124,8 +127,7 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false, - "depth": 1 + "prependAdjective": false }, "items": [ { @@ -202,7 +204,7 @@ "type": "damage", "_id": "p1UiGEiGyl6r7PrA", "systemPath": "actions", - "description": "", + "description": "Previous climbers left behind large metal rods that climbers can use to aid their ascent. If a PC using the pitons fails an action roll to climb, they can mark a Stress instead of ticking the countdown up.What do the shape and material of these pitons tell you about the previous climbers? How far apart are they from one another?", "chatDisplay": true, "actionType": "action", "cost": [], @@ -433,7 +435,7 @@ "type": "effect", "_id": "M8MfD2qBfYCwNKvH", "systemPath": "actions", - "description": "", + "description": "Spend a Fear to have a PC’s handhold fail, plummeting them toward the ground. If they aren’t saved on the next action, they hit the ground and tick up the countdown by 2. The PC takes 1d12 physical damage if the countdown is between 8 and 12, 2d12 between 4 and 7, and 3d12 at 3 or lower.How can you tell many others have fallen here before? What lives in these walls that might try to scare adventurers into falling for an easy meal?", "chatDisplay": true, "actionType": "action", "cost": [ diff --git a/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json b/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json index e3e90c26..1295db59 100644 --- a/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json +++ b/src/packs/environments/environment_Cult_Ritual_QAXXiOKBDmCTauHD.json @@ -45,9 +45,12 @@ "src": "systems/daggerheart/assets/icons/documents/actors/forest.svg", "anchorX": 0.5, "anchorY": 0.5, + "offsetX": 0, + "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, + "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -98,7 +101,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": {}, + "detectionModes": [], "occludable": { "radius": 0 }, @@ -124,8 +127,7 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false, - "depth": 1 + "prependAdjective": false }, "items": [ { @@ -181,15 +183,21 @@ "_id": "8yNIw8Y7rfMdOqWC", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.dualityRoll.defaultHopeDice", - "type": "override", - "value": "d10", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.rules.dualityRoll.defaultHopeDice", + "mode": 5, + "value": "d10", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -234,7 +242,7 @@ "type": "effect", "_id": "EATw4ZkcuGeDfgLZ", "systemPath": "actions", - "description": "", + "description": "A portion of the ritual’s power is diverted into a cult member to fight off interlopers. Choose one adversary to become Imbued with terrible magic until the scene ends or they’re defeated. An Imbued adversary immediately takes the spotlight and gains one of the following benefits, or all three if you spend a Fear:They gain advantage on all attacks.They deal an extra 1d10 damage on a successful attack.They gain the following feature: Relentless (2) - Passive. This adversary can be spotlighted up to two times per GM turn. Spend Fear as usual to spotlight them.How does the enemy change in appearance? What fears do their blows bring to the surface?", "chatDisplay": true, "actionType": "action", "cost": [], @@ -277,14 +285,23 @@ "_id": "dYQBQq1xIysM0qLo", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { - "value": null, - "units": "seconds", - "expiry": null, - "expired": false + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null }, "description": "An Imbued adversary immediately takes the spotlight and gains one of the following benefits, or all three if you spend a Fear:They gain advantage on all attacks.They deal an extra 1d10 damage on a successful attack.They gain the following feature: Relentless (2) - Passive. This adversary can be spotlighted up to two times per GM turn. Spend Fear as usual to spotlight them.How does the enemy change in appearance? What fears do their blows bring to the surface?", "tint": "#ffffff", @@ -294,9 +311,6 @@ "_stats": { "compendiumSource": null }, - "start": null, - "showIcon": 1, - "folder": null, "_key": "!actors.items.effects!QAXXiOKBDmCTauHD.0Rgqw1kUPeJ11ldd.dYQBQq1xIysM0qLo" }, { @@ -307,27 +321,36 @@ "_id": "Hxw5lXE77bGzuaOu", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.dice", - "type": "add", - "value": "1d10", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.dice", - "type": "add", - "value": "1d10", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.dice", + "mode": 2, + "value": "1d10", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.dice", + "mode": 2, + "value": "1d10", + "priority": null + } + ], "disabled": true, "duration": { - "value": null, - "units": "seconds", - "expiry": null, - "expired": false + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null }, "description": "", "tint": "#ffffff", @@ -337,9 +360,6 @@ "_stats": { "compendiumSource": null }, - "start": null, - "showIcon": 1, - "folder": null, "_key": "!actors.items.effects!QAXXiOKBDmCTauHD.0Rgqw1kUPeJ11ldd.Hxw5lXE77bGzuaOu" } ], diff --git a/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json b/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json index 339ac5cd..637cdd41 100644 --- a/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json +++ b/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json @@ -397,8 +397,14 @@ "_id": "znFFS76Nopwb8Yi7", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, @@ -422,33 +428,39 @@ "_id": "i3KYskkA9D4GHbXi", "type": "base", "system": { - "changes": [ - { - "key": "system.difficulty", - "type": "add", - "value": "0", - "priority": null - }, - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "0", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "0", - "priority": null - }, - { - "key": "system.bonuses.roll.attack.bonus", - "type": "add", - "value": "0", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.difficulty", + "mode": 2, + "value": "0", + "priority": null + }, + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "0", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "0", + "priority": null + }, + { + "key": "system.bonuses.roll.attack.bonus", + "mode": 2, + "value": "0", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/environments/environment_Hallowed_Temple_dsA6j69AnaJhUyqH.json b/src/packs/environments/environment_Hallowed_Temple_dsA6j69AnaJhUyqH.json index d8b04d22..c510a87f 100644 --- a/src/packs/environments/environment_Hallowed_Temple_dsA6j69AnaJhUyqH.json +++ b/src/packs/environments/environment_Hallowed_Temple_dsA6j69AnaJhUyqH.json @@ -44,9 +44,12 @@ "src": "systems/daggerheart/assets/icons/documents/actors/forest.svg", "anchorX": 0.5, "anchorY": 0.5, + "offsetX": 0, + "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, + "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -97,7 +100,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": {}, + "detectionModes": [], "occludable": { "radius": 0 }, @@ -123,8 +126,7 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false, - "depth": 1 + "prependAdjective": false }, "items": [ { @@ -138,7 +140,7 @@ "type": "healing", "_id": "uLCoTKa7Jn2HaRqR", "systemPath": "actions", - "description": "", + "description": "A PC who takes a rest in the Hallowed Temple automatically clears all HP.What does the incense smell like? What kinds of songs do the acolytes sing?", "chatDisplay": true, "actionType": "action", "cost": [], @@ -335,7 +337,7 @@ "type": "effect", "_id": "pJVipg7CbA9CB0Um", "systemPath": "actions", - "description": "", + "description": "When the PCs have trespassed, blasphemed, or offended the clergy, you can spend a Fear to summon a @UUID[Compendium.daggerheart.adversaries.Actor.r1mbfSSwKWdcFdAU]{High Seraph} and [[/r 1d4]] @UUID[Compendium.daggerheart.adversaries.Actor.B4LZcGuBAHzyVdzy]{Bladed Guard} within Close range of the senior priest to reinforce their will.What symbols or icons do they bear that signal they are anointed agents of the divinity? Who leads the group and what led them to this calling?", "chatDisplay": true, "actionType": "action", "cost": [ diff --git a/src/packs/environments/environment_Haunted_City_OzYbizKraK92FDiI.json b/src/packs/environments/environment_Haunted_City_OzYbizKraK92FDiI.json index bbc3ef0a..1bd07a57 100644 --- a/src/packs/environments/environment_Haunted_City_OzYbizKraK92FDiI.json +++ b/src/packs/environments/environment_Haunted_City_OzYbizKraK92FDiI.json @@ -44,9 +44,12 @@ "src": "systems/daggerheart/assets/icons/documents/actors/forest.svg", "anchorX": 0.5, "anchorY": 0.5, + "offsetX": 0, + "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, + "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -97,7 +100,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": {}, + "detectionModes": [], "occludable": { "radius": 0 }, @@ -123,8 +126,7 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false, - "depth": 1 + "prependAdjective": false }, "items": [ { @@ -201,15 +203,21 @@ "_id": "S9gl4jqdrziC1F0h", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.physical.resistance", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.resistance.physical.resistance", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -280,7 +288,7 @@ "type": "countdown", "_id": "VhqZKDA4032i8zY3", "systemPath": "actions", - "description": "", + "description": "Spend a Fear to manifest the echo of a past disaster that ravaged the city. Activate a Progress Countdown (5) as the disaster replays around the PCs. To complete the countdown and escape the catastrophe, the PCs must overcome threats such as rampaging fires, stampeding civilians, collapsing buildings, or crumbling streets, while recalling history and finding clues to escape the inevitable.Is this the disaster that led the city to be abandoned? What is known about this disaster and how could that help the PCs escape?", "chatDisplay": true, "originItem": { "type": "itemCollection" diff --git a/src/packs/environments/environment_Imperial_Court_jr1xAoXzVwVblzxI.json b/src/packs/environments/environment_Imperial_Court_jr1xAoXzVwVblzxI.json index 93851e3c..5807d43c 100644 --- a/src/packs/environments/environment_Imperial_Court_jr1xAoXzVwVblzxI.json +++ b/src/packs/environments/environment_Imperial_Court_jr1xAoXzVwVblzxI.json @@ -46,9 +46,12 @@ "src": "systems/daggerheart/assets/icons/documents/actors/forest.svg", "anchorX": 0.5, "anchorY": 0.5, + "offsetX": 0, + "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, + "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -99,7 +102,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": {}, + "detectionModes": [], "occludable": { "radius": 0 }, @@ -125,8 +128,7 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false, - "depth": 1 + "prependAdjective": false }, "items": [ { @@ -295,7 +297,7 @@ "type": "attack", "_id": "9ipckCFMz9DVw8ab", "systemPath": "actions", - "description": "", + "description": "Spend a Fear to tick down a long-term countdown related to the empire’s agenda by [[/r 1d4]]. If this triggers the countdown, a proclamation related to the agenda is announced at court as the plan is executed.What display of power or transfer of wealth was needed to expedite this plan? Whose lives were disrupted or upended to make this happen?", "chatDisplay": true, "actionType": "action", "cost": [], diff --git a/src/packs/environments/environment_Necromancer_s_Ossuary_h3KyRL7AshhLAmcH.json b/src/packs/environments/environment_Necromancer_s_Ossuary_h3KyRL7AshhLAmcH.json index 3d87930c..299e8729 100644 --- a/src/packs/environments/environment_Necromancer_s_Ossuary_h3KyRL7AshhLAmcH.json +++ b/src/packs/environments/environment_Necromancer_s_Ossuary_h3KyRL7AshhLAmcH.json @@ -137,7 +137,7 @@ "type": "damage", "_id": "jVY198vniaTSlgsX", "systemPath": "actions", - "description": "", + "description": "A feature or action that clears HP requires spending a Hope to use. If it already costs Hope, a PC must spend an additional Hope.What does it feel like to try to heal in a place so antithetical to life?", "chatDisplay": true, "actionType": "action", "cost": [], @@ -240,7 +240,7 @@ "type": "attack", "_id": "M1mOwi4Limw2hRwL", "systemPath": "actions", - "description": "", + "description": "All targets within Close range of a point you choose in this environment must succeed on an Agility Reaction Roll or take 4d8+8 physical damage from skeletal shrapnel as part of the ossuary detonates around them.What ancient skeletal architecture is destroyed? What bones stick in your armor?", "chatDisplay": true, "actionType": "action", "cost": [], @@ -421,7 +421,7 @@ "type": "effect", "_id": "hFeTdiHWeCYkb8Hg", "systemPath": "actions", - "description": "", + "description": "Spend a Fear to summon [[/r 1d6]] @UUID[Compendium.daggerheart.adversaries.Actor.gP3fWTLzSFnpA8EJ]{Rotted Zombie}, two @UUID[Compendium.daggerheart.adversaries.Actor.CP6iRfHdyFWniTHY]{Perfected Zombie}, or a @UUID[Compendium.daggerheart.adversaries.Actor.YhJrP7rTBiRdX5Fp]{Zombie Legion}, who appear at Close range of a chosen PC.Who were these people before they became the necromancer’s pawns? What vestiges of those lives remain for the heroes to see?", "chatDisplay": true, "actionType": "action", "cost": [ diff --git a/src/packs/environments/environment_Pitched_Battle_EWD3ZsLoK6VMVOf7.json b/src/packs/environments/environment_Pitched_Battle_EWD3ZsLoK6VMVOf7.json index 120b92a0..42fbd8f9 100644 --- a/src/packs/environments/environment_Pitched_Battle_EWD3ZsLoK6VMVOf7.json +++ b/src/packs/environments/environment_Pitched_Battle_EWD3ZsLoK6VMVOf7.json @@ -199,7 +199,7 @@ "type": "attack", "_id": "1giAFbu3tGqXwi8g", "systemPath": "actions", - "description": "", + "description": "Spend a Fear as a mage from one side uses large-scale destructive magic. Pick a point on the battlefield within Very Far range of the mage. All targets within Close range of that point must make an Agility Reaction Roll. Targets who fail take 3d12+8 magic damage and must mark a Stress.What form does the attack take—fireball raining acid a storm of blades? What tactical objective is this attack meant to accomplish and what comes next?", "chatDisplay": true, "actionType": "action", "cost": [ diff --git a/src/packs/environments/environment_Raging_River_t4cdqTfzcqP3H1vJ.json b/src/packs/environments/environment_Raging_River_t4cdqTfzcqP3H1vJ.json index 21e1bbe5..6c87c446 100644 --- a/src/packs/environments/environment_Raging_River_t4cdqTfzcqP3H1vJ.json +++ b/src/packs/environments/environment_Raging_River_t4cdqTfzcqP3H1vJ.json @@ -310,6 +310,12 @@ "_id": "T0ouSQyR8cVpAn79", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/items/armors/armor_Advanced_Chainmail_Armor_LzLOJ9EVaHWAjoq9.json b/src/packs/items/armors/armor_Advanced_Chainmail_Armor_LzLOJ9EVaHWAjoq9.json index 53f9bf79..4566396a 100644 --- a/src/packs/items/armors/armor_Advanced_Chainmail_Armor_LzLOJ9EVaHWAjoq9.json +++ b/src/packs/items/armors/armor_Advanced_Chainmail_Armor_LzLOJ9EVaHWAjoq9.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/armors/armor_Advanced_Full_Plate_Armor_crIbCb9NZ4K0VpoU.json b/src/packs/items/armors/armor_Advanced_Full_Plate_Armor_crIbCb9NZ4K0VpoU.json index 5fde7416..52adc7aa 100644 --- a/src/packs/items/armors/armor_Advanced_Full_Plate_Armor_crIbCb9NZ4K0VpoU.json +++ b/src/packs/items/armors/armor_Advanced_Full_Plate_Armor_crIbCb9NZ4K0VpoU.json @@ -45,12 +45,12 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-2" }, { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/armors/armor_Advanced_Gambeson_Armor_epkAmlZVk7HOfUUT.json b/src/packs/items/armors/armor_Advanced_Gambeson_Armor_epkAmlZVk7HOfUUT.json index fe6a96fb..36edec39 100644 --- a/src/packs/items/armors/armor_Advanced_Gambeson_Armor_epkAmlZVk7HOfUUT.json +++ b/src/packs/items/armors/armor_Advanced_Gambeson_Armor_epkAmlZVk7HOfUUT.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "1" } ], diff --git a/src/packs/items/armors/armor_Bellamoi_Fine_Armor_WuoVwZA53XRAIt6d.json b/src/packs/items/armors/armor_Bellamoi_Fine_Armor_WuoVwZA53XRAIt6d.json index 8df5162f..c470de87 100644 --- a/src/packs/items/armors/armor_Bellamoi_Fine_Armor_WuoVwZA53XRAIt6d.json +++ b/src/packs/items/armors/armor_Bellamoi_Fine_Armor_WuoVwZA53XRAIt6d.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.traits.presence.value", - "type": "add", + "mode": 2, "value": "1" } ], diff --git a/src/packs/items/armors/armor_Bladefare_Armor_mNN6pvcsS10ChrWF.json b/src/packs/items/armors/armor_Bladefare_Armor_mNN6pvcsS10ChrWF.json index 70a8b229..4ee73939 100644 --- a/src/packs/items/armors/armor_Bladefare_Armor_mNN6pvcsS10ChrWF.json +++ b/src/packs/items/armors/armor_Bladefare_Armor_mNN6pvcsS10ChrWF.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.rules.damageReduction.physical", - "type": "override", + "mode": 5, "value": "1" } ], diff --git a/src/packs/items/armors/armor_Chainmail_Armor_haULhuEg37zUUvhb.json b/src/packs/items/armors/armor_Chainmail_Armor_haULhuEg37zUUvhb.json index c41978b9..4f0719a7 100644 --- a/src/packs/items/armors/armor_Chainmail_Armor_haULhuEg37zUUvhb.json +++ b/src/packs/items/armors/armor_Chainmail_Armor_haULhuEg37zUUvhb.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/armors/armor_Channeling_Armor_vMJxEWz1srfwMsoj.json b/src/packs/items/armors/armor_Channeling_Armor_vMJxEWz1srfwMsoj.json index 9f24ee70..e805d5d1 100644 --- a/src/packs/items/armors/armor_Channeling_Armor_vMJxEWz1srfwMsoj.json +++ b/src/packs/items/armors/armor_Channeling_Armor_vMJxEWz1srfwMsoj.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.bonuses.roll.spellcast", - "type": "add", + "mode": 2, "value": "1" } ], diff --git a/src/packs/items/armors/armor_Elundrian_Chain_Armor_Q6LxmtFetDDkoZVZ.json b/src/packs/items/armors/armor_Elundrian_Chain_Armor_Q6LxmtFetDDkoZVZ.json index d8de4497..1cf74e2e 100644 --- a/src/packs/items/armors/armor_Elundrian_Chain_Armor_Q6LxmtFetDDkoZVZ.json +++ b/src/packs/items/armors/armor_Elundrian_Chain_Armor_Q6LxmtFetDDkoZVZ.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.resistance.magical.reduction", - "type": "add", + "mode": 2, "value": "@system.armorScore", "priority": 21 } diff --git a/src/packs/items/armors/armor_Full_Fortified_Armor_7emTSt6nhZuTlvt5.json b/src/packs/items/armors/armor_Full_Fortified_Armor_7emTSt6nhZuTlvt5.json index acc8c125..9f2d7ece 100644 --- a/src/packs/items/armors/armor_Full_Fortified_Armor_7emTSt6nhZuTlvt5.json +++ b/src/packs/items/armors/armor_Full_Fortified_Armor_7emTSt6nhZuTlvt5.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.rules.damageReduction.increasePerArmorMark", - "type": "override", + "mode": 5, "value": "2" } ], diff --git a/src/packs/items/armors/armor_Full_Plate_Armor_UdUJNa31WxFW2noa.json b/src/packs/items/armors/armor_Full_Plate_Armor_UdUJNa31WxFW2noa.json index 7d08e57e..7701d063 100644 --- a/src/packs/items/armors/armor_Full_Plate_Armor_UdUJNa31WxFW2noa.json +++ b/src/packs/items/armors/armor_Full_Plate_Armor_UdUJNa31WxFW2noa.json @@ -45,12 +45,12 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-2" }, { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/armors/armor_Gambeson_Armor_yJFp1bfpecDcStVK.json b/src/packs/items/armors/armor_Gambeson_Armor_yJFp1bfpecDcStVK.json index 0ab7203b..0ede5b60 100644 --- a/src/packs/items/armors/armor_Gambeson_Armor_yJFp1bfpecDcStVK.json +++ b/src/packs/items/armors/armor_Gambeson_Armor_yJFp1bfpecDcStVK.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "1" } ], diff --git a/src/packs/items/armors/armor_Improved_Chainmail_Armor_K5WkjS0NGqHYmhU3.json b/src/packs/items/armors/armor_Improved_Chainmail_Armor_K5WkjS0NGqHYmhU3.json index c87b1f51..ef93ecdd 100644 --- a/src/packs/items/armors/armor_Improved_Chainmail_Armor_K5WkjS0NGqHYmhU3.json +++ b/src/packs/items/armors/armor_Improved_Chainmail_Armor_K5WkjS0NGqHYmhU3.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/armors/armor_Improved_Full_Plate_Armor_9f7RozpPTqrzJS1m.json b/src/packs/items/armors/armor_Improved_Full_Plate_Armor_9f7RozpPTqrzJS1m.json index 85b4ed88..1723c53a 100644 --- a/src/packs/items/armors/armor_Improved_Full_Plate_Armor_9f7RozpPTqrzJS1m.json +++ b/src/packs/items/armors/armor_Improved_Full_Plate_Armor_9f7RozpPTqrzJS1m.json @@ -45,12 +45,12 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-2" }, { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/armors/armor_Improved_Gambeson_Armor_jphnMZjnS2FkOH3s.json b/src/packs/items/armors/armor_Improved_Gambeson_Armor_jphnMZjnS2FkOH3s.json index 4f2f3c2b..a2ff6554 100644 --- a/src/packs/items/armors/armor_Improved_Gambeson_Armor_jphnMZjnS2FkOH3s.json +++ b/src/packs/items/armors/armor_Improved_Gambeson_Armor_jphnMZjnS2FkOH3s.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "1" } ], diff --git a/src/packs/items/armors/armor_Irontree_Breastplate_Armor_tzZntboNtHL5C6VM.json b/src/packs/items/armors/armor_Irontree_Breastplate_Armor_tzZntboNtHL5C6VM.json index d73d5e45..a664ad9c 100644 --- a/src/packs/items/armors/armor_Irontree_Breastplate_Armor_tzZntboNtHL5C6VM.json +++ b/src/packs/items/armors/armor_Irontree_Breastplate_Armor_tzZntboNtHL5C6VM.json @@ -45,13 +45,13 @@ "changes": [ { "key": "system.damageThresholds.major", - "type": "add", + "mode": 2, "value": "2", "priority": null }, { "key": "system.damageThresholds.severe", - "type": "add", + "mode": 2, "value": "2", "priority": null } diff --git a/src/packs/items/armors/armor_Legendary_Chainmail_Armor_EsIN5OLKe9ZYFNXZ.json b/src/packs/items/armors/armor_Legendary_Chainmail_Armor_EsIN5OLKe9ZYFNXZ.json index 472b243c..6c93cbe4 100644 --- a/src/packs/items/armors/armor_Legendary_Chainmail_Armor_EsIN5OLKe9ZYFNXZ.json +++ b/src/packs/items/armors/armor_Legendary_Chainmail_Armor_EsIN5OLKe9ZYFNXZ.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/armors/armor_Legendary_Full_Plate_Armor_SXWjUR2aUR6bYvdl.json b/src/packs/items/armors/armor_Legendary_Full_Plate_Armor_SXWjUR2aUR6bYvdl.json index 52f52882..f66e4c38 100644 --- a/src/packs/items/armors/armor_Legendary_Full_Plate_Armor_SXWjUR2aUR6bYvdl.json +++ b/src/packs/items/armors/armor_Legendary_Full_Plate_Armor_SXWjUR2aUR6bYvdl.json @@ -45,12 +45,12 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-2" }, { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/armors/armor_Legendary_Gambeson_Armor_c6tMXz4rPf9ioQrf.json b/src/packs/items/armors/armor_Legendary_Gambeson_Armor_c6tMXz4rPf9ioQrf.json index a703c7c7..4cf1c856 100644 --- a/src/packs/items/armors/armor_Legendary_Gambeson_Armor_c6tMXz4rPf9ioQrf.json +++ b/src/packs/items/armors/armor_Legendary_Gambeson_Armor_c6tMXz4rPf9ioQrf.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "1" } ], diff --git a/src/packs/items/armors/armor_Monett_s_Cloak_AQzU2RsqS5V5bd1v.json b/src/packs/items/armors/armor_Monett_s_Cloak_AQzU2RsqS5V5bd1v.json index a160aeee..6bb479a4 100644 --- a/src/packs/items/armors/armor_Monett_s_Cloak_AQzU2RsqS5V5bd1v.json +++ b/src/packs/items/armors/armor_Monett_s_Cloak_AQzU2RsqS5V5bd1v.json @@ -45,7 +45,7 @@ "changes": [ { "key": "system.rules.damageReduction.magical", - "type": "override", + "mode": 5, "value": "1" } ], diff --git a/src/packs/items/armors/armor_Savior_Chainmail_8X16lJQ3xltTwynm.json b/src/packs/items/armors/armor_Savior_Chainmail_8X16lJQ3xltTwynm.json index 0a7f55ba..6826254a 100644 --- a/src/packs/items/armors/armor_Savior_Chainmail_8X16lJQ3xltTwynm.json +++ b/src/packs/items/armors/armor_Savior_Chainmail_8X16lJQ3xltTwynm.json @@ -45,37 +45,37 @@ "changes": [ { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "-1" }, { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "-1" }, { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "-1" }, { "key": "system.traits.instinct.value", - "type": "add", + "mode": 2, "value": "-1" }, { "key": "system.traits.presence.value", - "type": "add", + "mode": 2, "value": "-1" }, { "key": "system.traits.knowledge.value", - "type": "add", + "mode": 2, "value": "-1" }, { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/armors/armor_Spiked_Plate_Armor_QjwsIhXKqnlvRBMv.json b/src/packs/items/armors/armor_Spiked_Plate_Armor_QjwsIhXKqnlvRBMv.json index 8f91f92b..ac9115a2 100644 --- a/src/packs/items/armors/armor_Spiked_Plate_Armor_QjwsIhXKqnlvRBMv.json +++ b/src/packs/items/armors/armor_Spiked_Plate_Armor_QjwsIhXKqnlvRBMv.json @@ -45,12 +45,12 @@ "changes": [ { "key": "system.bonuses.damage.primaryWeapon.dice", - "type": "add", + "mode": 2, "value": "1d4" }, { "key": "system.bonuses.damage.secondaryWeapon.dice", - "type": "add", + "mode": 2, "value": "1d4" } ], diff --git a/src/packs/items/consumables/consumable_Attune_Potion_JGD3M9hBHtVAA8XP.json b/src/packs/items/consumables/consumable_Attune_Potion_JGD3M9hBHtVAA8XP.json index d17ae550..e034976a 100644 --- a/src/packs/items/consumables/consumable_Attune_Potion_JGD3M9hBHtVAA8XP.json +++ b/src/packs/items/consumables/consumable_Attune_Potion_JGD3M9hBHtVAA8XP.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.instinct.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Bolster_Potion_FOPQNqXbiVO0ilYL.json b/src/packs/items/consumables/consumable_Bolster_Potion_FOPQNqXbiVO0ilYL.json index d200d825..421acdc3 100644 --- a/src/packs/items/consumables/consumable_Bolster_Potion_FOPQNqXbiVO0ilYL.json +++ b/src/packs/items/consumables/consumable_Bolster_Potion_FOPQNqXbiVO0ilYL.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Charm_Potion_CVBbFfOY75YwyQsp.json b/src/packs/items/consumables/consumable_Charm_Potion_CVBbFfOY75YwyQsp.json index 015f334e..f1d7b058 100644 --- a/src/packs/items/consumables/consumable_Charm_Potion_CVBbFfOY75YwyQsp.json +++ b/src/packs/items/consumables/consumable_Charm_Potion_CVBbFfOY75YwyQsp.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.presence.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Control_Potion_eeBhZSGLjuNZuJuI.json b/src/packs/items/consumables/consumable_Control_Potion_eeBhZSGLjuNZuJuI.json index dbb6b796..2c6b9a93 100644 --- a/src/packs/items/consumables/consumable_Control_Potion_eeBhZSGLjuNZuJuI.json +++ b/src/packs/items/consumables/consumable_Control_Potion_eeBhZSGLjuNZuJuI.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Death_Tea_xDnJeF1grkmKck8Q.json b/src/packs/items/consumables/consumable_Death_Tea_xDnJeF1grkmKck8Q.json index c3140964..5fbae976 100644 --- a/src/packs/items/consumables/consumable_Death_Tea_xDnJeF1grkmKck8Q.json +++ b/src/packs/items/consumables/consumable_Death_Tea_xDnJeF1grkmKck8Q.json @@ -60,8 +60,14 @@ "_id": "IqlpqsgurXsUEQhs", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/consumables/consumable_Enlighten_Potion_aWHSO2AqDufi7nL4.json b/src/packs/items/consumables/consumable_Enlighten_Potion_aWHSO2AqDufi7nL4.json index 5d9712b1..bff70126 100644 --- a/src/packs/items/consumables/consumable_Enlighten_Potion_aWHSO2AqDufi7nL4.json +++ b/src/packs/items/consumables/consumable_Enlighten_Potion_aWHSO2AqDufi7nL4.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.knowledge.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Featherbone_DpxEMpwfasEBpORU.json b/src/packs/items/consumables/consumable_Featherbone_DpxEMpwfasEBpORU.json index 60801419..9b5bd0df 100644 --- a/src/packs/items/consumables/consumable_Featherbone_DpxEMpwfasEBpORU.json +++ b/src/packs/items/consumables/consumable_Featherbone_DpxEMpwfasEBpORU.json @@ -60,8 +60,14 @@ "_id": "VfJIJBW96e45xQHY", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/consumables/consumable_Gill_Salve_Nvbb9mze6o5D0AEg.json b/src/packs/items/consumables/consumable_Gill_Salve_Nvbb9mze6o5D0AEg.json index 2e0ac7b6..890c61e4 100644 --- a/src/packs/items/consumables/consumable_Gill_Salve_Nvbb9mze6o5D0AEg.json +++ b/src/packs/items/consumables/consumable_Gill_Salve_Nvbb9mze6o5D0AEg.json @@ -60,8 +60,14 @@ "_id": "5rL9CY5GO9SJcEZq", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/consumables/consumable_Grindletooth_Venom_8WkhvSzeOmLdnoLJ.json b/src/packs/items/consumables/consumable_Grindletooth_Venom_8WkhvSzeOmLdnoLJ.json index 22cc7723..70291404 100644 --- a/src/packs/items/consumables/consumable_Grindletooth_Venom_8WkhvSzeOmLdnoLJ.json +++ b/src/packs/items/consumables/consumable_Grindletooth_Venom_8WkhvSzeOmLdnoLJ.json @@ -60,15 +60,21 @@ "_id": "yx4ZkXeuXgw2KvV4", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.dice", - "type": "add", - "value": "1d6", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.dice", + "mode": 2, + "value": "1d6", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/consumables/consumable_Homet_s_Secret_Potion_VSwa1LpQ9PjZKsWF.json b/src/packs/items/consumables/consumable_Homet_s_Secret_Potion_VSwa1LpQ9PjZKsWF.json index 9b88b267..00eb03f1 100644 --- a/src/packs/items/consumables/consumable_Homet_s_Secret_Potion_VSwa1LpQ9PjZKsWF.json +++ b/src/packs/items/consumables/consumable_Homet_s_Secret_Potion_VSwa1LpQ9PjZKsWF.json @@ -60,8 +60,14 @@ "_id": "QyzXAnvho7lVQQtP", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/consumables/consumable_Improved_Grindletooth_Venom_BqBWXXe9T07AMV4u.json b/src/packs/items/consumables/consumable_Improved_Grindletooth_Venom_BqBWXXe9T07AMV4u.json index 3e5907d8..560644b3 100644 --- a/src/packs/items/consumables/consumable_Improved_Grindletooth_Venom_BqBWXXe9T07AMV4u.json +++ b/src/packs/items/consumables/consumable_Improved_Grindletooth_Venom_BqBWXXe9T07AMV4u.json @@ -60,15 +60,21 @@ "_id": "P7tbNjq58bQ9R1Cc", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.dice", - "type": "add", - "value": "1d8", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.dice", + "mode": 2, + "value": "1d8", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/consumables/consumable_Major_Attune_Potion_CCPFm5iXXwvyYYwR.json b/src/packs/items/consumables/consumable_Major_Attune_Potion_CCPFm5iXXwvyYYwR.json index 784ed534..b27fee91 100644 --- a/src/packs/items/consumables/consumable_Major_Attune_Potion_CCPFm5iXXwvyYYwR.json +++ b/src/packs/items/consumables/consumable_Major_Attune_Potion_CCPFm5iXXwvyYYwR.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.instinct.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Major_Bolster_Potion_mnyQDRtngWWQeRXF.json b/src/packs/items/consumables/consumable_Major_Bolster_Potion_mnyQDRtngWWQeRXF.json index fc35ef93..95cd6c92 100644 --- a/src/packs/items/consumables/consumable_Major_Bolster_Potion_mnyQDRtngWWQeRXF.json +++ b/src/packs/items/consumables/consumable_Major_Bolster_Potion_mnyQDRtngWWQeRXF.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Major_Charm_Potion_IJLAUlQymbSjzsri.json b/src/packs/items/consumables/consumable_Major_Charm_Potion_IJLAUlQymbSjzsri.json index c70ff759..c7e22aeb 100644 --- a/src/packs/items/consumables/consumable_Major_Charm_Potion_IJLAUlQymbSjzsri.json +++ b/src/packs/items/consumables/consumable_Major_Charm_Potion_IJLAUlQymbSjzsri.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.presence.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Major_Control_Potion_80s1FLmTLtohZ5GH.json b/src/packs/items/consumables/consumable_Major_Control_Potion_80s1FLmTLtohZ5GH.json index 3f8786d2..1dabf6c6 100644 --- a/src/packs/items/consumables/consumable_Major_Control_Potion_80s1FLmTLtohZ5GH.json +++ b/src/packs/items/consumables/consumable_Major_Control_Potion_80s1FLmTLtohZ5GH.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Major_Enlighten_Potion_SDdv1G2veMLKrxcJ.json b/src/packs/items/consumables/consumable_Major_Enlighten_Potion_SDdv1G2veMLKrxcJ.json index ea3e4ffc..5a9a2d28 100644 --- a/src/packs/items/consumables/consumable_Major_Enlighten_Potion_SDdv1G2veMLKrxcJ.json +++ b/src/packs/items/consumables/consumable_Major_Enlighten_Potion_SDdv1G2veMLKrxcJ.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.knowledge.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Morphing_Clay_f1NHVSIHJJCIOaBl.json b/src/packs/items/consumables/consumable_Morphing_Clay_f1NHVSIHJJCIOaBl.json index b7f44fea..90dd4fdc 100644 --- a/src/packs/items/consumables/consumable_Morphing_Clay_f1NHVSIHJJCIOaBl.json +++ b/src/packs/items/consumables/consumable_Morphing_Clay_f1NHVSIHJJCIOaBl.json @@ -60,6 +60,12 @@ "_id": "rMno0zO5Cbwlu4zn", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "shortRest" diff --git a/src/packs/items/consumables/consumable_Mythic_Dust_Zsh2AvZr8EkGtLyw.json b/src/packs/items/consumables/consumable_Mythic_Dust_Zsh2AvZr8EkGtLyw.json index 596b5ac8..342bf60b 100644 --- a/src/packs/items/consumables/consumable_Mythic_Dust_Zsh2AvZr8EkGtLyw.json +++ b/src/packs/items/consumables/consumable_Mythic_Dust_Zsh2AvZr8EkGtLyw.json @@ -60,15 +60,21 @@ "_id": "L68lFhuWdS3ppDxR", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.magical.dice", - "type": "add", - "value": "1d12", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.magical.dice", + "mode": 2, + "value": "1d12", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/consumables/consumable_Ogre_Musk_qr1bosjFcUfuwq4B.json b/src/packs/items/consumables/consumable_Ogre_Musk_qr1bosjFcUfuwq4B.json index 6e384417..59e51e80 100644 --- a/src/packs/items/consumables/consumable_Ogre_Musk_qr1bosjFcUfuwq4B.json +++ b/src/packs/items/consumables/consumable_Ogre_Musk_qr1bosjFcUfuwq4B.json @@ -60,6 +60,12 @@ "_id": "n73d0J4oMCBIPWHN", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "shortRest" diff --git a/src/packs/items/consumables/consumable_Potion_of_Stability_dvL8oaxpEF6jKvYN.json b/src/packs/items/consumables/consumable_Potion_of_Stability_dvL8oaxpEF6jKvYN.json index ecfc34ea..ddff33f0 100644 --- a/src/packs/items/consumables/consumable_Potion_of_Stability_dvL8oaxpEF6jKvYN.json +++ b/src/packs/items/consumables/consumable_Potion_of_Stability_dvL8oaxpEF6jKvYN.json @@ -63,13 +63,13 @@ "changes": [ { "key": "system.bonuses.rest.shortRest.shortMoves", - "type": "add", + "mode": 2, "value": "1", "priority": null }, { "key": "system.bonuses.rest.longRest.longMoves", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Redthorn_Saliva_s2Exl2XFuoOhtIov.json b/src/packs/items/consumables/consumable_Redthorn_Saliva_s2Exl2XFuoOhtIov.json index ec8e6d5a..69edf2df 100644 --- a/src/packs/items/consumables/consumable_Redthorn_Saliva_s2Exl2XFuoOhtIov.json +++ b/src/packs/items/consumables/consumable_Redthorn_Saliva_s2Exl2XFuoOhtIov.json @@ -60,15 +60,21 @@ "_id": "tWf00ezdpxQQLuZ1", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.dice", - "type": "add", - "value": "1d12", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.dice", + "mode": 2, + "value": "1d12", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/consumables/consumable_Stride_Potion_lNtcrkgFGOJNaroE.json b/src/packs/items/consumables/consumable_Stride_Potion_lNtcrkgFGOJNaroE.json index c13af610..76d43d33 100644 --- a/src/packs/items/consumables/consumable_Stride_Potion_lNtcrkgFGOJNaroE.json +++ b/src/packs/items/consumables/consumable_Stride_Potion_lNtcrkgFGOJNaroE.json @@ -63,7 +63,7 @@ "changes": [ { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/consumables/consumable_Vial_of_Moondrip_VqEX5YwK5oL3r1t6.json b/src/packs/items/consumables/consumable_Vial_of_Moondrip_VqEX5YwK5oL3r1t6.json index b81a2604..3fc572fd 100644 --- a/src/packs/items/consumables/consumable_Vial_of_Moondrip_VqEX5YwK5oL3r1t6.json +++ b/src/packs/items/consumables/consumable_Vial_of_Moondrip_VqEX5YwK5oL3r1t6.json @@ -60,6 +60,12 @@ "_id": "548KAUPcSbQLsivh", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "shortRest" diff --git a/src/packs/items/consumables/consumable_Wingsprout_n10vozlmosVR6lo4.json b/src/packs/items/consumables/consumable_Wingsprout_n10vozlmosVR6lo4.json index e0ea5ea5..1bdd4bc0 100644 --- a/src/packs/items/consumables/consumable_Wingsprout_n10vozlmosVR6lo4.json +++ b/src/packs/items/consumables/consumable_Wingsprout_n10vozlmosVR6lo4.json @@ -60,8 +60,14 @@ "_id": "80F8gAn7ejhhNL7R", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/loot/loot_Arcane_Prism_Mn1eo2Mdtu1kzyxB.json b/src/packs/items/loot/loot_Arcane_Prism_Mn1eo2Mdtu1kzyxB.json index 2a6729d2..016c7262 100644 --- a/src/packs/items/loot/loot_Arcane_Prism_Mn1eo2Mdtu1kzyxB.json +++ b/src/packs/items/loot/loot_Arcane_Prism_Mn1eo2Mdtu1kzyxB.json @@ -53,7 +53,7 @@ "changes": [ { "key": "system.bonuses.roll.spellcast.bonus", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/loot/loot_Attune_Relic_vK6bKyQTT3m8WvMh.json b/src/packs/items/loot/loot_Attune_Relic_vK6bKyQTT3m8WvMh.json index 60afc84c..abed8a55 100644 --- a/src/packs/items/loot/loot_Attune_Relic_vK6bKyQTT3m8WvMh.json +++ b/src/packs/items/loot/loot_Attune_Relic_vK6bKyQTT3m8WvMh.json @@ -23,7 +23,7 @@ "changes": [ { "key": "system.traits.instinct.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/loot/loot_Bag_of_Ficklesand_v758j4FwNVAurhYK.json b/src/packs/items/loot/loot_Bag_of_Ficklesand_v758j4FwNVAurhYK.json index 44565535..2cb80d86 100644 --- a/src/packs/items/loot/loot_Bag_of_Ficklesand_v758j4FwNVAurhYK.json +++ b/src/packs/items/loot/loot_Bag_of_Ficklesand_v758j4FwNVAurhYK.json @@ -74,8 +74,14 @@ "_id": "Ouq3xWzj5rf6olVs", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/loot/loot_Bolster_Relic_m3EpxlDgxn2tCDDR.json b/src/packs/items/loot/loot_Bolster_Relic_m3EpxlDgxn2tCDDR.json index 2d7c360e..d45af6dc 100644 --- a/src/packs/items/loot/loot_Bolster_Relic_m3EpxlDgxn2tCDDR.json +++ b/src/packs/items/loot/loot_Bolster_Relic_m3EpxlDgxn2tCDDR.json @@ -23,7 +23,7 @@ "changes": [ { "key": "system.traits.strength.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/loot/loot_Charging_Quiver_gsUDP90d4SRtLEUn.json b/src/packs/items/loot/loot_Charging_Quiver_gsUDP90d4SRtLEUn.json index a31a4e93..ee7d7a10 100644 --- a/src/packs/items/loot/loot_Charging_Quiver_gsUDP90d4SRtLEUn.json +++ b/src/packs/items/loot/loot_Charging_Quiver_gsUDP90d4SRtLEUn.json @@ -20,21 +20,27 @@ "_id": "0zebbOsyjkm9IqE6", "img": "icons/weapons/ammunition/arrow-broadhead-glowing-orange.webp", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "@system.tier", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "@system.tier", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "@system.tier", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "@system.tier", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/items/loot/loot_Charm_Relic_9P9jqGSlxVCbTdLe.json b/src/packs/items/loot/loot_Charm_Relic_9P9jqGSlxVCbTdLe.json index 514df12b..f3313941 100644 --- a/src/packs/items/loot/loot_Charm_Relic_9P9jqGSlxVCbTdLe.json +++ b/src/packs/items/loot/loot_Charm_Relic_9P9jqGSlxVCbTdLe.json @@ -23,7 +23,7 @@ "changes": [ { "key": "system.traits.presence.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/loot/loot_Control_Relic_QPGBDItjrRhXU6iJ.json b/src/packs/items/loot/loot_Control_Relic_QPGBDItjrRhXU6iJ.json index 5df7b228..254f4017 100644 --- a/src/packs/items/loot/loot_Control_Relic_QPGBDItjrRhXU6iJ.json +++ b/src/packs/items/loot/loot_Control_Relic_QPGBDItjrRhXU6iJ.json @@ -23,7 +23,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/loot/loot_Enlighten_Relic_vSGx1f9SYUiA29L3.json b/src/packs/items/loot/loot_Enlighten_Relic_vSGx1f9SYUiA29L3.json index a99e6b9b..a6ca361e 100644 --- a/src/packs/items/loot/loot_Enlighten_Relic_vSGx1f9SYUiA29L3.json +++ b/src/packs/items/loot/loot_Enlighten_Relic_vSGx1f9SYUiA29L3.json @@ -23,7 +23,7 @@ "changes": [ { "key": "system.traits.knowledge.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/loot/loot_Glamour_Stone_Pj17cvdJ1XG1jv6I.json b/src/packs/items/loot/loot_Glamour_Stone_Pj17cvdJ1XG1jv6I.json index 0521ccd8..424d7a04 100644 --- a/src/packs/items/loot/loot_Glamour_Stone_Pj17cvdJ1XG1jv6I.json +++ b/src/packs/items/loot/loot_Glamour_Stone_Pj17cvdJ1XG1jv6I.json @@ -57,8 +57,14 @@ "_id": "K5SB6tfuDkdVaQYe", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/loot/loot_Piercing_Arrows_I63LTFD6GXHgyGpR.json b/src/packs/items/loot/loot_Piercing_Arrows_I63LTFD6GXHgyGpR.json index 3d0493c4..b87bd1b0 100644 --- a/src/packs/items/loot/loot_Piercing_Arrows_I63LTFD6GXHgyGpR.json +++ b/src/packs/items/loot/loot_Piercing_Arrows_I63LTFD6GXHgyGpR.json @@ -43,21 +43,27 @@ "_id": "lRfqfbwlfxzPbE6U", "img": "icons/weapons/ammunition/arrow-broadhead-glowing-orange.webp", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "@system.proficiency", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "@system.proficiency", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "@system.proficiency", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "@system.proficiency", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/items/loot/loot_Ring_of_Resistance_aUqRifqR5JXXa1dN.json b/src/packs/items/loot/loot_Ring_of_Resistance_aUqRifqR5JXXa1dN.json index 6db909b2..3668b6b7 100644 --- a/src/packs/items/loot/loot_Ring_of_Resistance_aUqRifqR5JXXa1dN.json +++ b/src/packs/items/loot/loot_Ring_of_Resistance_aUqRifqR5JXXa1dN.json @@ -50,21 +50,27 @@ "_id": "Sj7uGf560T7u4rlX", "type": "base", "system": { - "changes": [ - { - "key": "system.resistance.magical.resistance", - "type": "override", - "value": "1", - "priority": null - }, - { - "key": "system.resistance.physical.resistance", - "type": "override", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.resistance.magical.resistance", + "mode": 5, + "value": "1", + "priority": null + }, + { + "key": "system.resistance.physical.resistance", + "mode": 5, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/loot/loot_Ring_of_Silence_K1ysGnTpNyxPu5Au.json b/src/packs/items/loot/loot_Ring_of_Silence_K1ysGnTpNyxPu5Au.json index b44419e6..3521098d 100644 --- a/src/packs/items/loot/loot_Ring_of_Silence_K1ysGnTpNyxPu5Au.json +++ b/src/packs/items/loot/loot_Ring_of_Silence_K1ysGnTpNyxPu5Au.json @@ -57,8 +57,14 @@ "_id": "9JSLRu7amQ4iuIO7", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/items/loot/loot_Stride_Relic_FfJISMzYATaPQPLc.json b/src/packs/items/loot/loot_Stride_Relic_FfJISMzYATaPQPLc.json index 50917309..703d8439 100644 --- a/src/packs/items/loot/loot_Stride_Relic_FfJISMzYATaPQPLc.json +++ b/src/packs/items/loot/loot_Stride_Relic_FfJISMzYATaPQPLc.json @@ -23,7 +23,7 @@ "changes": [ { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "1", "priority": null } diff --git a/src/packs/items/weapons/weapon_Aantari_Bow_ijodu5yNBoMxpkHV.json b/src/packs/items/weapons/weapon_Aantari_Bow_ijodu5yNBoMxpkHV.json index 195d3ef9..7b51d436 100644 --- a/src/packs/items/weapons/weapon_Aantari_Bow_ijodu5yNBoMxpkHV.json +++ b/src/packs/items/weapons/weapon_Aantari_Bow_ijodu5yNBoMxpkHV.json @@ -113,16 +113,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "nRNnU57i7RMJoklC", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Advanced_Arcane_Frame_Wheelchair_la3sAWgnvadc4NvP.json b/src/packs/items/weapons/weapon_Advanced_Arcane_Frame_Wheelchair_la3sAWgnvadc4NvP.json index 042d922a..a727bcd5 100644 --- a/src/packs/items/weapons/weapon_Advanced_Arcane_Frame_Wheelchair_la3sAWgnvadc4NvP.json +++ b/src/packs/items/weapons/weapon_Advanced_Arcane_Frame_Wheelchair_la3sAWgnvadc4NvP.json @@ -112,16 +112,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "VnV5X9MBMabhz47b", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Advanced_Broadsword_WtQAGz0TUgz8Xg70.json b/src/packs/items/weapons/weapon_Advanced_Broadsword_WtQAGz0TUgz8Xg70.json index f7e1f872..4581c52f 100644 --- a/src/packs/items/weapons/weapon_Advanced_Broadsword_WtQAGz0TUgz8Xg70.json +++ b/src/packs/items/weapons/weapon_Advanced_Broadsword_WtQAGz0TUgz8Xg70.json @@ -113,16 +113,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "wu2AmDvgeWI3hmRQ", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Advanced_Greatsword_MAC6YWTo4lzSotQc.json b/src/packs/items/weapons/weapon_Advanced_Greatsword_MAC6YWTo4lzSotQc.json index 39d1b6f2..9e04bf7a 100644 --- a/src/packs/items/weapons/weapon_Advanced_Greatsword_MAC6YWTo4lzSotQc.json +++ b/src/packs/items/weapons/weapon_Advanced_Greatsword_MAC6YWTo4lzSotQc.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Advanced_Halberd_C8gQn7onAc9wsrCs.json b/src/packs/items/weapons/weapon_Advanced_Halberd_C8gQn7onAc9wsrCs.json index 92841972..6c11724c 100644 --- a/src/packs/items/weapons/weapon_Advanced_Halberd_C8gQn7onAc9wsrCs.json +++ b/src/packs/items/weapons/weapon_Advanced_Halberd_C8gQn7onAc9wsrCs.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Advanced_Heavy_Frame_Wheelchair_eT2Qwb0RdrLX2hH1.json b/src/packs/items/weapons/weapon_Advanced_Heavy_Frame_Wheelchair_eT2Qwb0RdrLX2hH1.json index 1e9a6441..7f5bb9c7 100644 --- a/src/packs/items/weapons/weapon_Advanced_Heavy_Frame_Wheelchair_eT2Qwb0RdrLX2hH1.json +++ b/src/packs/items/weapons/weapon_Advanced_Heavy_Frame_Wheelchair_eT2Qwb0RdrLX2hH1.json @@ -115,7 +115,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Advanced_Longbow_M5CywMAyPKGgebsJ.json b/src/packs/items/weapons/weapon_Advanced_Longbow_M5CywMAyPKGgebsJ.json index 4bf1375d..14327a8c 100644 --- a/src/packs/items/weapons/weapon_Advanced_Longbow_M5CywMAyPKGgebsJ.json +++ b/src/packs/items/weapons/weapon_Advanced_Longbow_M5CywMAyPKGgebsJ.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Advanced_Shortsword_p3nz5CaGUoyuGVg0.json b/src/packs/items/weapons/weapon_Advanced_Shortsword_p3nz5CaGUoyuGVg0.json index 2a24d0cc..dd48db21 100644 --- a/src/packs/items/weapons/weapon_Advanced_Shortsword_p3nz5CaGUoyuGVg0.json +++ b/src/packs/items/weapons/weapon_Advanced_Shortsword_p3nz5CaGUoyuGVg0.json @@ -113,20 +113,20 @@ "name": "Paired", "description": "Add this Secondary Weapon's tier + 1 to your primary weapon against targets within Melee range", "img": "icons/skills/melee/weapons-crossed-swords-yellow-teal.webp", + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "ITEM.@system.tier + 1" + } + ], "system": { "rangeDependence": { "enabled": true, "range": "melee", "target": "hostile", "type": "withinRange" - }, - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "ITEM.@system.tier + 1" - } - ] + } }, "_id": "zQMaG3JcUWJR9k2L", "type": "base", diff --git a/src/packs/items/weapons/weapon_Advanced_Small_Dagger_0thN0BpN05KT8Avx.json b/src/packs/items/weapons/weapon_Advanced_Small_Dagger_0thN0BpN05KT8Avx.json index 2e313ace..a63789f3 100644 --- a/src/packs/items/weapons/weapon_Advanced_Small_Dagger_0thN0BpN05KT8Avx.json +++ b/src/packs/items/weapons/weapon_Advanced_Small_Dagger_0thN0BpN05KT8Avx.json @@ -113,20 +113,20 @@ "name": "Paired", "description": "Add this Secondary Weapon's tier + 1 to your primary weapon against targets within Melee range", "img": "icons/skills/melee/weapons-crossed-swords-yellow-teal.webp", + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "ITEM.@system.tier + 1" + } + ], "system": { "rangeDependence": { "enabled": true, - "type": "withinRange", + "range": "melee", "target": "hostile", - "range": "melee" - }, - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "ITEM.@system.tier + 1" - } - ] + "type": "withinRange" + } }, "_id": "6tJmTBsumbPmEwkY", "type": "base", diff --git a/src/packs/items/weapons/weapon_Advanced_Warhammer_8Lipw3RRKDgBVP0p.json b/src/packs/items/weapons/weapon_Advanced_Warhammer_8Lipw3RRKDgBVP0p.json index 8770ef57..bb142281 100644 --- a/src/packs/items/weapons/weapon_Advanced_Warhammer_8Lipw3RRKDgBVP0p.json +++ b/src/packs/items/weapons/weapon_Advanced_Warhammer_8Lipw3RRKDgBVP0p.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Arcane_Frame_Wheelchair_XRChepscgr75Uug7.json b/src/packs/items/weapons/weapon_Arcane_Frame_Wheelchair_XRChepscgr75Uug7.json index cdb26ca6..6959fb30 100644 --- a/src/packs/items/weapons/weapon_Arcane_Frame_Wheelchair_XRChepscgr75Uug7.json +++ b/src/packs/items/weapons/weapon_Arcane_Frame_Wheelchair_XRChepscgr75Uug7.json @@ -113,16 +113,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "dXHsy9qr5FWZqsVq", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Black_Powder_Revolver_AokqTusPzn0hghkE.json b/src/packs/items/weapons/weapon_Black_Powder_Revolver_AokqTusPzn0hghkE.json index f8b254f3..34371c2b 100644 --- a/src/packs/items/weapons/weapon_Black_Powder_Revolver_AokqTusPzn0hghkE.json +++ b/src/packs/items/weapons/weapon_Black_Powder_Revolver_AokqTusPzn0hghkE.json @@ -128,15 +128,6 @@ "source": "Daggerheart SRD", "page": 48, "artist": "" - }, - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "recovery": null, - "progression": "decreasing", - "dieFaces": "d4", - "icon": "fa-solid fa-gun" } }, "effects": [], diff --git a/src/packs/items/weapons/weapon_Blunderbuss_SLFrK0WmldPo0shz.json b/src/packs/items/weapons/weapon_Blunderbuss_SLFrK0WmldPo0shz.json index 570d8856..9b2f455a 100644 --- a/src/packs/items/weapons/weapon_Blunderbuss_SLFrK0WmldPo0shz.json +++ b/src/packs/items/weapons/weapon_Blunderbuss_SLFrK0WmldPo0shz.json @@ -128,15 +128,6 @@ "source": "Daggerheart SRD", "page": 46, "artist": "" - }, - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "recovery": null, - "progression": "decreasing", - "dieFaces": "d4", - "icon": "fa-solid fa-gun" } }, "effects": [], diff --git a/src/packs/items/weapons/weapon_Bravesword_QZrWAkprA2tL2MOI.json b/src/packs/items/weapons/weapon_Bravesword_QZrWAkprA2tL2MOI.json index 281ec542..412a7083 100644 --- a/src/packs/items/weapons/weapon_Bravesword_QZrWAkprA2tL2MOI.json +++ b/src/packs/items/weapons/weapon_Bravesword_QZrWAkprA2tL2MOI.json @@ -116,12 +116,12 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" }, { "key": "system.damageThresholds.severe", - "type": "add", + "mode": 2, "value": "ITEM.@system.tier" } ], diff --git a/src/packs/items/weapons/weapon_Broadsword_1cwWNt4sqlgA8gCT.json b/src/packs/items/weapons/weapon_Broadsword_1cwWNt4sqlgA8gCT.json index 1bed724d..87c6f7e8 100644 --- a/src/packs/items/weapons/weapon_Broadsword_1cwWNt4sqlgA8gCT.json +++ b/src/packs/items/weapons/weapon_Broadsword_1cwWNt4sqlgA8gCT.json @@ -113,16 +113,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "mqcpj2cFAprf2AmY", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Buckler_EmFTp9wzT6MHSaNz.json b/src/packs/items/weapons/weapon_Buckler_EmFTp9wzT6MHSaNz.json index 911dd4c3..be147888 100644 --- a/src/packs/items/weapons/weapon_Buckler_EmFTp9wzT6MHSaNz.json +++ b/src/packs/items/weapons/weapon_Buckler_EmFTp9wzT6MHSaNz.json @@ -154,7 +154,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "@system.armorScore", "priority": 21 } diff --git a/src/packs/items/weapons/weapon_Curved_Dagger_Fk69R40svV0kanZD.json b/src/packs/items/weapons/weapon_Curved_Dagger_Fk69R40svV0kanZD.json index ddaa12d0..1af2c372 100644 --- a/src/packs/items/weapons/weapon_Curved_Dagger_Fk69R40svV0kanZD.json +++ b/src/packs/items/weapons/weapon_Curved_Dagger_Fk69R40svV0kanZD.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.rules.damage.flipMinDiceValue", - "type": "override", + "mode": 5, "value": "1" } ], diff --git a/src/packs/items/weapons/weapon_Finehair_Bow_ykF3jouxHZ6YR8Bg.json b/src/packs/items/weapons/weapon_Finehair_Bow_ykF3jouxHZ6YR8Bg.json index 4523ad41..d1bd58b5 100644 --- a/src/packs/items/weapons/weapon_Finehair_Bow_ykF3jouxHZ6YR8Bg.json +++ b/src/packs/items/weapons/weapon_Finehair_Bow_ykF3jouxHZ6YR8Bg.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.bonuses.roll.primaryWeapon.attack", - "type": "add", + "mode": 2, "value": "1" } ], diff --git a/src/packs/items/weapons/weapon_Flickerfly_Blade_xLJ5RRpUoTRmAC3G.json b/src/packs/items/weapons/weapon_Flickerfly_Blade_xLJ5RRpUoTRmAC3G.json index ffd6531f..acf0cfd6 100644 --- a/src/packs/items/weapons/weapon_Flickerfly_Blade_xLJ5RRpUoTRmAC3G.json +++ b/src/packs/items/weapons/weapon_Flickerfly_Blade_xLJ5RRpUoTRmAC3G.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", + "mode": 2, "value": "@system.traits.agility.value", "priority": 21 } diff --git a/src/packs/items/weapons/weapon_Fusion_Gloves_uK1RhtYAsDeoPNGx.json b/src/packs/items/weapons/weapon_Fusion_Gloves_uK1RhtYAsDeoPNGx.json index e2e61ec7..034ad5cf 100644 --- a/src/packs/items/weapons/weapon_Fusion_Gloves_uK1RhtYAsDeoPNGx.json +++ b/src/packs/items/weapons/weapon_Fusion_Gloves_uK1RhtYAsDeoPNGx.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", + "mode": 2, "value": "@system.levelData.level.current" } ], diff --git a/src/packs/items/weapons/weapon_Gilded_Bow_ctTgFfMbM3YtmsYU.json b/src/packs/items/weapons/weapon_Gilded_Bow_ctTgFfMbM3YtmsYU.json index 0f5b5c71..0147cfdb 100644 --- a/src/packs/items/weapons/weapon_Gilded_Bow_ctTgFfMbM3YtmsYU.json +++ b/src/packs/items/weapons/weapon_Gilded_Bow_ctTgFfMbM3YtmsYU.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.rules.damage.flipMinDiceValue", - "type": "override", + "mode": 5, "value": "1" } ], diff --git a/src/packs/items/weapons/weapon_Greatsword_70ysaFJDREwTgvZa.json b/src/packs/items/weapons/weapon_Greatsword_70ysaFJDREwTgvZa.json index 74aa3cf3..f0e450a4 100644 --- a/src/packs/items/weapons/weapon_Greatsword_70ysaFJDREwTgvZa.json +++ b/src/packs/items/weapons/weapon_Greatsword_70ysaFJDREwTgvZa.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Halberd_qT7FfmauAumOjJoq.json b/src/packs/items/weapons/weapon_Halberd_qT7FfmauAumOjJoq.json index 8d58b29b..5a990da3 100644 --- a/src/packs/items/weapons/weapon_Halberd_qT7FfmauAumOjJoq.json +++ b/src/packs/items/weapons/weapon_Halberd_qT7FfmauAumOjJoq.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Hand_Cannon_MyGz8nd5sieRQ7zl.json b/src/packs/items/weapons/weapon_Hand_Cannon_MyGz8nd5sieRQ7zl.json index f9d54bcd..4967c6e4 100644 --- a/src/packs/items/weapons/weapon_Hand_Cannon_MyGz8nd5sieRQ7zl.json +++ b/src/packs/items/weapons/weapon_Hand_Cannon_MyGz8nd5sieRQ7zl.json @@ -128,15 +128,6 @@ "source": "Daggerheart SRD", "page": 50, "artist": "" - }, - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "recovery": null, - "progression": "decreasing", - "dieFaces": "d4", - "icon": "fa-solid fa-gun" } }, "effects": [], diff --git a/src/packs/items/weapons/weapon_Heavy_Frame_Wheelchair_XjPQjhRCH08VUIbr.json b/src/packs/items/weapons/weapon_Heavy_Frame_Wheelchair_XjPQjhRCH08VUIbr.json index a8187c25..e74ff4aa 100644 --- a/src/packs/items/weapons/weapon_Heavy_Frame_Wheelchair_XjPQjhRCH08VUIbr.json +++ b/src/packs/items/weapons/weapon_Heavy_Frame_Wheelchair_XjPQjhRCH08VUIbr.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Ilmari_s_Rifle_TMrUzVC3KvcHmdt8.json b/src/packs/items/weapons/weapon_Ilmari_s_Rifle_TMrUzVC3KvcHmdt8.json index 512168f5..cddd762a 100644 --- a/src/packs/items/weapons/weapon_Ilmari_s_Rifle_TMrUzVC3KvcHmdt8.json +++ b/src/packs/items/weapons/weapon_Ilmari_s_Rifle_TMrUzVC3KvcHmdt8.json @@ -128,15 +128,6 @@ "source": "Daggerheart SRD", "page": 49, "artist": "" - }, - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "recovery": null, - "progression": "decreasing", - "dieFaces": "d4", - "icon": "fa-solid fa-gun" } }, "effects": [], diff --git a/src/packs/items/weapons/weapon_Improved_Arcane_Frame_Wheelchair_N9P695V5KKlJbAY5.json b/src/packs/items/weapons/weapon_Improved_Arcane_Frame_Wheelchair_N9P695V5KKlJbAY5.json index f7d1a9d3..33f96030 100644 --- a/src/packs/items/weapons/weapon_Improved_Arcane_Frame_Wheelchair_N9P695V5KKlJbAY5.json +++ b/src/packs/items/weapons/weapon_Improved_Arcane_Frame_Wheelchair_N9P695V5KKlJbAY5.json @@ -112,16 +112,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "1f6fFhOLwZrmA6e5", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Improved_Broadsword_OcKeLJxvmdT81VBc.json b/src/packs/items/weapons/weapon_Improved_Broadsword_OcKeLJxvmdT81VBc.json index cd7f62d4..6d6f1921 100644 --- a/src/packs/items/weapons/weapon_Improved_Broadsword_OcKeLJxvmdT81VBc.json +++ b/src/packs/items/weapons/weapon_Improved_Broadsword_OcKeLJxvmdT81VBc.json @@ -113,16 +113,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "228lcQpohdJ3Bbga", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Improved_Greatsword_FPX4ouDrxXiQ5MDf.json b/src/packs/items/weapons/weapon_Improved_Greatsword_FPX4ouDrxXiQ5MDf.json index ec618f0b..60e5dd53 100644 --- a/src/packs/items/weapons/weapon_Improved_Greatsword_FPX4ouDrxXiQ5MDf.json +++ b/src/packs/items/weapons/weapon_Improved_Greatsword_FPX4ouDrxXiQ5MDf.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Improved_Halberd_F9PETfCQGwczBPif.json b/src/packs/items/weapons/weapon_Improved_Halberd_F9PETfCQGwczBPif.json index 79c3a31b..fb5a1dcc 100644 --- a/src/packs/items/weapons/weapon_Improved_Halberd_F9PETfCQGwczBPif.json +++ b/src/packs/items/weapons/weapon_Improved_Halberd_F9PETfCQGwczBPif.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Improved_Heavy_Frame_Wheelchair_L5KeCtrs768PmYWW.json b/src/packs/items/weapons/weapon_Improved_Heavy_Frame_Wheelchair_L5KeCtrs768PmYWW.json index 1443e76f..e65cc221 100644 --- a/src/packs/items/weapons/weapon_Improved_Heavy_Frame_Wheelchair_L5KeCtrs768PmYWW.json +++ b/src/packs/items/weapons/weapon_Improved_Heavy_Frame_Wheelchair_L5KeCtrs768PmYWW.json @@ -115,7 +115,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Improved_Longbow_NacNonjbzyoVMNhI.json b/src/packs/items/weapons/weapon_Improved_Longbow_NacNonjbzyoVMNhI.json index cc083a33..c197f726 100644 --- a/src/packs/items/weapons/weapon_Improved_Longbow_NacNonjbzyoVMNhI.json +++ b/src/packs/items/weapons/weapon_Improved_Longbow_NacNonjbzyoVMNhI.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Improved_Shortsword_rSyBNRwemBVuTo3H.json b/src/packs/items/weapons/weapon_Improved_Shortsword_rSyBNRwemBVuTo3H.json index 498b5dfb..96ecd37f 100644 --- a/src/packs/items/weapons/weapon_Improved_Shortsword_rSyBNRwemBVuTo3H.json +++ b/src/packs/items/weapons/weapon_Improved_Shortsword_rSyBNRwemBVuTo3H.json @@ -113,20 +113,20 @@ "name": "Paired", "description": "Add this Secondary Weapon's tier + 1 to your primary weapon against targets within Melee range", "img": "icons/skills/melee/weapons-crossed-swords-yellow-teal.webp", + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "ITEM.@system.tier + 1" + } + ], "system": { "rangeDependence": { "enabled": true, "range": "melee", "target": "hostile", "type": "withinRange" - }, - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "ITEM.@system.tier + 1" - } - ] + } }, "_id": "UW2fqbhBqvnK1coG", "type": "base", diff --git a/src/packs/items/weapons/weapon_Improved_Small_Dagger_nMuF8ZDZ2aXZVTg6.json b/src/packs/items/weapons/weapon_Improved_Small_Dagger_nMuF8ZDZ2aXZVTg6.json index 01f3fc8e..1553d75d 100644 --- a/src/packs/items/weapons/weapon_Improved_Small_Dagger_nMuF8ZDZ2aXZVTg6.json +++ b/src/packs/items/weapons/weapon_Improved_Small_Dagger_nMuF8ZDZ2aXZVTg6.json @@ -113,20 +113,20 @@ "name": "Paired", "description": "Add this Secondary Weapon's tier + 1 to your primary weapon against targets within Melee range", "img": "icons/skills/melee/weapons-crossed-swords-yellow-teal.webp", + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "ITEM.@system.tier + 1" + } + ], "system": { "rangeDependence": { "enabled": true, - "type": "withinRange", + "range": "melee", "target": "hostile", - "range": "melee" - }, - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "ITEM.@system.tier + 1" - } - ] + "type": "withinRange" + } }, "_id": "PMXG4l85UkXRf41E", "type": "base", diff --git a/src/packs/items/weapons/weapon_Improved_Warhammer_pxaN4ZK4eqKrjtWj.json b/src/packs/items/weapons/weapon_Improved_Warhammer_pxaN4ZK4eqKrjtWj.json index 47b553a6..aa24c4ad 100644 --- a/src/packs/items/weapons/weapon_Improved_Warhammer_pxaN4ZK4eqKrjtWj.json +++ b/src/packs/items/weapons/weapon_Improved_Warhammer_pxaN4ZK4eqKrjtWj.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Keeper_s_Staff_q382JqMkqLaaFLIr.json b/src/packs/items/weapons/weapon_Keeper_s_Staff_q382JqMkqLaaFLIr.json index e72607cb..21fe863b 100644 --- a/src/packs/items/weapons/weapon_Keeper_s_Staff_q382JqMkqLaaFLIr.json +++ b/src/packs/items/weapons/weapon_Keeper_s_Staff_q382JqMkqLaaFLIr.json @@ -113,16 +113,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "LvxPAfrKuRfgubGV", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Legendary_Arcane_Frame_Wheelchair_gA2tiET9VHGhwMoO.json b/src/packs/items/weapons/weapon_Legendary_Arcane_Frame_Wheelchair_gA2tiET9VHGhwMoO.json index 935584a8..f947acac 100644 --- a/src/packs/items/weapons/weapon_Legendary_Arcane_Frame_Wheelchair_gA2tiET9VHGhwMoO.json +++ b/src/packs/items/weapons/weapon_Legendary_Arcane_Frame_Wheelchair_gA2tiET9VHGhwMoO.json @@ -112,16 +112,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "TvsoAiqHCwgtYat1", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Legendary_Broadsword_y3hfTPfZhMognyaJ.json b/src/packs/items/weapons/weapon_Legendary_Broadsword_y3hfTPfZhMognyaJ.json index 4570fa8b..361d0353 100644 --- a/src/packs/items/weapons/weapon_Legendary_Broadsword_y3hfTPfZhMognyaJ.json +++ b/src/packs/items/weapons/weapon_Legendary_Broadsword_y3hfTPfZhMognyaJ.json @@ -113,16 +113,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "ujb6VAqjyXmfnnjy", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Legendary_Greatsword_zMZ46F9VR7zdTxb9.json b/src/packs/items/weapons/weapon_Legendary_Greatsword_zMZ46F9VR7zdTxb9.json index 97464c6b..aa9d2ef0 100644 --- a/src/packs/items/weapons/weapon_Legendary_Greatsword_zMZ46F9VR7zdTxb9.json +++ b/src/packs/items/weapons/weapon_Legendary_Greatsword_zMZ46F9VR7zdTxb9.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Legendary_Halberd_1AuMNiJz96Ez9fur.json b/src/packs/items/weapons/weapon_Legendary_Halberd_1AuMNiJz96Ez9fur.json index 2b411f11..af6b2a07 100644 --- a/src/packs/items/weapons/weapon_Legendary_Halberd_1AuMNiJz96Ez9fur.json +++ b/src/packs/items/weapons/weapon_Legendary_Halberd_1AuMNiJz96Ez9fur.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Legendary_Heavy_Frame_Wheelchair_S6nB0CNlzdU05o5U.json b/src/packs/items/weapons/weapon_Legendary_Heavy_Frame_Wheelchair_S6nB0CNlzdU05o5U.json index 9139a7b0..d8816fc9 100644 --- a/src/packs/items/weapons/weapon_Legendary_Heavy_Frame_Wheelchair_S6nB0CNlzdU05o5U.json +++ b/src/packs/items/weapons/weapon_Legendary_Heavy_Frame_Wheelchair_S6nB0CNlzdU05o5U.json @@ -115,7 +115,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Legendary_Longbow_Utt1GpoH1fhaTOtN.json b/src/packs/items/weapons/weapon_Legendary_Longbow_Utt1GpoH1fhaTOtN.json index e9e95967..bd5ab13b 100644 --- a/src/packs/items/weapons/weapon_Legendary_Longbow_Utt1GpoH1fhaTOtN.json +++ b/src/packs/items/weapons/weapon_Legendary_Longbow_Utt1GpoH1fhaTOtN.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Legendary_Shortsword_dEumq3BIZBk5xYTk.json b/src/packs/items/weapons/weapon_Legendary_Shortsword_dEumq3BIZBk5xYTk.json index c01a6d5e..a2203a1d 100644 --- a/src/packs/items/weapons/weapon_Legendary_Shortsword_dEumq3BIZBk5xYTk.json +++ b/src/packs/items/weapons/weapon_Legendary_Shortsword_dEumq3BIZBk5xYTk.json @@ -113,20 +113,20 @@ "name": "Paired", "description": "Add this Secondary Weapon's tier + 1 to your primary weapon against targets within Melee range", "img": "icons/skills/melee/weapons-crossed-swords-yellow-teal.webp", + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "ITEM.@system.tier + 1" + } + ], "system": { "rangeDependence": { "enabled": true, "range": "melee", "target": "hostile", "type": "withinRange" - }, - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "ITEM.@system.tier + 1" - } - ] + } }, "_id": "ebloMf4gItx38xkZ", "type": "base", diff --git a/src/packs/items/weapons/weapon_Legendary_Small_Dagger_Px3Rh3kIvAqyISxJ.json b/src/packs/items/weapons/weapon_Legendary_Small_Dagger_Px3Rh3kIvAqyISxJ.json index 42a977f6..cf63bde2 100644 --- a/src/packs/items/weapons/weapon_Legendary_Small_Dagger_Px3Rh3kIvAqyISxJ.json +++ b/src/packs/items/weapons/weapon_Legendary_Small_Dagger_Px3Rh3kIvAqyISxJ.json @@ -113,20 +113,20 @@ "name": "Paired", "description": "Add this Secondary Weapon's tier + 1 to your primary weapon against targets within Melee range", "img": "icons/skills/melee/weapons-crossed-swords-yellow-teal.webp", + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "ITEM.@system.tier + 1" + } + ], "system": { "rangeDependence": { "enabled": true, - "type": "withinRange", + "range": "melee", "target": "hostile", - "range": "melee" - }, - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "ITEM.@system.tier + 1" - } - ] + "type": "withinRange" + } }, "_id": "WAqE3sZFkTefglDq", "type": "base", diff --git a/src/packs/items/weapons/weapon_Legendary_Warhammer_W9ymfEDck2icfvla.json b/src/packs/items/weapons/weapon_Legendary_Warhammer_W9ymfEDck2icfvla.json index 91d26e71..562122d2 100644 --- a/src/packs/items/weapons/weapon_Legendary_Warhammer_W9ymfEDck2icfvla.json +++ b/src/packs/items/weapons/weapon_Legendary_Warhammer_W9ymfEDck2icfvla.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Longbow_YfVs6Se903az4Yet.json b/src/packs/items/weapons/weapon_Longbow_YfVs6Se903az4Yet.json index f2995cb5..43af46ab 100644 --- a/src/packs/items/weapons/weapon_Longbow_YfVs6Se903az4Yet.json +++ b/src/packs/items/weapons/weapon_Longbow_YfVs6Se903az4Yet.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.traits.finesse.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Magus_Revolver_jGykNGQiKm63tCiE.json b/src/packs/items/weapons/weapon_Magus_Revolver_jGykNGQiKm63tCiE.json index fd3e86d3..9dbbb1c1 100644 --- a/src/packs/items/weapons/weapon_Magus_Revolver_jGykNGQiKm63tCiE.json +++ b/src/packs/items/weapons/weapon_Magus_Revolver_jGykNGQiKm63tCiE.json @@ -128,15 +128,6 @@ "source": "Daggerheart SRD", "page": 51, "artist": "" - }, - "resource": { - "type": "simple", - "value": 1, - "max": "1", - "recovery": null, - "progression": "decreasing", - "dieFaces": "d4", - "icon": "fa-solid fa-gun" } }, "effects": [], diff --git a/src/packs/items/weapons/weapon_Midas_Scythe_BdLfy5i488VZgkjP.json b/src/packs/items/weapons/weapon_Midas_Scythe_BdLfy5i488VZgkjP.json index 143d4910..57fe2367 100644 --- a/src/packs/items/weapons/weapon_Midas_Scythe_BdLfy5i488VZgkjP.json +++ b/src/packs/items/weapons/weapon_Midas_Scythe_BdLfy5i488VZgkjP.json @@ -145,7 +145,7 @@ "changes": [ { "key": "system.proficiency", - "type": "add", + "mode": 2, "value": "1" } ], diff --git a/src/packs/items/weapons/weapon_Powered_Gauntlet_bW3xw5S9DbaLCN3E.json b/src/packs/items/weapons/weapon_Powered_Gauntlet_bW3xw5S9DbaLCN3E.json index 9ba6f1b1..3c4ebd1c 100644 --- a/src/packs/items/weapons/weapon_Powered_Gauntlet_bW3xw5S9DbaLCN3E.json +++ b/src/packs/items/weapons/weapon_Powered_Gauntlet_bW3xw5S9DbaLCN3E.json @@ -152,7 +152,7 @@ "changes": [ { "key": "system.proficiency", - "type": "add", + "mode": 2, "value": "1" } ], diff --git a/src/packs/items/weapons/weapon_Shortsword_cjGZpXCoshEqi1FI.json b/src/packs/items/weapons/weapon_Shortsword_cjGZpXCoshEqi1FI.json index e8d49d15..0ea874f8 100644 --- a/src/packs/items/weapons/weapon_Shortsword_cjGZpXCoshEqi1FI.json +++ b/src/packs/items/weapons/weapon_Shortsword_cjGZpXCoshEqi1FI.json @@ -113,21 +113,21 @@ "name": "Paired", "description": "Add this Secondary Weapon's tier + 1 to your primary weapon against targets within Melee range", "img": "icons/skills/melee/weapons-crossed-swords-yellow-teal.webp", + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "ITEM.@system.tier + 1", + "priority": null + } + ], "system": { "rangeDependence": { "enabled": true, "range": "melee", "target": "hostile", "type": "withinRange" - }, - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "ITEM.@system.tier + 1", - "priority": null - } - ] + } }, "_id": "djNtNpasgNDRP8Dd", "type": "base", diff --git a/src/packs/items/weapons/weapon_Sledge_Axe_OxsEmffWriiQmqJK.json b/src/packs/items/weapons/weapon_Sledge_Axe_OxsEmffWriiQmqJK.json index 3e43c85a..d0230362 100644 --- a/src/packs/items/weapons/weapon_Sledge_Axe_OxsEmffWriiQmqJK.json +++ b/src/packs/items/weapons/weapon_Sledge_Axe_OxsEmffWriiQmqJK.json @@ -171,7 +171,7 @@ "changes": [ { "key": "system.traits.agility.value", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/items/weapons/weapon_Small_Dagger_wKklDxs5nkzILNp4.json b/src/packs/items/weapons/weapon_Small_Dagger_wKklDxs5nkzILNp4.json index 184b1ff0..058d138e 100644 --- a/src/packs/items/weapons/weapon_Small_Dagger_wKklDxs5nkzILNp4.json +++ b/src/packs/items/weapons/weapon_Small_Dagger_wKklDxs5nkzILNp4.json @@ -113,20 +113,20 @@ "name": "Paired", "description": "Add this Secondary Weapon's tier + 1 to your primary weapon against targets within Melee range", "img": "icons/skills/melee/weapons-crossed-swords-yellow-teal.webp", + "changes": [ + { + "key": "system.bonuses.damage.primaryWeapon.bonus", + "mode": 2, + "value": "ITEM.@system.tier + 1" + } + ], "system": { "rangeDependence": { "enabled": true, - "type": "withinRange", + "range": "melee", "target": "hostile", - "range": "melee" - }, - "changes": [ - { - "key": "system.bonuses.damage.primaryWeapon.bonus", - "type": "add", - "value": "ITEM.@system.tier + 1" - } - ] + "type": "withinRange" + } }, "_id": "HKh73AHxImdgxgTg", "type": "base", diff --git a/src/packs/items/weapons/weapon_Thistlebow_I1nDGpulg29GpWOW.json b/src/packs/items/weapons/weapon_Thistlebow_I1nDGpulg29GpWOW.json index 4cd9ad55..18f635eb 100644 --- a/src/packs/items/weapons/weapon_Thistlebow_I1nDGpulg29GpWOW.json +++ b/src/packs/items/weapons/weapon_Thistlebow_I1nDGpulg29GpWOW.json @@ -113,16 +113,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "G9mMGxBSexwjWTYV", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Wand_of_Enthrallment_tP6vmnrmTq2h5sj7.json b/src/packs/items/weapons/weapon_Wand_of_Enthrallment_tP6vmnrmTq2h5sj7.json index ea13be12..84c7b3f2 100644 --- a/src/packs/items/weapons/weapon_Wand_of_Enthrallment_tP6vmnrmTq2h5sj7.json +++ b/src/packs/items/weapons/weapon_Wand_of_Enthrallment_tP6vmnrmTq2h5sj7.json @@ -152,7 +152,7 @@ "changes": [ { "key": "system.traits.presence.value", - "type": "add", + "mode": 2, "value": "2" } ], diff --git a/src/packs/items/weapons/weapon_War_Scythe_z6yEdFYQJ5IzgTX3.json b/src/packs/items/weapons/weapon_War_Scythe_z6yEdFYQJ5IzgTX3.json index fc893901..0c57dd50 100644 --- a/src/packs/items/weapons/weapon_War_Scythe_z6yEdFYQJ5IzgTX3.json +++ b/src/packs/items/weapons/weapon_War_Scythe_z6yEdFYQJ5IzgTX3.json @@ -113,16 +113,22 @@ "name": "Reliable", "description": "+1 to attack rolls", "img": "icons/skills/melee/strike-sword-slashing-red.webp", + "changes": [ + { + "key": "system.bonuses.roll.primaryWeapon.bonus", + "mode": 2, + "value": "1" + } + ], "_id": "cOYeI9TxHXpDwszu", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.primaryWeapon.bonus", - "type": "add", - "value": "1" - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "disabled": false, "duration": { diff --git a/src/packs/items/weapons/weapon_Warhammer_ZXh1GQahBiODfSTC.json b/src/packs/items/weapons/weapon_Warhammer_ZXh1GQahBiODfSTC.json index 17724919..a94950c7 100644 --- a/src/packs/items/weapons/weapon_Warhammer_ZXh1GQahBiODfSTC.json +++ b/src/packs/items/weapons/weapon_Warhammer_ZXh1GQahBiODfSTC.json @@ -116,7 +116,7 @@ "changes": [ { "key": "system.evasion", - "type": "add", + "mode": 2, "value": "-1" } ], diff --git a/src/packs/subclasses/feature_Act_of_Reprisal_k7vvMJtEcxMWUUrW.json b/src/packs/subclasses/feature_Act_of_Reprisal_k7vvMJtEcxMWUUrW.json index 4c862887..5dee0c1c 100644 --- a/src/packs/subclasses/feature_Act_of_Reprisal_k7vvMJtEcxMWUUrW.json +++ b/src/packs/subclasses/feature_Act_of_Reprisal_k7vvMJtEcxMWUUrW.json @@ -54,6 +54,12 @@ "_id": "9Uo0yOYGn3vandPp", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [], "duration": { "type": "temporary", diff --git a/src/packs/subclasses/feature_Adrenaline_uByM34yQlw38yf1V.json b/src/packs/subclasses/feature_Adrenaline_uByM34yQlw38yf1V.json index 95cb2263..dc25498b 100644 --- a/src/packs/subclasses/feature_Adrenaline_uByM34yQlw38yf1V.json +++ b/src/packs/subclasses/feature_Adrenaline_uByM34yQlw38yf1V.json @@ -25,21 +25,27 @@ "_id": "HMx9uZ54mvMiH95x", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "@system.levelData.level.current", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "@system.levelData.level.current", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "@system.levelData.level.current", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "@system.levelData.level.current", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Advanced_Training_uGcs785h94RMtueH.json b/src/packs/subclasses/feature_Advanced_Training_uGcs785h94RMtueH.json index b551ef50..16a5cd79 100644 --- a/src/packs/subclasses/feature_Advanced_Training_uGcs785h94RMtueH.json +++ b/src/packs/subclasses/feature_Advanced_Training_uGcs785h94RMtueH.json @@ -21,17 +21,23 @@ "name": "Advanced Training", "type": "base", "system": { - "changes": [ - { - "key": "system.companionData.levelupChoices", - "type": "add", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "bKOuMxhB2Jth3j2T", "img": "icons/creatures/mammals/wolf-howl-moon-gray.webp", + "changes": [ + { + "key": "system.companionData.levelupChoices", + "mode": 2, + "value": "2", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Arcane_Charge_yA4MKQ1tbKFiJoDB.json b/src/packs/subclasses/feature_Arcane_Charge_yA4MKQ1tbKFiJoDB.json index e563668d..e92b71ad 100644 --- a/src/packs/subclasses/feature_Arcane_Charge_yA4MKQ1tbKFiJoDB.json +++ b/src/packs/subclasses/feature_Arcane_Charge_yA4MKQ1tbKFiJoDB.json @@ -29,17 +29,23 @@ "name": "Charged", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "+10", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "z49V45ir45HGHOBB", "img": "icons/magic/unholy/strike-hand-glow-pink.webp", + "changes": [ + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "+10", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Ascendant_fefLgx6kcYWusjBb.json b/src/packs/subclasses/feature_Ascendant_fefLgx6kcYWusjBb.json index abdbe271..737930df 100644 --- a/src/packs/subclasses/feature_Ascendant_fefLgx6kcYWusjBb.json +++ b/src/packs/subclasses/feature_Ascendant_fefLgx6kcYWusjBb.json @@ -21,17 +21,23 @@ "name": "Ascendant", "type": "base", "system": { - "changes": [ - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "+4", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "7M8UsvVweRtT3E85", "img": "icons/magic/defensive/shield-barrier-deflect-gold.webp", + "changes": [ + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "+4", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_At_Ease_xPWFvGvtUjIcqgJq.json b/src/packs/subclasses/feature_At_Ease_xPWFvGvtUjIcqgJq.json index f63b0e42..ce628a2f 100644 --- a/src/packs/subclasses/feature_At_Ease_xPWFvGvtUjIcqgJq.json +++ b/src/packs/subclasses/feature_At_Ease_xPWFvGvtUjIcqgJq.json @@ -21,17 +21,23 @@ "name": "At Ease", "type": "base", "system": { - "changes": [ - { - "key": "system.resources.stress.max", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "xbS4Lr3dWpXUCHEi", "img": "icons/magic/holy/meditation-chi-focus-blue.webp", + "changes": [ + { + "key": "system.resources.stress.max", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Battle_Bonded_hWsKyed1vfILg0I8.json b/src/packs/subclasses/feature_Battle_Bonded_hWsKyed1vfILg0I8.json index 9f68639f..578be0a3 100644 --- a/src/packs/subclasses/feature_Battle_Bonded_hWsKyed1vfILg0I8.json +++ b/src/packs/subclasses/feature_Battle_Bonded_hWsKyed1vfILg0I8.json @@ -21,6 +21,12 @@ "name": "Battle Bonded", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.evasion", diff --git a/src/packs/subclasses/feature_Battlemage_Y9eGMewnFZgPvX0M.json b/src/packs/subclasses/feature_Battlemage_Y9eGMewnFZgPvX0M.json index 36706909..9e389095 100644 --- a/src/packs/subclasses/feature_Battlemage_Y9eGMewnFZgPvX0M.json +++ b/src/packs/subclasses/feature_Battlemage_Y9eGMewnFZgPvX0M.json @@ -21,17 +21,23 @@ "name": "Battlemage", "type": "base", "system": { - "changes": [ - { - "key": "system.resources.hitPoints.max", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "6jjKzvBxAJTHHGoX", "img": "icons/equipment/chest/collar-steel.webp", + "changes": [ + { + "key": "system.resources.hitPoints.max", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Conjure_Shield_oirsCnN66GOlK3Fa.json b/src/packs/subclasses/feature_Conjure_Shield_oirsCnN66GOlK3Fa.json index 8f542544..99b04487 100644 --- a/src/packs/subclasses/feature_Conjure_Shield_oirsCnN66GOlK3Fa.json +++ b/src/packs/subclasses/feature_Conjure_Shield_oirsCnN66GOlK3Fa.json @@ -21,17 +21,23 @@ "name": "Conjure Shield", "type": "base", "system": { - "changes": [ - { - "key": "system.evasion", - "type": "add", - "value": "@system.proficiency", - "priority": 21 - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "0i7GVOvjH6bK5AUM", "img": "icons/magic/defensive/barrier-shield-dome-blue-purple.webp", + "changes": [ + { + "key": "system.evasion", + "mode": 2, + "value": "@system.proficiency", + "priority": 21 + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Elemental_Aura_2JH9NaOh69yN80Gw.json b/src/packs/subclasses/feature_Elemental_Aura_2JH9NaOh69yN80Gw.json index cc6ff640..7a3ebd91 100644 --- a/src/packs/subclasses/feature_Elemental_Aura_2JH9NaOh69yN80Gw.json +++ b/src/packs/subclasses/feature_Elemental_Aura_2JH9NaOh69yN80Gw.json @@ -52,7 +52,7 @@ "includeBase": false }, "target": { - "type": "", + "type": "hostile", "amount": 1 }, "effects": [ @@ -63,23 +63,13 @@ ], "name": "Fire", "img": "icons/magic/fire/barrier-wall-explosion-orange.webp", - "range": "", - "areas": [ - { - "name": "Elemental Aura: Fire", - "type": "attached", - "shape": "emanation", - "size": "close", - "hasHole": false, - "effects": [] - } - ] + "range": "close" }, "xDBLH5TWidvrYF7z": { "type": "effect", "_id": "xDBLH5TWidvrYF7z", "systemPath": "actions", - "description": "Your allies gain a +1 bonus to Strength.", + "description": "When an adversary marks 1 or more Hit Points, they must also mark a Stress.", "chatDisplay": true, "actionType": "action", "cost": [], @@ -88,26 +78,19 @@ "max": "", "recovery": null }, - "effects": [], + "effects": [ + { + "_id": "WRuijfHxmUscAa69", + "onSave": false + } + ], "target": { - "type": "", + "type": "friendly", "amount": null }, "name": "Earth", "img": "icons/magic/control/buff-strength-muscle-damage-red.webp", - "range": "", - "areas": [ - { - "name": "Elemental Aura: Earth", - "type": "attached", - "shape": "emanation", - "size": "close", - "hasHole": true, - "effects": [ - "yvpWNCNobg0LLjey" - ] - } - ] + "range": "close" }, "S4t5HlgxWlHwaBDw": { "type": "effect", @@ -129,22 +112,12 @@ } ], "target": { - "type": "self", + "type": "hostile", "amount": null }, "name": "Water", "img": "icons/magic/water/vortex-water-whirlpool.webp", - "range": "self", - "areas": [ - { - "name": "Elemental Aura: Water", - "type": "attached", - "shape": "emanation", - "size": "close", - "hasHole": false, - "effects": [] - } - ] + "range": "close" }, "hAsKFFewtTqd1gg9": { "type": "attack", @@ -165,10 +138,15 @@ "includeBase": false }, "target": { - "type": "self", + "type": "any", "amount": null }, - "effects": [], + "effects": [ + { + "_id": "mJBA2QTyM9SM5NVS", + "onSave": false + } + ], "roll": { "type": "diceSet", "trait": null, @@ -191,19 +169,7 @@ }, "name": "Air", "img": "icons/magic/air/air-burst-spiral-blue-gray.webp", - "range": "self", - "areas": [ - { - "name": "Elemental Aura: Air", - "type": "attached", - "shape": "emanation", - "size": "close", - "hasHole": false, - "effects": [ - "vnKV5hsO4DVjURAl" - ] - } - ] + "range": "" } }, "originItemType": null, @@ -216,21 +182,73 @@ }, "effects": [ { - "name": "Elemental Aura (Water)", - "img": "icons/magic/water/vortex-water-whirlpool.webp", + "name": "Elemental Aura (Earth)", + "img": "icons/magic/control/buff-strength-muscle-damage-orange.webp", "origin": "Compendium.daggerheart.subclasses.Item.2JH9NaOh69yN80Gw", "transfer": false, - "_id": "H7W52ps5d3UGmaFr", + "_id": "WRuijfHxmUscAa69", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.traits.strength.value", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { - "value": null, - "units": "seconds", - "expiry": null, - "expired": false + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null + }, + "description": "", + "tint": "#ffffff", + "statuses": [], + "sort": 0, + "flags": {}, + "_stats": { + "compendiumSource": null + }, + "_key": "!items.effects!2JH9NaOh69yN80Gw.WRuijfHxmUscAa69" + }, + { + "name": "Elemental Aura (Water)", + "img": "icons/magic/water/vortex-water-whirlpool.webp", + "origin": "Compendium.daggerheart.subclasses.Item.2JH9NaOh69yN80Gw", + "transfer": false, + "_id": "H7W52ps5d3UGmaFr", + "type": "base", + "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } + }, + "changes": [], + "disabled": false, + "duration": { + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null }, "description": "", "tint": "#ffffff", @@ -240,9 +258,6 @@ "_stats": { "compendiumSource": null }, - "start": null, - "showIcon": 1, - "folder": null, "_key": "!items.effects!2JH9NaOh69yN80Gw.H7W52ps5d3UGmaFr" }, { @@ -253,14 +268,23 @@ "_id": "WX5AMEpmUAutB9Hm", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { - "value": null, - "units": "seconds", - "expiry": null, - "expired": false + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null }, "description": "", "tint": "#ffffff", @@ -270,114 +294,43 @@ "_stats": { "compendiumSource": null }, - "start": null, - "showIcon": 1, - "folder": null, "_key": "!items.effects!2JH9NaOh69yN80Gw.WX5AMEpmUAutB9Hm" }, { - "name": "Elemental Aura: Earth", - "disabled": false, - "img": "icons/magic/control/buff-strength-muscle-damage-red.webp", - "description": "Your allies gain a +1 bonus to Strength.", - "transfer": false, - "statuses": [], - "system": { - "changes": [ - { - "key": "system.traits.strength.value", - "type": "add", - "value": 1, - "priority": null, - "phase": "initial" - } - ], - "duration": { - "description": "", - "type": "" - }, - "stacking": null, - "targetDispositions": [ - 1 - ] - }, - "_id": "yvpWNCNobg0LLjey", - "type": "base", - "start": { - "time": 0, - "combat": null, - "combatant": null, - "initiative": null, - "round": null, - "turn": null - }, - "duration": { - "value": null, - "units": "seconds", - "expiry": null, - "expired": false - }, - "origin": null, - "tint": "#ffffff", - "showIcon": 1, - "folder": null, - "sort": 0, - "flags": {}, - "_stats": { - "compendiumSource": null - }, - "_key": "!items.effects!2JH9NaOh69yN80Gw.yvpWNCNobg0LLjey" - }, - { - "name": "Elemental Aura: Air", - "disabled": false, + "name": "Elemental Aura (Air)", "img": "icons/magic/air/air-burst-spiral-blue-gray.webp", - "description": "When you or an ally takes damage from an attack beyond Melee range, reduce the damage by 1d8.", + "origin": "Compendium.daggerheart.subclasses.Item.2JH9NaOh69yN80Gw", "transfer": false, - "statuses": [], + "_id": "mJBA2QTyM9SM5NVS", + "type": "base", "system": { "rangeDependence": { "enabled": false, "type": "withinRange", "target": "hostile", "range": "melee" - }, - "changes": [], - "duration": { - "description": "", - "type": "" - }, - "stacking": null, - "targetDispositions": [ - 1 - ] - }, - "_id": "vnKV5hsO4DVjURAl", - "type": "base", - "start": { - "time": 0, - "combat": null, - "combatant": null, - "initiative": null, - "round": null, - "turn": null + } }, + "changes": [], + "disabled": false, "duration": { - "value": null, - "units": "seconds", - "expiry": null, - "expired": false + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null }, - "origin": null, + "description": "", "tint": "#ffffff", - "showIcon": 1, - "folder": null, + "statuses": [], "sort": 0, "flags": {}, "_stats": { "compendiumSource": null }, - "_key": "!items.effects!2JH9NaOh69yN80Gw.vnKV5hsO4DVjURAl" + "_key": "!items.effects!2JH9NaOh69yN80Gw.mJBA2QTyM9SM5NVS" } ], "sort": 100000, diff --git a/src/packs/subclasses/feature_Elemental_Dominion_EFUJHrkTuyv8uA9l.json b/src/packs/subclasses/feature_Elemental_Dominion_EFUJHrkTuyv8uA9l.json index 0adda762..2476046c 100644 --- a/src/packs/subclasses/feature_Elemental_Dominion_EFUJHrkTuyv8uA9l.json +++ b/src/packs/subclasses/feature_Elemental_Dominion_EFUJHrkTuyv8uA9l.json @@ -141,15 +141,21 @@ "_id": "FoBFRSXRfGa1zkiX", "type": "base", "system": { - "changes": [ - { - "key": "system.proficiency", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + } }, + "changes": [ + { + "key": "system.proficiency", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -178,6 +184,12 @@ "_id": "bGwFZZT4juuaIRmZ", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "veryFar" + }, "changes": [], "duration": { "type": "temporary" @@ -220,15 +232,21 @@ "_id": "edF2zvvlcGf54r2n", "type": "base", "system": { - "changes": [ - { - "key": "system.evasion", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + } }, + "changes": [ + { + "key": "system.evasion", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -257,8 +275,14 @@ "_id": "p5FoUb4JKQFP405d", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Elemental_Incarnation_f37TTgCc0Q3Ih1A1.json b/src/packs/subclasses/feature_Elemental_Incarnation_f37TTgCc0Q3Ih1A1.json index 87150aa0..45ffde60 100644 --- a/src/packs/subclasses/feature_Elemental_Incarnation_f37TTgCc0Q3Ih1A1.json +++ b/src/packs/subclasses/feature_Elemental_Incarnation_f37TTgCc0Q3Ih1A1.json @@ -243,21 +243,27 @@ "_id": "7xyUtUbBk5jbNnqY", "type": "base", "system": { - "changes": [ - { - "key": "system.damageThresholds.major", - "type": "add", - "value": "@system.proficiency", - "priority": 21 - }, - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "@system.proficiency", - "priority": 21 - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + } }, + "changes": [ + { + "key": "system.damageThresholds.major", + "mode": 2, + "value": "@system.proficiency", + "priority": 21 + }, + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "@system.proficiency", + "priority": 21 + } + ], "disabled": false, "duration": { "startTime": null, @@ -286,15 +292,21 @@ "_id": "3ck6CeapLxQVjE2W", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Advantage on Agility Rolls", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Advantage on Agility Rolls", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -323,8 +335,14 @@ "_id": "Jy6dpEbzkZ2eRDf5", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, @@ -353,8 +371,14 @@ "_id": "ANle8tuOEZIevTWv", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Elementalist_dPcqKN5NeDkjB1HW.json b/src/packs/subclasses/feature_Elementalist_dPcqKN5NeDkjB1HW.json index dd989364..8a6b742a 100644 --- a/src/packs/subclasses/feature_Elementalist_dPcqKN5NeDkjB1HW.json +++ b/src/packs/subclasses/feature_Elementalist_dPcqKN5NeDkjB1HW.json @@ -98,15 +98,21 @@ "_id": "EY87mY6ULfIt3XC8", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.roll.action.bonus", - "type": "add", - "value": "+2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + } }, + "changes": [ + { + "key": "system.bonuses.roll.action.bonus", + "mode": 2, + "value": "+2", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, @@ -135,21 +141,27 @@ "_id": "WwibpgaO6Kkks7aZ", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "+3", - "priority": null - }, - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "+3", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + } }, + "changes": [ + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "+3", + "priority": null + }, + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "+3", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Elusive_Predator_Cjtc43V3IzAmfIFG.json b/src/packs/subclasses/feature_Elusive_Predator_Cjtc43V3IzAmfIFG.json index 865268e9..82cd55a0 100644 --- a/src/packs/subclasses/feature_Elusive_Predator_Cjtc43V3IzAmfIFG.json +++ b/src/packs/subclasses/feature_Elusive_Predator_Cjtc43V3IzAmfIFG.json @@ -21,6 +21,12 @@ "name": "Elusive Predator", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.evasion", diff --git a/src/packs/subclasses/feature_Epic_Poetry_eCoEWkWuZPMZ9C6a.json b/src/packs/subclasses/feature_Epic_Poetry_eCoEWkWuZPMZ9C6a.json index 2367f220..0eb3240e 100644 --- a/src/packs/subclasses/feature_Epic_Poetry_eCoEWkWuZPMZ9C6a.json +++ b/src/packs/subclasses/feature_Epic_Poetry_eCoEWkWuZPMZ9C6a.json @@ -20,17 +20,23 @@ "name": "Rally:d10", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.rally", - "type": "override", - "value": "d10", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "RSmscgGyuHJucF6C", "img": "icons/sundries/documents/document-letter-blue.webp", + "changes": [ + { + "key": "system.bonuses.rally", + "mode": 5, + "value": "d10", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Ethereal_Visage_tyGB6wRKjYdIBK1i.json b/src/packs/subclasses/feature_Ethereal_Visage_tyGB6wRKjYdIBK1i.json index 15871e9f..43039d73 100644 --- a/src/packs/subclasses/feature_Ethereal_Visage_tyGB6wRKjYdIBK1i.json +++ b/src/packs/subclasses/feature_Ethereal_Visage_tyGB6wRKjYdIBK1i.json @@ -21,17 +21,23 @@ "name": "Ethereal Visage", "type": "base", "system": { - "changes": [ - { - "key": "system.advantageSources", - "type": "add", - "value": "Presence rolls while flying", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "Ns1DcQ8wo47LhlL3", "img": "icons/magic/holy/saint-glass-portrait-halo.webp", + "changes": [ + { + "key": "system.advantageSources", + "mode": 2, + "value": "Presence rolls while flying", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Expert_Training_iCXtOWBKv1FdKdWz.json b/src/packs/subclasses/feature_Expert_Training_iCXtOWBKv1FdKdWz.json index 0ae1a60d..06819dc9 100644 --- a/src/packs/subclasses/feature_Expert_Training_iCXtOWBKv1FdKdWz.json +++ b/src/packs/subclasses/feature_Expert_Training_iCXtOWBKv1FdKdWz.json @@ -21,17 +21,23 @@ "name": "Expert Training", "type": "base", "system": { - "changes": [ - { - "key": "system.companionData.levelupChoices", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "rknTONvaUDZ2Yz1W", "img": "icons/creatures/mammals/dog-husky-white-blue.webp", + "changes": [ + { + "key": "system.companionData.levelupChoices", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Fleeting_Shadow_EY7Eo6hNGppVL3dR.json b/src/packs/subclasses/feature_Fleeting_Shadow_EY7Eo6hNGppVL3dR.json index fe3f252f..cdebe9b3 100644 --- a/src/packs/subclasses/feature_Fleeting_Shadow_EY7Eo6hNGppVL3dR.json +++ b/src/packs/subclasses/feature_Fleeting_Shadow_EY7Eo6hNGppVL3dR.json @@ -21,17 +21,23 @@ "name": "Fleeting Shadow", "type": "base", "system": { - "changes": [ - { - "key": "system.evasion", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "hsEwoHkNr2qVwm2H", "img": "icons/magic/unholy/projectile-flame-white-purple.webp", + "changes": [ + { + "key": "system.evasion", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Gifted_Performer_99U7YWNCxFZHCiT0.json b/src/packs/subclasses/feature_Gifted_Performer_99U7YWNCxFZHCiT0.json index 47a597e7..f65cd041 100644 --- a/src/packs/subclasses/feature_Gifted_Performer_99U7YWNCxFZHCiT0.json +++ b/src/packs/subclasses/feature_Gifted_Performer_99U7YWNCxFZHCiT0.json @@ -186,6 +186,12 @@ "_id": "FK4IdbxluRErfYor", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "close" + }, "changes": [], "duration": { "type": "temporary" diff --git a/src/packs/subclasses/feature_Iron_Will_7AVRNyBcd1Nffjtn.json b/src/packs/subclasses/feature_Iron_Will_7AVRNyBcd1Nffjtn.json index fa8516ca..bea62e2b 100644 --- a/src/packs/subclasses/feature_Iron_Will_7AVRNyBcd1Nffjtn.json +++ b/src/packs/subclasses/feature_Iron_Will_7AVRNyBcd1Nffjtn.json @@ -21,17 +21,23 @@ "name": "Iron Will", "type": "base", "system": { - "changes": [ - { - "key": "system.rules.damageReduction.maxArmorMarked.value", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "htEDIjCEWYtznpRV", "img": "icons/equipment/chest/breastplate-helmet-metal.webp", + "changes": [ + { + "key": "system.rules.damageReduction.maxArmorMarked.value", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Nemesis_DPKmipNRlSAMs2Cg.json b/src/packs/subclasses/feature_Nemesis_DPKmipNRlSAMs2Cg.json index f3931f8c..3b2d440c 100644 --- a/src/packs/subclasses/feature_Nemesis_DPKmipNRlSAMs2Cg.json +++ b/src/packs/subclasses/feature_Nemesis_DPKmipNRlSAMs2Cg.json @@ -60,8 +60,14 @@ "_id": "JoBFHkhLbm4JyuZm", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Ruthless_Predator_Qny2J3R35bvC0Cey.json b/src/packs/subclasses/feature_Ruthless_Predator_Qny2J3R35bvC0Cey.json index ba92472f..135447fa 100644 --- a/src/packs/subclasses/feature_Ruthless_Predator_Qny2J3R35bvC0Cey.json +++ b/src/packs/subclasses/feature_Ruthless_Predator_Qny2J3R35bvC0Cey.json @@ -60,15 +60,21 @@ "_id": "8BNwCS7ueIQuvn2M", "type": "base", "system": { - "changes": [ - { - "key": "system.proficiency", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + } }, + "changes": [ + { + "key": "system.proficiency", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Shadow_Stepper_hAwTXjhyphiE3aeW.json b/src/packs/subclasses/feature_Shadow_Stepper_hAwTXjhyphiE3aeW.json index fcba875a..7e6fa730 100644 --- a/src/packs/subclasses/feature_Shadow_Stepper_hAwTXjhyphiE3aeW.json +++ b/src/packs/subclasses/feature_Shadow_Stepper_hAwTXjhyphiE3aeW.json @@ -60,8 +60,14 @@ "_id": "RYri0b9z5kq74U5n", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Transcendence_th6HZwEFnVBjUtqm.json b/src/packs/subclasses/feature_Transcendence_th6HZwEFnVBjUtqm.json index 32d8181c..c03c10b5 100644 --- a/src/packs/subclasses/feature_Transcendence_th6HZwEFnVBjUtqm.json +++ b/src/packs/subclasses/feature_Transcendence_th6HZwEFnVBjUtqm.json @@ -53,6 +53,12 @@ "name": "Bonus to Threshold", "type": "base", "system": { + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + }, "changes": [ { "key": "system.damageThresholds.severe", @@ -100,10 +106,16 @@ "name": "Bonus to Trait", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "cTgSmxkTi89y6sbc", "img": "icons/magic/fire/elemental-fire-flying.webp", + "changes": [], "disabled": true, "duration": { "startTime": null, @@ -130,17 +142,23 @@ "name": "Bonus to Proficiency", "type": "base", "system": { - "changes": [ - { - "key": "system.proficiency", - "type": "add", - "value": "+1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "oWf3iXf4dawdbmzd", "img": "icons/magic/fire/elemental-fire-flying.webp", + "changes": [ + { + "key": "system.proficiency", + "mode": 2, + "value": "+1", + "priority": null + } + ], "disabled": true, "duration": { "startTime": null, @@ -167,10 +185,16 @@ "name": "Bonus to Evasion", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, "_id": "2LCF6lSnWFqNiPs5", "img": "icons/magic/fire/elemental-fire-flying.webp", + "changes": [], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Undaunted_866b2jjyzXP8nPRQ.json b/src/packs/subclasses/feature_Undaunted_866b2jjyzXP8nPRQ.json index 792dfd3c..dc5ae2ec 100644 --- a/src/packs/subclasses/feature_Undaunted_866b2jjyzXP8nPRQ.json +++ b/src/packs/subclasses/feature_Undaunted_866b2jjyzXP8nPRQ.json @@ -21,23 +21,29 @@ "name": "Undaunted", "type": "base", "system": { - "changes": [ - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "3", - "priority": null - }, - { - "key": "system.damageThresholds.major", - "type": "add", - "value": "3", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + } }, "_id": "zggFRaerHCj1e5F5", "img": "icons/skills/melee/shield-block-gray-yellow.webp", + "changes": [ + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "3", + "priority": null + }, + { + "key": "system.damageThresholds.major", + "mode": 2, + "value": "3", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Unrelenting_4qP7bNyxVHBmr4Rb.json b/src/packs/subclasses/feature_Unrelenting_4qP7bNyxVHBmr4Rb.json index 287a54c1..dea5e345 100644 --- a/src/packs/subclasses/feature_Unrelenting_4qP7bNyxVHBmr4Rb.json +++ b/src/packs/subclasses/feature_Unrelenting_4qP7bNyxVHBmr4Rb.json @@ -21,23 +21,29 @@ "name": "Unrelenting", "type": "base", "system": { - "changes": [ - { - "key": "system.damageThresholds.major", - "type": "add", - "value": "2", - "priority": null - }, - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "2", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + } }, "_id": "IKb6yutns8EJZ49M", "img": "icons/equipment/shield/heater-steel-crystal-red.webp", + "changes": [ + { + "key": "system.damageThresholds.major", + "mode": 2, + "value": "2", + "priority": null + }, + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "2", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Unwavering_WBiFZaYNoQNhysmN.json b/src/packs/subclasses/feature_Unwavering_WBiFZaYNoQNhysmN.json index dc183879..aa898296 100644 --- a/src/packs/subclasses/feature_Unwavering_WBiFZaYNoQNhysmN.json +++ b/src/packs/subclasses/feature_Unwavering_WBiFZaYNoQNhysmN.json @@ -21,23 +21,29 @@ "name": "Unwavering", "type": "base", "system": { - "changes": [ - { - "key": "system.damageThresholds.major", - "type": "add", - "value": "1", - "priority": null - }, - { - "key": "system.damageThresholds.severe", - "type": "add", - "value": "1", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "any", + "range": "self" + } }, "_id": "3wexvo6La4V46aiX", "img": "icons/equipment/shield/heater-steel-gold.webp", + "changes": [ + { + "key": "system.damageThresholds.major", + "mode": 2, + "value": "1", + "priority": null + }, + { + "key": "system.damageThresholds.severe", + "mode": 2, + "value": "1", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Vanishing_Act_iyIg1VLwO8C6jvFZ.json b/src/packs/subclasses/feature_Vanishing_Act_iyIg1VLwO8C6jvFZ.json index 713578e6..67cfa833 100644 --- a/src/packs/subclasses/feature_Vanishing_Act_iyIg1VLwO8C6jvFZ.json +++ b/src/packs/subclasses/feature_Vanishing_Act_iyIg1VLwO8C6jvFZ.json @@ -60,8 +60,14 @@ "_id": "czrwqq44sEr0uJ8O", "type": "base", "system": { - "changes": [] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [], "disabled": true, "duration": { "startTime": null, diff --git a/src/packs/subclasses/feature_Wings_of_Light_KkQH0tYhagIqe2MT.json b/src/packs/subclasses/feature_Wings_of_Light_KkQH0tYhagIqe2MT.json index b7d8af3f..5b86e348 100644 --- a/src/packs/subclasses/feature_Wings_of_Light_KkQH0tYhagIqe2MT.json +++ b/src/packs/subclasses/feature_Wings_of_Light_KkQH0tYhagIqe2MT.json @@ -94,21 +94,27 @@ "_id": "PfCwuVbKLxhnrm9X", "type": "base", "system": { - "changes": [ - { - "key": "system.bonuses.damage.physical.dice", - "type": "add", - "value": "+1d8", - "priority": null - }, - { - "key": "system.bonuses.damage.magical.dice", - "type": "add", - "value": "+1d8", - "priority": null - } - ] + "rangeDependence": { + "enabled": false, + "type": "withinRange", + "target": "hostile", + "range": "melee" + } }, + "changes": [ + { + "key": "system.bonuses.damage.physical.dice", + "mode": 2, + "value": "+1d8", + "priority": null + }, + { + "key": "system.bonuses.damage.magical.dice", + "mode": 2, + "value": "+1d8", + "priority": null + } + ], "disabled": false, "duration": { "startTime": null, diff --git a/styles/less/dialog/damage-selection/sheet.less b/styles/less/dialog/damage-selection/sheet.less index 0bb0f2be..9f8cfc8a 100644 --- a/styles/less/dialog/damage-selection/sheet.less +++ b/styles/less/dialog/damage-selection/sheet.less @@ -17,13 +17,6 @@ } } - .section-header { - font-size: var(--font-size-20); - color: light-dark(@dark, @beige); - text-align: center; - margin-bottom: -12px; - } - .bonuses { gap: 4px; .critical-chip { diff --git a/styles/less/dialog/group-roll-dialog/initialization.less b/styles/less/dialog/group-roll-dialog/initialization.less index a4b82e55..b32f4756 100644 --- a/styles/less/dialog/group-roll-dialog/initialization.less +++ b/styles/less/dialog/group-roll-dialog/initialization.less @@ -22,7 +22,6 @@ font-family: var(--dh-font-body); font-size: var(--font-size-12); font-weight: 300; - text-align: center; } .members-container { diff --git a/styles/less/dialog/tag-team-dialog/initialization.less b/styles/less/dialog/tag-team-dialog/initialization.less index e79ed65c..d6f7ad29 100644 --- a/styles/less/dialog/tag-team-dialog/initialization.less +++ b/styles/less/dialog/tag-team-dialog/initialization.less @@ -88,21 +88,9 @@ grid-template-columns: 1fr 1fr; gap: 8px; - .inactive { + &.inactive { opacity: 0.4; } - - .initiator-cost-fields { - display: flex; - flex-direction: column; - align-items: flex-start; - - .initiator-cost-inputs { - display: grid; - grid-template-columns: auto 1fr; - align-items: center; - } - } } footer { diff --git a/styles/less/global/chat.less b/styles/less/global/chat.less index 4e29cfff..b9478ea4 100644 --- a/styles/less/global/chat.less +++ b/styles/less/global/chat.less @@ -7,12 +7,12 @@ .chat-log .chat-message { background-image: url('../assets/parchments/dh-parchment-light.png'); - .message-header .message-header-main .message-metadata, - .message-header .message-header-main .name { + .message-header .message-header-metadata .message-metadata, + .message-header .message-header-main .message-sub-header-container { color: @dark; } - .message-header .message-header-main h4 { + .message-header .message-header-main .message-sub-header-container h4 { color: @dark-blue; } @@ -42,12 +42,27 @@ .message-header { display: flex; - gap: 8px; + gap: 4px; padding: 8px; - align-items: center; - .portrait { - flex: 0 0 auto; + .message-header-metadata { + flex: none; + display: flex; + flex-direction: column; + + .message-metadata { + font-family: @font-body; + color: @beige; + } + } + + .message-header-main { + display: flex; + align-items: center; + gap: 8px; + flex: 1; + overflow: hidden; + .actor-img { border-radius: 50%; width: 40px; @@ -55,60 +70,20 @@ object-fit: cover; object-position: top center; } - } - .message-header-main { - display: flex; - align-items: center; - column-gap: 4px; - row-gap: 2px; - flex: 1; - overflow: hidden; - - display: grid; - grid-template: - "title metadata" - "subtitle subtitle"; - - h4 { - font-size: var(--font-size-16); - font-weight: bold; - margin-bottom: 0; - font-family: @font-subtitle; - color: @golden; - white-space: nowrap; - text-overflow: ellipsis; - flex: 1; - overflow: hidden; - align-self: flex-end; - } - - .message-metadata { - font-family: @font-body; - color: @beige; - white-space: nowrap; - align-items: baseline; - .message-timestamp { - font-size: var(--font-size-11); - } - } - - .subtitle { - grid-area: subtitle; + .message-sub-header-container { flex: 1; display: flex; + flex-direction: column; justify-content: space-between; color: @beige; - gap: 4px; - align-items: baseline; - line-height: 1; - .name { - flex: 1; - } - .whisper-to { - color: @color-text-subtle; - flex: 0; - white-space: nowrap; + + h4 { + font-size: var(--font-size-16); + font-weight: bold; + margin-bottom: 0; + font-family: @font-subtitle; + color: @golden; } } } diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index d31e09b9..e57ba50d 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -26,11 +26,9 @@ &:focus, &:focus[type='text'], &:focus[type='number'] { - &:where(:not(:disabled)) { - background: light-dark(@soft-shadow, @semi-transparent-dark-blue); - box-shadow: none; - outline: 2px solid @input-color-border; - } + background: light-dark(@soft-shadow, @semi-transparent-dark-blue); + box-shadow: none; + outline: 2px solid @input-color-border; } &:disabled[type='text'], @@ -263,14 +261,13 @@ fieldset { align-items: center; - margin: 5px 0 0 0; + margin-top: 5px; border-radius: 6px; border-color: @color-fieldset-border; - padding-inline: 0.625rem; &.glassy { background-color: light-dark(@dark-blue-10, @golden-10); - border: none; + border-color: transparent; legend { padding: 2px 12px; @@ -308,10 +305,6 @@ min-height: auto; row-gap: 0; - &.active { - row-gap: 10px; - } - legend { display: flex; align-items: center; @@ -391,10 +384,6 @@ justify-content: space-between; } - label { - white-space: nowrap; - } - .btn { padding-top: 15px; } @@ -410,13 +399,6 @@ > .checkbox { align-self: end; } - - .auto-sized { - width: auto; - display: flex; - flex-direction: column; - align-items: center; - } } .form-group { @@ -553,39 +535,50 @@ transform-origin: top; } - /* A multi-button element used to attach resources to other buttons */ - .item-button { + .item-buttons { + grid-column: span 3; display: flex; - button { - color: light-dark(@dark-blue, @dark-blue); - white-space: nowrap; - border: none; + gap: 8px; + flex-wrap: wrap; + margin-top: 2px; - &:hover { - color: @color-text-emphatic; - } + .item-button { + display: flex; + border: 1px solid light-dark(#18162e, #18162e); + color: light-dark(#18162e, #18162e); + outline: none; + box-shadow: none; + border-radius: 6px; - &:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - padding: 6px; - background: light-dark(@dark-blue-10, @golden-secondary); - color: light-dark(@dark-blue, @dark-golden); + button { + border-radius: 3px 0px 0px 3px; + color: light-dark(@dark-blue, @dark-blue); + white-space: nowrap; + border: 0; &:hover { - background: light-dark(@light-black, @dark-blue); - color: light-dark(@dark-blue, @golden-secondary); + color: @color-text-emphatic; + } + + &:not(:first-child) { + padding: 6px; + background: light-dark(@dark-blue-10, @golden-secondary); + border-radius: 0px 3px 3px 0px; + color: light-dark(@dark-blue, @dark-golden); + + &:hover { + background: light-dark(@light-black, @dark-blue); + color: light-dark(@dark-blue, @golden-secondary); + } } } - &:not(:last-child) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; + .spacer { border-right: 1px solid black; + content: ''; } } } - .artist-attribution { width: 100%; display: flex; @@ -595,86 +588,7 @@ margin-top: 4px; color: light-dark(#14142599, #efe6d850); font-size: var(--font-size-12); - padding-left: 16px; - } - - section.gm-notes-section { - padding-bottom: var(--spacer-4); - header.gm-notes + p { - margin-top: 0; - } - } - - header.gm-notes { - position: relative; - display: flex; - gap: 6px; - align-items: center; - &::before, - &::after { - content: " "; - flex: 1; - border-bottom: 1px solid var(--color-dark-6); - } - &::before { - mask-image: linear-gradient(270deg, black 0%, black calc(100% - 10px), transparent 100%); - } - &::after { - mask-image: linear-gradient(270deg, transparent 0%, black 10px, black 100%); - } - margin-top: var(--spacer-8); - margin-bottom: var(--spacer-4); - font-size: var(--font-size-11); - text-transform: uppercase; - } - - secret-block { - display: block; - - /** A buffer to make the hover behavior work a bit better. The bottom in the button needs to compensate */ - @buffer: 8px; - margin-top: -@buffer; - padding-top: @buffer; - - button.reveal { - --button-size: 1rem; - height: var(--button-size); - position: absolute; - margin: auto; - left: 0; - right: 0; - width: min-content; - padding: 1px 8px 0 8px; - bottom: calc(100% - 0.4375rem - 1px); - - background-color: var(--dh-window-button-color-bg); // todo: find a better var name - border-color: var(--color-secret-border); - color: var(--dh-window-button-color-text); - font-size: var(--font-size-10); - user-select: none; - text-transform: uppercase; - white-space: nowrap; - - visibility: hidden; - } - - &:hover button.reveal { - visibility: visible; - } - } - - /** - * The element inside a secret-block. - * This is separate since during prosemirror editing, the secret-block container does not exist. - */ - section.secret { - --color-secret-bg: @red-10; - --color-revealed-bg: @green-10; - position: relative; - padding: 0; - p { - margin: 0.5rem 0; - } + padding-left: 3px; } } @@ -896,8 +810,4 @@ right: 2px; } } - - .gm-notes { - font-style: italic; - } } diff --git a/styles/less/global/feature-section.less b/styles/less/global/feature-section.less index ecfb4ff6..2fd4e20f 100644 --- a/styles/less/global/feature-section.less +++ b/styles/less/global/feature-section.less @@ -3,7 +3,7 @@ .sheet.daggerheart.dh-style.item { .tab.features { - padding: 7px 10px; + padding: 0 10px; overflow-y: auto; .feature-list { display: flex; diff --git a/styles/less/global/global.less b/styles/less/global/global.less index 2c44c94e..c0e7f3fc 100644 --- a/styles/less/global/global.less +++ b/styles/less/global/global.less @@ -12,9 +12,6 @@ } .daggerheart.dh-style { - /** Not an actual scrollbar width (it can't be configured on all browsers) but actually a compensation value for scrollbar gutter purposes */ - --scrollbar-width: 10px; - * { scrollbar-width: thin; scrollbar-color: light-dark(@dark-blue, @golden) transparent; @@ -111,7 +108,3 @@ body.theme-light, .themed.theme-light { color-scheme: light; } - -body:not([data-gm=true]) [data-visibility="gm"] { - display: none; -} \ No newline at end of file diff --git a/styles/less/global/inventory-item.less b/styles/less/global/inventory-item.less index d2ca76c6..3a5a9321 100644 --- a/styles/less/global/inventory-item.less +++ b/styles/less/global/inventory-item.less @@ -43,19 +43,16 @@ } } - .item-main { - border-radius: 5px; - padding: 2px; - margin: -2px; - } - &:hover { .inventory-item-header .item-label .item-name .expanded-icon { margin-left: 10px; display: inline-block; } - .item-main { - background: light-dark(@dark-blue-40, @golden-40); + &:has(.inventory-item-content.extensible) { + .inventory-item-header, + .inventory-item-content { + background: light-dark(@dark-blue-40, @golden-40); + } } &:has(.inventory-item-content.extended) { .inventory-item-header .item-label .item-name .expanded-icon { @@ -63,6 +60,19 @@ } } } + + &:has(.inventory-item-content.extensible) { + .inventory-item-header { + border-radius: 5px 5px 0 0; + } + .inventory-item-content { + border-radius: 0 0 5px 5px; + } + } + + &:not(:has(.inventory-item-content.extensible)) .inventory-item-header { + border-radius: 5px; + } } .inventory-item-header, @@ -144,10 +154,6 @@ display: flex; align-items: center; gap: 4px; - - .unloaded { - opacity: 0.5; - } } } @@ -165,9 +171,39 @@ grid-template-rows: 1fr; padding-top: 4px; } - .inventory-description { + .invetory-description { overflow: hidden; - .typography(); + + h1 { + font-size: var(--font-size-32); + } + h2 { + font-size: var(--font-size-28); + font-weight: 600; + } + h3 { + font-size: var(--font-size-20); + font-weight: 600; + } + h4 { + font-size: var(--font-size-16); + color: @beige; + font-weight: 600; + } + + ul, + ol { + margin: 1rem 0; + padding: 0 0 0 1.25rem; + + li { + margin-bottom: 0.25rem; + } + } + + ul { + list-style: disc; + } } } .item-resources { @@ -245,14 +281,6 @@ grid-area: labels; } } - - .item-buttons { - grid-column: span 3; - display: flex; - gap: 4px; - flex-wrap: wrap; - margin-top: 2px; - } } .card-item { diff --git a/styles/less/global/item-header.less b/styles/less/global/item-header.less index 1a8d7fce..f47ca7dc 100755 --- a/styles/less/global/item-header.less +++ b/styles/less/global/item-header.less @@ -12,14 +12,12 @@ }); .application.sheet.daggerheart.dh-style { - --portrait-size: 150px; - .item-sheet-header { display: flex; .profile { - height: var(--portrait-size); - width: var(--portrait-size); + height: 150px; + width: 150px; object-fit: cover; border-right: 1px solid light-dark(@dark-blue, @golden); border-bottom: 1px solid light-dark(@dark-blue, @golden); @@ -36,24 +34,19 @@ text-align: center; width: 80%; - .item-name { - display: flex; - flex-direction: column; - margin: 10px 10px 0 10px; - input[type='text'] { - font-size: var(--font-size-30); - text-align: center; - width: 100%; - transition: all 0.3s ease; - outline: 2px solid transparent; - border: 1px solid transparent; - text-overflow: ellipsis; + .item-name input[type='text'] { + font-size: var(--font-size-32); + height: 42px; + text-align: center; + width: 90%; + transition: all 0.3s ease; + outline: 2px solid transparent; + border: 1px solid transparent; - &:hover[type='text'], - &:focus[type='text'] { - box-shadow: none; - outline: 2px solid light-dark(@dark-blue, @golden); - } + &:hover[type='text'], + &:focus[type='text'] { + box-shadow: none; + outline: 2px solid light-dark(@dark-blue, @golden); } } diff --git a/styles/less/global/prose-mirror.less b/styles/less/global/prose-mirror.less index 430ca79d..e4b1249f 100644 --- a/styles/less/global/prose-mirror.less +++ b/styles/less/global/prose-mirror.less @@ -1,11 +1,8 @@ @import '../utils/colors.less'; @import '../utils/fonts.less'; -@import '../utils/mixin.less'; .application.daggerheart { prose-mirror { - --menu-padding: 4px 0px; - --menu-height: calc(var(--menu-button-height) + 8px); height: 100% !important; width: 100%; @@ -13,9 +10,37 @@ background-color: transparent; } .editor-content { - .with-scroll-shadows(); - .typography(); - } + h1 { + font-size: var(--font-size-32); + } + h2 { + font-size: var(--font-size-28); + font-weight: 600; + } + h3 { + font-size: var(--font-size-20); + font-weight: 600; + } + h4 { + font-size: var(--font-size-16); + color: light-dark(@dark, @beige); + font-weight: 600; + } + + ul, + ol { + margin: 1rem 0; + padding: 0 0 0 1.25rem; + + li { + margin-bottom: 0.25rem; + } + } + + ul { + list-style: disc; + } + } // Fixes centering and makes it not render over scrollbar &:hover button.toggle:enabled { display: flex; diff --git a/styles/less/global/resource-bar.less b/styles/less/global/resource-bar.less index 3560285a..d06b43a8 100644 --- a/styles/less/global/resource-bar.less +++ b/styles/less/global/resource-bar.less @@ -9,107 +9,110 @@ } }); -/** Pips styling, can exist standalone even without a slot-value */ -.slot-bar { - display: flex; - gap: 4px; - padding: 5px; - border: 1px solid @color-border; - border-radius: 6px; - z-index: 1; - color: @color-text-emphatic; - width: fit-content; - min-height: 22px; - flex-wrap: wrap; - - .slot { - transition: all 0.3s ease; - cursor: pointer; - } - - .slot:not(:has(i)) { - width: 15px; - height: 10px; - border: 1px solid @color-border; - background: light-dark(@dark-blue-10, @golden-10); - border-radius: 3px; - - &.large { - width: 20px; - } - - &.filled { - background: light-dark(@dark-blue, @golden); - } - } - - &.armor .slot { - font-size: var(--font-size-12); - .fa-shield-halved { - color: light-dark(@dark-blue-40, @golden-40); - } - } - - .empty-slot { - width: 15px; - height: 10px; - } -} - -.slot-value { - display: flex; - flex-direction: column; - font-size: 1.5rem; - align-items: center; - justify-content: center; - text-align: center; - z-index: 2; - color: @beige; - - .slot-label { - display: flex; - align-items: center; - color: light-dark(@beige, @dark-blue); - background: light-dark(@dark-blue, @golden); - padding: 0 5px; - width: fit-content; - font-weight: bold; - border-radius: 0px 0px 5px 5px; - font-size: var(--font-size-12); - - .label { - padding-right: 5px; - } - - .value { - padding-left: 6px; - border-left: 1px solid light-dark(@beige, @dark-golden); - } - } -} - .status-bar { display: flex; - flex-direction: column; - align-items: center; + justify-content: center; position: relative; + width: 120px; + height: 40px; - .status-value { + .status-label { position: relative; + top: 40px; + height: 22px; + width: 79px; + clip-path: path('M0 0H79L74 16.5L39 22L4 16.5L0 0Z'); + background: light-dark(@dark-blue, @golden); + + h4 { + font-weight: bold; + text-align: center; + line-height: 18px; + color: light-dark(@beige, @dark-blue); + } + } + .slot-value { + position: absolute; display: flex; + flex-direction: column; padding: 0 5px; font-size: 1.5rem; align-items: center; - width: 100px; + width: 140px; height: 40px; justify-content: center; text-align: center; z-index: 2; color: @beige; - > * { + .slot-bar { + display: flex; + flex-wrap: wrap; + gap: 5px; + padding: 5px; + border: 1px solid @color-border; + border-radius: 6px; z-index: 1; + color: @color-text-emphatic; + width: fit-content; + + .slot { + width: 15px; + height: 10px; + border: 1px solid @color-border; + background: light-dark(@dark-blue-10, @golden-10); + border-radius: 3px; + transition: all 0.3s ease; + cursor: pointer; + + &.large { + width: 20px; + } + + &.filled { + background: light-dark(@dark-blue, @golden); + } + } + + .empty-slot { + width: 15px; + height: 10px; + } } + .slot-label { + display: flex; + align-items: center; + color: light-dark(@beige, @dark-blue); + background: light-dark(@dark-blue, @golden); + padding: 0 5px; + width: fit-content; + font-weight: bold; + border-radius: 0px 0px 5px 5px; + font-size: var(--font-size-12); + + .label { + padding-right: 5px; + } + + .value { + padding-left: 6px; + border-left: 1px solid light-dark(@beige, @dark-golden); + } + } + } + + .status-value { + position: absolute; + display: flex; + padding: 0 5px; + font-size: 1.5rem; + align-items: center; + width: 140px; + height: 40px; + justify-content: center; + text-align: center; + z-index: 2; + color: @beige; input[type='number'] { background: transparent; @@ -143,11 +146,11 @@ .progress-bar { position: absolute; appearance: none; - width: 100%; - height: 100%; + width: 100px; + height: 40px; border: 1px solid @color-border; border-radius: 6px; - z-index: 0; + z-index: 1; background: @dark-blue; &::-webkit-progress-bar { @@ -172,29 +175,4 @@ border-radius: 6px; } } - .status-label { - position: relative; - height: 22px; - width: 79px; - background: light-dark(@dark-blue, @golden); - - &.pointy { - clip-path: path('M0 0H79L74 16.5L39 22L4 16.5L0 0Z'); - margin-bottom: -2px; // compensate for pointy bottom so spacing feels more "right" - } - - h4 { - font-weight: bold; - text-align: center; - line-height: 18px; - color: light-dark(@beige, @dark-blue); - } - } } - -// Overrides for sidebar usage. -aside[data-application-part="sidebar"] .resources-section .slot-bar { - display: grid; - grid-template-columns: repeat(6, min-content); - grid-auto-flow: row; -} \ No newline at end of file diff --git a/styles/less/global/sheet.less b/styles/less/global/sheet.less index d7be1a84..e3072da1 100755 --- a/styles/less/global/sheet.less +++ b/styles/less/global/sheet.less @@ -36,8 +36,8 @@ body.game:is(.performance-low, .noblur) { } button { - background: var(--dh-window-button-color-bg); - color: var(--dh-window-button-color-text); + background: light-dark(#e8e6e3, @deep-black); + color: light-dark(@dark-blue, @beige); border: 1px solid light-dark(@dark-blue, transparent); padding: 0; @@ -54,7 +54,7 @@ body.game:is(.performance-low, .noblur) { position: relative; min-height: -webkit-fill-available; transition: opacity 0.3s ease; - padding-bottom: 16px; + padding-bottom: 20px; .tab { padding: 0 10px; diff --git a/styles/less/global/tab-description.less b/styles/less/global/tab-description.less index e2869723..5c18e02b 100644 --- a/styles/less/global/tab-description.less +++ b/styles/less/global/tab-description.less @@ -6,80 +6,11 @@ display: flex; flex-direction: column; flex: 1; - overflow: hidden; - padding: 0; - margin: 0; + overflow-y: hidden !important; + padding-top: 10px; - .description-section { - flex: 1; - display: flex; - flex-direction: column; - overflow: auto; - padding: 12px 16px 4px 16px; - .with-scroll-shadows(); - prose-mirror { - button.toggle { - top: 0px; - right: 0; - } - button[data-action=editGMNote] { - right: calc(var(--button-size) + 4px); - } - &.inactive { - height: unset!important; - overflow: unset; - .editor-content { - position: relative; - overflow: unset; - - // Allows content links to peek out - margin-top: -4px; - padding: 4px 0 0 0; - } - } - &.active { - --min-height: 250px; - padding: 8px 0 0 16px; - button[data-action=editGMNote] { - display: none; - } - .editor-content { - padding-right: 16px; - padding-bottom: 4px; - } - } - } - /** Hide editors that are empty when inactive if we need them to be */ - prose-mirror.inactive.hide-if-inactive { - display: none; - } - &:has(prose-mirror.active) { - padding: 0; - } - /** Description should fill available room (with overriden exceptions) */ - prose-mirror[name="system.description"] { - flex: 1 0; - } - &:has(prose-mirror[name="system.gmNotes"]:not(.hide-if-inactive)) { - prose-mirror.inactive { - --min-height: 3rem; - &[name="system.description"] { - flex: 0 0; - } - &[name="system.gmNotes"] { - flex: 1 0; - } - } - } - } - - /** Hide other elements if an editor is open */ - &:has(prose-mirror.active) { - prose-mirror.inactive, - header.gm-notes, - .artist-attribution { - display: none; - } + prose-mirror.active + .artist-attribution { + display: none; } } } diff --git a/styles/less/sheets/actors/actor-sheet-shared.less b/styles/less/sheets/actors/actor-sheet-shared.less index a464d7a1..b3eb0469 100644 --- a/styles/less/sheets/actors/actor-sheet-shared.less +++ b/styles/less/sheets/actors/actor-sheet-shared.less @@ -37,30 +37,12 @@ color: @color-text-subtle; } - .window-header > .attribution-header-label { - margin-right: var(--spacer-4); - pointer-events: none; - } - - .tab-navigation { - margin-bottom: 0; - } - - .tab { - flex: 1; - padding: 0; - overflow: hidden; - .search-section { - padding: 12px 14px var(--spacer-8) 12px; - } - } - .tab.inventory { .gold-section { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 10px; - padding: var(--spacer-8) 16px var(--spacer-8) 16px; + padding: 10px 10px 0; .input { color: light-dark(@dark, @beige); @@ -68,33 +50,6 @@ } } - .tab.notes.active { - padding: 0; - margin: 0; - scrollbar-gutter: unset; - - // Add padding around top level level prosemirrors used for note tabs - > prose-mirror { - @right-padding: calc(16px - var(--scrollbar-width)); - .editor-content { - scrollbar-gutter: stable; - padding-right: @right-padding; - padding-bottom: 4px; - } - &.inactive { - button.toggle { - top: 16px; - } - .editor-content { - padding: 16px @right-padding 4px 16px; - } - } - &.active { - padding: 8px 0 0 16px; - } - } - } - .search-section { display: flex; gap: 10px; diff --git a/styles/less/sheets/actors/adversary/effects.less b/styles/less/sheets/actors/adversary/effects.less index f489bee6..4aa44e51 100644 --- a/styles/less/sheets/actors/adversary/effects.less +++ b/styles/less/sheets/actors/adversary/effects.less @@ -7,8 +7,9 @@ display: flex; flex-direction: column; gap: 10px; - padding: 7px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/adversary/features.less b/styles/less/sheets/actors/adversary/features.less index 49289d36..447d050e 100644 --- a/styles/less/sheets/actors/adversary/features.less +++ b/styles/less/sheets/actors/adversary/features.less @@ -5,8 +5,12 @@ .application.sheet.daggerheart.actor.dh-style.adversary { .tab.features { .feature-section { - padding: 16px calc(16px - var(--scrollbar-width)) 4px 16px; - .stable-scroll-container(); + display: flex; + flex-direction: column; + gap: 10px; + overflow-y: auto; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/adversary/header.less b/styles/less/sheets/actors/adversary/header.less index 549a219d..1e5e4fa5 100644 --- a/styles/less/sheets/actors/adversary/header.less +++ b/styles/less/sheets/actors/adversary/header.less @@ -3,21 +3,16 @@ .application.sheet.daggerheart.actor.dh-style.adversary { .adversary-header-sheet { + padding: 0 15px; padding-top: var(--header-height); width: 100%; - > *:not(line-div, .tab-navigation) { - padding-left: 15px; - padding-right: 15px; - } - .name-row { display: flex; gap: 5px; align-items: center; justify-content: space-between; - padding-top: var(--spacer-4); - padding-bottom: var(--spacer-4); + padding: 8px 0; flex: 1; h1 { @@ -39,8 +34,8 @@ .tags { display: flex; - gap: 8px; - padding-bottom: var(--spacer-12); + gap: 10px; + padding-bottom: 8px; .tag { display: flex; @@ -49,7 +44,8 @@ justify-content: center; align-items: center; padding: 3px 5px; - font: var(--font-size-12) @font-body; + font-size: var(--font-size-12); + font: @font-body; background: light-dark(@dark-15, @beige-15); border: 1px solid light-dark(@dark, @beige); @@ -68,16 +64,8 @@ .adversary-info { display: flex; flex-direction: column; - gap: var(--spacer-8); - padding-top: var(--spacer-12); - padding-bottom: var(--spacer-12); - } - - .tab-navigation { - margin-top: 0; - button[data-action="openSettings"] { - margin-right: 12px; - } + gap: 12px; + padding: 16px 0; } } } diff --git a/styles/less/sheets/actors/adversary/index.less b/styles/less/sheets/actors/adversary/index.less index 978cf1f8..28ff9d22 100644 --- a/styles/less/sheets/actors/adversary/index.less +++ b/styles/less/sheets/actors/adversary/index.less @@ -1,6 +1,7 @@ -@import './sheet.less'; @import './features.less'; @import './header.less'; +@import './sheet.less'; @import './sidebar.less'; @import './effects.less'; @import './notes.less'; + diff --git a/styles/less/sheets/actors/adversary/sheet.less b/styles/less/sheets/actors/adversary/sheet.less index 1eb7d423..0bd845fa 100644 --- a/styles/less/sheets/actors/adversary/sheet.less +++ b/styles/less/sheets/actors/adversary/sheet.less @@ -2,37 +2,35 @@ @import '../../../utils/fonts.less'; .application.sheet.daggerheart.actor.dh-style.adversary { - --sidebar-width: 260px; - .window-content { display: grid; - grid-template-columns: var(--sidebar-width) 1fr; + grid-template-columns: 275px 1fr; grid-template-rows: auto 1fr; height: 100%; width: 100%; padding-bottom: 0; - } - .adversary-sidebar-sheet { - grid-row: 1 / span 2; - grid-column: 1; - overflow: hidden; - display: flex; - flex-direction: column; - } - - .adversary-header-sheet { - grid-row: 1; - grid-column: 2; - } - - .tab { - grid-row: 2; - grid-column: 2; - &.active { + .adversary-sidebar-sheet { + grid-row: 1 / span 2; + grid-column: 1; + overflow: hidden; display: flex; flex-direction: column; - margin: 0 0 10px 0; + } + + .adversary-header-sheet { + grid-row: 1; + grid-column: 2; + } + + .tab { + grid-row: 2; + grid-column: 2; + &.active { + overflow: hidden; + display: flex; + flex-direction: column; + } } } -} \ No newline at end of file +} diff --git a/styles/less/sheets/actors/adversary/sidebar.less b/styles/less/sheets/actors/adversary/sidebar.less index 8353d092..5db9f5e9 100644 --- a/styles/less/sheets/actors/adversary/sidebar.less +++ b/styles/less/sheets/actors/adversary/sidebar.less @@ -22,8 +22,8 @@ .application.sheet.daggerheart.actor.dh-style.adversary { .adversary-sidebar-sheet { - width: var(--sidebar-width); - min-width: var(--sidebar-width); + width: 275px; + min-width: 275px; border-right: 1px solid light-dark(@dark-blue, @golden); .portrait { @@ -52,7 +52,7 @@ } img { - height: var(--sidebar-width); + height: 275px; } .death-roll-btn { @@ -63,7 +63,7 @@ .threshold-section { position: relative; display: flex; - gap: 7px; + gap: 10px; background-color: light-dark(transparent, @dark-blue); color: @color-text-emphatic; padding: 5px 10px; @@ -106,8 +106,8 @@ display: flex; flex-direction: column; top: -20px; - gap: 10px; - margin-bottom: -16px; + gap: 16px; + margin-bottom: -10px; &.pip-display { top: -15px; @@ -120,6 +120,105 @@ .resources-section { display: flex; justify-content: space-evenly; + margin-bottom: 16px; + + .status-bar { + display: flex; + justify-content: center; + position: relative; + width: 100px; + height: 40px; + + .status-label { + position: relative; + top: 40px; + height: 22px; + width: 79px; + clip-path: path('M0 0H79L74 16.5L39 22L4 16.5L0 0Z'); + background: light-dark(@dark-blue, @golden); + + h4 { + font-weight: bold; + text-align: center; + line-height: 18px; + color: light-dark(@beige, @dark-blue); + } + } + .status-value { + position: absolute; + display: flex; + padding: 0 6px; + font-size: 1.5rem; + align-items: center; + width: 100px; + height: 40px; + justify-content: center; + text-align: center; + z-index: 2; + color: @beige; + + input[type='number'] { + background: transparent; + font-size: 1.5rem; + width: 40px; + height: 30px; + text-align: center; + border: none; + outline: 2px solid transparent; + color: @beige; + + &.bar-input { + padding: 0; + color: @beige; + backdrop-filter: none; + background: transparent; + transition: all 0.3s ease; + + &:hover, + &:focus { + background: @semi-transparent-dark-blue; + backdrop-filter: blur(9.5px); + } + } + } + + .bar-label { + width: 40px; + } + } + .progress-bar { + position: absolute; + appearance: none; + width: 100px; + height: 40px; + border: 1px solid @color-border; + border-radius: 6px; + z-index: 1; + background: @dark-blue; + + &::-webkit-progress-bar { + border: none; + background: @dark-blue; + border-radius: 6px; + } + &::-webkit-progress-value { + background: @gradient-hp; + border-radius: 6px; + } + &.stress-color::-webkit-progress-value { + background: @gradient-stress; + border-radius: 6px; + } + &::-moz-progress-bar { + background: @gradient-hp; + border-radius: 6px; + } + &.stress-color::-moz-progress-bar { + background: @gradient-stress; + border-radius: 6px; + } + } + } } .status-section { @@ -157,7 +256,7 @@ .status-label { padding: 2px 10px; width: 100%; - border-radius: 0 0 3px 3px; + border-radius: 3px; background: light-dark(@dark-blue, @golden); h4 { @@ -185,8 +284,8 @@ .shortcut-items-section { overflow-y: hidden; - padding: 10px 0; - flex: 1; + padding-top: 10px; + padding-bottom: 20px; scrollbar-gutter: stable; .with-scroll-shadows(); @@ -214,6 +313,8 @@ } .experience-section { + margin-bottom: 20px; + .title { display: flex; gap: 15px; @@ -230,21 +331,21 @@ gap: 5px; width: 100%; margin-top: 10px; - align-items: stretch; - padding: 0 4px 0 12px; + align-items: center; .experience-row { display: flex; gap: 5px; + width: 250px; align-items: center; justify-content: space-between; .experience-name { + width: 180px; display: flex; align-items: center; text-align: start; font-size: var(--font-size-14); - flex: 1; color: light-dark(@dark, @beige); line-height: 1; } @@ -269,7 +370,9 @@ .reaction-section { display: flex; - margin: 10px; + padding: 0 10px; + margin-top: 20px; + width: 100%; button { height: 40px; diff --git a/styles/less/sheets/actors/character/biography.less b/styles/less/sheets/actors/character/biography.less index 9782a588..8548a2fb 100644 --- a/styles/less/sheets/actors/character/biography.less +++ b/styles/less/sheets/actors/character/biography.less @@ -8,14 +8,17 @@ display: flex; flex-direction: column; gap: 10px; - height: 100%; - padding: 12px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + height: 100%; + overflow-y: auto; + padding-top: 8px; + padding-bottom: 20px; + height: 100%; + .with-scroll-shadows(); } .characteristics-section { gap: 20px; - padding: 0 4px; + padding: 0 10px; } .biography-section { diff --git a/styles/less/sheets/actors/character/effects.less b/styles/less/sheets/actors/character/effects.less index 8fac301c..0ab1007d 100644 --- a/styles/less/sheets/actors/character/effects.less +++ b/styles/less/sheets/actors/character/effects.less @@ -8,8 +8,9 @@ display: flex; flex-direction: column; gap: 10px; - padding: 7px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/character/features.less b/styles/less/sheets/actors/character/features.less index fcde3e38..52b41826 100644 --- a/styles/less/sheets/actors/character/features.less +++ b/styles/less/sheets/actors/character/features.less @@ -8,8 +8,9 @@ display: flex; flex-direction: column; gap: 10px; - padding: 7px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/character/header.less b/styles/less/sheets/actors/character/header.less index 68ebc812..91b3545a 100644 --- a/styles/less/sheets/actors/character/header.less +++ b/styles/less/sheets/actors/character/header.less @@ -19,19 +19,16 @@ .application.sheet.daggerheart.actor.dh-style.character { .character-header-sheet { + padding: 0 15px; padding-top: var(--header-height); width: 100%; - > *:not(line-div, .tab-navigation) { - padding-left: 15px; - padding-right: 15px; - } - .name-row { display: flex; gap: 6px; align-items: start; justify-content: space-between; + padding: 0; padding-top: 5px; flex: 1; @@ -42,14 +39,19 @@ } h1 { - --dh-input-color-border: @color-border; display: flex; flex: 1; padding: 6px 0 0 0; font-size: var(--font-size-32); text-align: start; + border: 1px solid transparent; + outline: 2px solid transparent; transition: all 0.3s ease; word-break: break-word; + + &:hover { + outline: 2px solid light-dark(@dark, @golden); + } } .level-div { @@ -98,8 +100,8 @@ .character-details { display: flex; justify-content: space-between; - margin-top: 5px; - margin-bottom: 10px; + padding: 5px 0; + margin-bottom: 8px; font-size: var(--font-size-12); color: @color-text-emphatic; @@ -128,6 +130,7 @@ .character-row { display: flex; align-items: center; + padding: 0; margin-bottom: 12px; .resource-section { @@ -215,11 +218,12 @@ .character-traits { display: flex; + padding: 0; margin-bottom: 15px; justify-content: space-between; max-width: 38.5rem; gap: 0.5rem; - margin-left: 0.5rem; + padding-left: 0.5rem; .trait { cursor: pointer; @@ -321,9 +325,5 @@ } } } - - .tab-navigation button[data-action="openSettings"] { - margin-right: 12px; - } } } diff --git a/styles/less/sheets/actors/character/index.less b/styles/less/sheets/actors/character/index.less index f196d5bf..edefe0a1 100644 --- a/styles/less/sheets/actors/character/index.less +++ b/styles/less/sheets/actors/character/index.less @@ -1,8 +1,8 @@ -@import './sheet.less'; @import './biography.less'; @import './effects.less'; @import './features.less'; @import './header.less'; @import './inventory.less'; @import './loadout.less'; +@import './sheet.less'; @import './sidebar.less'; diff --git a/styles/less/sheets/actors/character/inventory.less b/styles/less/sheets/actors/character/inventory.less index 2e40b349..fcfbbee9 100644 --- a/styles/less/sheets/actors/character/inventory.less +++ b/styles/less/sheets/actors/character/inventory.less @@ -8,8 +8,10 @@ display: flex; flex-direction: column; gap: 10px; - padding: 8px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + margin-top: 20px; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/character/loadout.less b/styles/less/sheets/actors/character/loadout.less index cb1baaa6..fa3e0176 100644 --- a/styles/less/sheets/actors/character/loadout.less +++ b/styles/less/sheets/actors/character/loadout.less @@ -50,8 +50,11 @@ display: flex; flex-direction: column; gap: 10px; - padding: 8px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + height: 100%; + overflow-y: auto; + margin-top: 20px; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/character/sheet.less b/styles/less/sheets/actors/character/sheet.less index 43401b19..68792c99 100644 --- a/styles/less/sheets/actors/character/sheet.less +++ b/styles/less/sheets/actors/character/sheet.less @@ -30,7 +30,7 @@ &.active { display: flex; flex-direction: column; - margin: 0 0 10px 0; + overflow: hidden; } } } diff --git a/styles/less/sheets/actors/character/sidebar.less b/styles/less/sheets/actors/character/sidebar.less index 66f09cfc..c76ee9ff 100644 --- a/styles/less/sheets/actors/character/sidebar.less +++ b/styles/less/sheets/actors/character/sidebar.less @@ -89,13 +89,113 @@ .resources-section { justify-content: space-around; - margin: 8px 2px 0 2px; + margin: 8px 2px 8px 2px; } } .resources-section { display: flex; justify-content: space-evenly; + margin-bottom: 20px; + + .status-bar { + display: flex; + justify-content: center; + position: relative; + width: 120px; + height: 40px; + + .status-label { + position: relative; + top: 40px; + height: 22px; + width: 79px; + clip-path: path('M0 0H79L74 16.5L39 22L4 16.5L0 0Z'); + background: light-dark(@dark-blue, @golden); + + h4 { + font-weight: bold; + text-align: center; + line-height: 18px; + color: light-dark(@beige, @dark-blue); + } + } + + .status-value { + position: absolute; + display: flex; + padding: 0 5px; + font-size: 1.5rem; + align-items: center; + width: 140px; + height: 40px; + justify-content: center; + text-align: center; + z-index: 2; + color: @beige; + + input[type='number'] { + background: transparent; + font-size: 1.5rem; + width: 40px; + height: 30px; + text-align: center; + border: none; + outline: 2px solid transparent; + color: @beige; + + &.bar-input { + padding: 0; + color: @beige; + backdrop-filter: none; + background: transparent; + transition: all 0.3s ease; + + &:hover, + &:focus { + background: @semi-transparent-dark-blue; + backdrop-filter: blur(9.5px); + } + } + } + + .bar-label { + width: 40px; + } + } + .progress-bar { + position: absolute; + appearance: none; + width: 100px; + height: 40px; + border: 1px solid @color-border; + border-radius: 6px; + z-index: 1; + background: @dark-blue; + + &::-webkit-progress-bar { + border: none; + background: @dark-blue; + border-radius: 6px; + } + &::-webkit-progress-value { + background: @gradient-hp; + border-radius: 6px; + } + &.stress-color::-webkit-progress-value { + background: @gradient-stress; + border-radius: 6px; + } + &::-moz-progress-bar { + background: @gradient-hp; + border-radius: 6px; + } + &.stress-color::-moz-progress-bar { + background: @gradient-stress; + border-radius: 6px; + } + } + } } .status-section { @@ -145,21 +245,21 @@ .status-bar.armor-slots { display: flex; + justify-content: center; + position: relative; width: 95px; + height: 30px; white-space: nowrap; - .status-label { - height: 30px; - } - .status-label { padding: 2px 2px; position: relative; + top: 30px; height: 22px; width: 95px; border-radius: 3px; background: light-dark(@dark-blue, @golden); - + clip-path: none; display: flex; align-items: center; justify-content: center; @@ -191,16 +291,40 @@ } } .slot-value { + position: absolute; + display: flex; + padding: 0 5px; font-size: 1.2rem; + align-items: center; width: 80px; height: 30px; + justify-content: center; + text-align: center; + z-index: 2; color: light-dark(@dark-blue, @beige); flex-direction: column; .slot-bar { + display: flex; + flex-wrap: wrap; + gap: 4px; + padding: 5px; + border: 1px solid @color-border; + border-radius: 6px; + z-index: 1; background: @dark-blue; justify-content: center; - border-bottom: none; + color: @color-text-emphatic; + + .armor-slot { + cursor: pointer; + transition: all 0.3s ease; + font-size: var(--font-size-12); + + .fa-shield-halved { + color: light-dark(@dark-blue-40, @golden-40); + } + } } .slot-label { display: flex; @@ -240,21 +364,41 @@ } } .status-value { + position: absolute; + display: flex; padding: 0 6px; font-size: 1.2rem; + align-items: center; width: 80px; height: 30px; justify-content: center; + text-align: center; + z-index: 2; color: light-dark(@dark-blue, @beige); + border: 1px solid @color-border; + border-bottom: none; + border-radius: 6px 6px 0 0; input[type='number'] { + background: transparent; font-size: 1.2rem; width: 30px; height: 20px; + text-align: center; + border: none; + outline: 2px solid transparent; color: light-dark(@dark-blue, @beige); &.bar-input { + padding: 0; color: light-dark(@dark-blue, @beige); + backdrop-filter: none; + background: transparent; + &:hover, + &:focus { + background: @semi-transparent-dark-blue; + backdrop-filter: blur(9.5px); + } } } @@ -263,9 +407,32 @@ } } .progress-bar { + position: absolute; + appearance: none; + width: 80px; + height: 30px; + border: 1px solid @color-border; + border-radius: 6px; + z-index: 1; background: light-dark(transparent, @dark-blue); border-bottom: none; border-radius: 6px 6px 0 0; + &::-webkit-progress-bar { + border: none; + background: light-dark(transparent, @dark-blue); + } + &::-webkit-progress-value { + background: @gradient-stress; + } + &.stress-color::-webkit-progress-value { + background: @gradient-stress; + } + &::-moz-progress-bar { + background: @gradient-stress; + } + &.stress-color::-moz-progress-bar { + background: @gradient-stress; + } } } diff --git a/styles/less/sheets/actors/companion/details.less b/styles/less/sheets/actors/companion/details.less index e10e7680..2e43cac4 100644 --- a/styles/less/sheets/actors/companion/details.less +++ b/styles/less/sheets/actors/companion/details.less @@ -1,10 +1,7 @@ @import '../../../utils/colors.less'; @import '../../../utils/fonts.less'; -.application.sheet.daggerheart.actor.dh-style.companion .tab.details.active { - padding: 12px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); - +.application.sheet.daggerheart.actor.dh-style.companion { .partner-section, .attack-section, .experience-list { diff --git a/styles/less/sheets/actors/companion/effects.less b/styles/less/sheets/actors/companion/effects.less index ffe66da8..c0cac669 100644 --- a/styles/less/sheets/actors/companion/effects.less +++ b/styles/less/sheets/actors/companion/effects.less @@ -6,8 +6,9 @@ display: flex; flex-direction: column; gap: 10px; - padding: 7px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/environment/features.less b/styles/less/sheets/actors/environment/features.less index c6fe3750..84cf26f8 100644 --- a/styles/less/sheets/actors/environment/features.less +++ b/styles/less/sheets/actors/environment/features.less @@ -5,8 +5,12 @@ .application.sheet.daggerheart.actor.dh-style.environment { .tab.features { .feature-section { - padding: 16px calc(16px - var(--scrollbar-width)) 4px 16px; - .stable-scroll-container(); + display: flex; + flex-direction: column; + gap: 10px; + overflow-y: auto; + padding-bottom: 4px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/environment/index.less b/styles/less/sheets/actors/environment/index.less index df7e6fc2..211c8e60 100644 --- a/styles/less/sheets/actors/environment/index.less +++ b/styles/less/sheets/actors/environment/index.less @@ -1,4 +1,4 @@ -@import './sheet.less'; @import './features.less'; @import './header.less'; @import './potentialAdversaries.less'; +@import './sheet.less'; diff --git a/styles/less/sheets/actors/environment/potentialAdversaries.less b/styles/less/sheets/actors/environment/potentialAdversaries.less index 07dc5f92..f112c0d2 100644 --- a/styles/less/sheets/actors/environment/potentialAdversaries.less +++ b/styles/less/sheets/actors/environment/potentialAdversaries.less @@ -6,8 +6,9 @@ display: flex; flex-direction: column; gap: 10px; - padding: 7px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + padding-bottom: 4px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/environment/sheet.less b/styles/less/sheets/actors/environment/sheet.less index ef9d542a..2d9cc188 100644 --- a/styles/less/sheets/actors/environment/sheet.less +++ b/styles/less/sheets/actors/environment/sheet.less @@ -14,7 +14,9 @@ .application.sheet.daggerheart.actor.dh-style.environment { .tab { + flex: 1; overflow-y: auto; + &.active { overflow: hidden; display: flex; diff --git a/styles/less/sheets/actors/npc/features.less b/styles/less/sheets/actors/npc/features.less index f68df8a8..a579d9f8 100644 --- a/styles/less/sheets/actors/npc/features.less +++ b/styles/less/sheets/actors/npc/features.less @@ -7,8 +7,12 @@ } .feature-section { - padding: 16px calc(16px - var(--scrollbar-width)) 4px 16px; - .stable-scroll-container(); + display: flex; + flex-direction: column; + gap: 10px; + overflow-y: auto; + padding-bottom: 4px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/party/header.less b/styles/less/sheets/actors/party/header.less index 96858805..58e3bc31 100644 --- a/styles/less/sheets/actors/party/header.less +++ b/styles/less/sheets/actors/party/header.less @@ -1,44 +1,48 @@ -@import '../../../utils/colors.less'; -@import '../../../utils/fonts.less'; -@import '../../../utils/mixin.less'; - -.party-header-sheet { - display: flex; - flex-direction: column; - justify-content: start; - text-align: center; - - .profile { - height: 235px; - cursor: pointer; - .smooth-gradient-ease-in-out(mask-image, to top, black, 3.5rem); - } - - .item-container { - margin-top: -2rem; - z-index: 1; - input.item-name[type='text'] { - --dh-input-color-border: @color-border; - backdrop-filter: none; - border: none; - color: @color-text-emphatic; - font-family: @font-title; - font-size: var(--font-size-32); - outline: 2px solid transparent; - box-shadow: unset; - text-shadow: 0 0 4px @color-text-shadow-contrast, 0 0 8px @color-text-shadow-contrast, 0 0 14px @color-text-shadow-contrast; - - text-align: center; - transition: all 0.3s ease; - width: calc(100% - 40px); - height: 2.625rem; - } - - .label { - font-style: normal; - font-weight: 700; - font-size: 16px; - margin: 5px 0; - } - } -} +@import '../../../utils/colors.less'; +@import '../../../utils/fonts.less'; +@import '../../../utils/mixin.less'; + +.party-header-sheet { + display: flex; + flex-direction: column; + justify-content: start; + text-align: center; + + .profile { + height: 235px; + cursor: pointer; + .smooth-gradient-ease-in-out(mask-image, to top, black, 3.5rem); + } + + .item-container { + margin-top: -2rem; + z-index: 1; + input.item-name[type='text'] { + backdrop-filter: none; + border: none; + color: @color-text-emphatic; + font-family: @font-title; + font-size: var(--font-size-32); + outline: 2px solid transparent; + box-shadow: unset; + text-shadow: 0 0 4px @color-text-shadow-contrast, 0 0 8px @color-text-shadow-contrast, 0 0 14px @color-text-shadow-contrast; + + text-align: center; + transition: all 0.3s ease; + width: calc(100% - 40px); + height: 2.625rem; + + &:hover[type='text'], + &:focus[type='text'] { + outline: 2px solid @color-border; + } + } + + .label { + font-style: normal; + font-weight: 700; + font-size: 16px; + margin: 5px 0; + } + } +} diff --git a/styles/less/sheets/actors/party/inventory.less b/styles/less/sheets/actors/party/inventory.less index a0db5dfe..444c6a57 100644 --- a/styles/less/sheets/actors/party/inventory.less +++ b/styles/less/sheets/actors/party/inventory.less @@ -8,8 +8,10 @@ display: flex; flex-direction: column; gap: 10px; - padding: 8px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + margin-top: 20px; + padding-bottom: 4px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/party/party-members.less b/styles/less/sheets/actors/party/party-members.less index ca384322..dc464291 100644 --- a/styles/less/sheets/actors/party/party-members.less +++ b/styles/less/sheets/actors/party/party-members.less @@ -1,286 +1,295 @@ -@import '../../../utils/colors.less'; -@import '../../../utils/fonts.less'; -@import '../../../utils/mixin.less'; - -.application.sheet.daggerheart.actor.dh-style.party .tab.partyMembers { - padding: 12px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); - - .actions-section { - display: flex; - align-items: center; - justify-content: center; - padding: 10px; - margin-bottom: 10px; - gap: 20px; - background-color: light-dark(@dark-blue-10, @golden-10); - - button { - span { - font-size: 12px; - } - } - - .active-action { - animation: glow 0.75s infinite alternate; - } - } - - .actors-list { - display: flex; - flex-direction: column; - gap: 8px; - align-items: stretch; - width: 100%; - - .actor-resources { - display: grid; - grid-template: - "img header" min-content - "img body" 1fr - / 7.5rem 1fr; - gap: 6px; - column-gap: 12px; - padding: 6px; - background-color: light-dark(@dark-blue-10, @golden-10); - - .actor-img-frame { - grid-area: img; - width: 7.375rem; - height: 7.375rem; - position: relative; - - .actor-img { - object-fit: cover; - object-position: top center; - border-radius: 6px; - width: 100%; - height: 100%; - } - - .equipped-weapons { - position: absolute; - top: -2px; - left: -3px; - display: flex; - flex-direction: column; - gap: 1px; - img { - border-radius: 50%; - width: 24px; - height: 24px; - border: 1px solid @color-border; - object-fit: cover; - } - } - - .evasion { - position: absolute; - top: 1px; - right: 1px; - width: 1.75rem; - height: 1.75rem; - background: url('../assets/svg/trait-shield.svg') no-repeat; - background-size: 100%; - color: var(--color-light-1); - font-size: var(--font-size-14); - font-weight: 700; - display: flex; - align-items: center; - justify-content: center; - } - - .threshold-section { - position: absolute; - left: 0; - right: 0; - bottom: -2px; - margin: auto; - - display: flex; - gap: 4px; - background-color: light-dark(var(--color-light-1), @dark-blue); - color: @color-text-emphatic; - padding: 4px 6px; - border: 1px solid @color-border; - border-radius: 3px; - align-items: baseline; - width: fit-content; - - h4 { - font-weight: bold; - text-transform: uppercase; - white-space: nowrap; - - &.threshold-label { - font-size: var(--font-size-10); - color: @color-text-emphatic; - } - - &.threshold-value { - font-size: var(--font-size-11); - color: light-dark(@dark, @beige); - } - } - } - } - - header { - grid-area: header; - display: grid; - grid-template: - "name hope" min-content - "subtitle subtitle" min-content - / 1fr min-content; - - .actor-name { - width: 100%; - z-index: 1; - font-size: var(--font-size-20); - color: @color-text-emphatic; - font-weight: bold; - } - - .delete-icon { - font-size: 0.75em; - } - - .subtitle { - grid-area: subtitle; - font-size: var(--font-size-14); - } - - .hope-section { - display: flex; - background-color: light-dark(transparent, @dark-blue); - color: @color-text-emphatic; - padding: 3px 6px; - border: 1px solid @color-border; - border-radius: 3px; - align-items: center; - width: fit-content; - margin-left: auto; - - h4 { - font-size: var(--font-size-12); - font-weight: bold; - text-transform: uppercase; - color: @color-text-emphatic; - margin-right: 3px; - } - - .hope-value { - display: flex; - cursor: pointer; - font-size: var(--font-size-12); - margin-left: 1px; - } - } - } - - .body { - grid-area: body; - display: flex; - align-items: start; - justify-content: space-between; - } - - .resources { - display: flex; - flex-direction: column; - gap: 4px; - - .slot-section { - display: flex; - flex-direction: row; - align-items: stretch; - - .slot-label { - display: flex; - align-items: center; - color: light-dark(@beige, @dark-blue); - background: light-dark(@dark-blue, @golden); - padding: 0 4px; - width: fit-content; - font-weight: bold; - border-radius: 6px 0px 0px 6px; - font-size: var(--font-size-12); - white-space: nowrap; - - .label { - padding-right: 2px; - } - - .value { - font-variant-numeric: tabular-nums; - .current { - display: inline-block; - text-align: end; - width: 2ch; - } - .max { - display: inline-block; - text-align: start; - width: 2ch; - } - } - } - - .slot-bar { - align-items: center; - flex-wrap: wrap; - background-color: light-dark(@dark-blue-10, @dark-blue); - padding: 2px 5px; - border-radius: 0 6px 6px 0; - width: fit-content; - } - } - } - - .traits { - background-color: light-dark(@dark-blue-10, @dark-blue); - border: 1px solid @color-border; - border-radius: 6px; - display: grid; - grid-template-columns: 1fr 1fr; - font-size: var(--font-size-12); - padding: 3px 4px; - gap: 3px 7px; - .trait { - display: flex; - justify-content: space-between; - gap: 3px; - .label { - color: @color-text-emphatic; - } - .value { - font-weight: 600; - } - } - } - } - } - - .actors-list.limited { - .actor-resources { - display: flex; - align-items: center; - } - .actor-img-frame { - width: 3rem; - height: 3rem; - } - } - - .actors-dragger { - display: flex; - align-items: center; - justify-content: center; - box-sizing: border-box; - width: 100%; - height: 40px; - border: 1px dashed light-dark(@dark-blue-50, @beige-50); - border-radius: 3px; - color: light-dark(@dark-blue-50, @beige-50); - } -} +@import '../../../utils/colors.less'; +@import '../../../utils/fonts.less'; +@import '../../../utils/mixin.less'; + +.application.sheet.daggerheart.actor.dh-style.party .tab.partyMembers { + overflow: auto; + + .actors-list { + display: flex; + flex-direction: column; + gap: 8px; + align-items: stretch; + width: 100%; + + .actor-resources { + display: grid; + grid-template: + "img header" min-content + "img body" 1fr + / 7.5rem 1fr; + gap: 6px; + column-gap: 12px; + padding: 6px; + background-color: light-dark(@dark-blue-10, @golden-10); + + .actor-img-frame { + grid-area: img; + width: 7.375rem; + height: 7.375rem; + position: relative; + + .actor-img { + object-fit: cover; + object-position: top center; + border-radius: 6px; + width: 100%; + height: 100%; + } + + .equipped-weapons { + position: absolute; + top: -2px; + left: -3px; + display: flex; + flex-direction: column; + gap: 1px; + img { + border-radius: 50%; + width: 24px; + height: 24px; + border: 1px solid @color-border; + object-fit: cover; + } + } + + .evasion { + position: absolute; + top: 1px; + right: 1px; + width: 1.75rem; + height: 1.75rem; + background: url('../assets/svg/trait-shield.svg') no-repeat; + background-size: 100%; + color: var(--color-light-1); + font-size: var(--font-size-14); + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + } + + .threshold-section { + position: absolute; + left: 0; + right: 0; + bottom: -2px; + margin: auto; + + display: flex; + gap: 4px; + background-color: light-dark(var(--color-light-1), @dark-blue); + color: @color-text-emphatic; + padding: 4px 6px; + border: 1px solid @color-border; + border-radius: 3px; + align-items: baseline; + width: fit-content; + + h4 { + font-weight: bold; + text-transform: uppercase; + white-space: nowrap; + + &.threshold-label { + font-size: var(--font-size-10); + color: @color-text-emphatic; + } + + &.threshold-value { + font-size: var(--font-size-11); + color: light-dark(@dark, @beige); + } + } + } + } + + header { + grid-area: header; + display: grid; + grid-template: + "name hope" min-content + "subtitle subtitle" min-content + / 1fr min-content; + + .actor-name { + width: 100%; + z-index: 1; + font-size: var(--font-size-20); + color: @color-text-emphatic; + font-weight: bold; + } + + .delete-icon { + font-size: 0.75em; + } + + .subtitle { + grid-area: subtitle; + font-size: var(--font-size-14); + } + + .hope-section { + display: flex; + background-color: light-dark(transparent, @dark-blue); + color: @color-text-emphatic; + padding: 3px 6px; + border: 1px solid @color-border; + border-radius: 3px; + align-items: center; + width: fit-content; + margin-left: auto; + + h4 { + font-size: var(--font-size-12); + font-weight: bold; + text-transform: uppercase; + color: @color-text-emphatic; + margin-right: 3px; + } + + .hope-value { + display: flex; + cursor: pointer; + font-size: var(--font-size-12); + margin-left: 1px; + } + } + } + + .body { + grid-area: body; + display: flex; + align-items: start; + justify-content: space-between; + } + + .resources { + display: flex; + flex-direction: column; + gap: 4px; + + .slot-section { + display: flex; + flex-direction: row; + align-items: stretch; + + .slot-label { + display: flex; + align-items: center; + color: light-dark(@beige, @dark-blue); + background: light-dark(@dark-blue, @golden); + padding: 0 4px; + width: fit-content; + font-weight: bold; + border-radius: 6px 0px 0px 6px; + font-size: var(--font-size-12); + white-space: nowrap; + + .label { + padding-right: 2px; + } + + .value { + font-variant-numeric: tabular-nums; + .current { + display: inline-block; + text-align: end; + width: 2ch; + } + .max { + display: inline-block; + text-align: start; + width: 2ch; + } + } + } + + .slot-bar { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 4px; + + background-color: light-dark(@dark-blue-10, @dark-blue); + color: @color-text-emphatic; + padding: 2px 5px; + border: 1px solid @color-border; + border-radius: 0 6px 6px 0; + width: fit-content; + min-height: 22px; + + .armor-slot { + cursor: pointer; + transition: all 0.3s ease; + font-size: var(--font-size-12); + + .fa-shield-halved { + color: light-dark(@dark-blue-40, @golden-40); + } + } + + .slot { + width: 16px; + height: 10px; + border: 1px solid @color-border; + background: light-dark(@dark-blue-10, @golden-10); + border-radius: 3px; + transition: all 0.3s ease; + cursor: pointer; + + &.filled { + background: light-dark(@dark-blue, @golden); + } + } + } + } + } + + .traits { + background-color: light-dark(@dark-blue-10, @dark-blue); + border: 1px solid @color-border; + border-radius: 6px; + display: grid; + grid-template-columns: 1fr 1fr; + font-size: var(--font-size-12); + padding: 3px 4px; + gap: 3px 7px; + .trait { + display: flex; + justify-content: space-between; + gap: 3px; + .label { + color: @color-text-emphatic; + } + .value { + font-weight: 600; + } + } + } + } + } + + .actors-list.limited { + .actor-resources { + display: flex; + align-items: center; + } + .actor-img-frame { + width: 3rem; + height: 3rem; + } + } + + .actors-dragger { + display: flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + width: 100%; + height: 40px; + border: 1px dashed light-dark(@dark-blue-50, @beige-50); + border-radius: 3px; + color: light-dark(@dark-blue-50, @beige-50); + } +} diff --git a/styles/less/sheets/actors/party/sheet.less b/styles/less/sheets/actors/party/sheet.less index bf589696..852b6cfc 100644 --- a/styles/less/sheets/actors/party/sheet.less +++ b/styles/less/sheets/actors/party/sheet.less @@ -17,8 +17,35 @@ }); .application.sheet.daggerheart.actor.dh-style.party { - .tab.active { - display: flex; - flex-direction: column; + .tab { + flex: 1; + overflow-y: auto; + scrollbar-gutter: stable; + + &.active { + overflow: auto; + display: flex; + flex-direction: column; + } + + .actions-section { + display: flex; + align-items: center; + justify-content: center; + padding: 10px; + margin-bottom: 10px; + gap: 20px; + background-color: light-dark(@dark-blue-10, @golden-10); + + button { + span { + font-size: 12px; + } + } + + .active-action { + animation: glow 0.75s infinite alternate; + } + } } } diff --git a/styles/less/sheets/items/beastform.less b/styles/less/sheets/items/beastform.less index 017c4ef0..100b024a 100644 --- a/styles/less/sheets/items/beastform.less +++ b/styles/less/sheets/items/beastform.less @@ -1,6 +1,4 @@ .application.sheet.daggerheart.dh-style.beastform { - --portrait-size: 130px; - .settings.tab { .advantage-on-section { display: flex; @@ -11,11 +9,4 @@ font-style: italic; } } - .tab.features.active { - display: flex; - flex-direction: column; - gap: 10px; - padding: 8px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); - } } diff --git a/styles/less/sheets/items/feature.less b/styles/less/sheets/items/feature.less index 9166fac1..f3c7cd49 100644 --- a/styles/less/sheets/items/feature.less +++ b/styles/less/sheets/items/feature.less @@ -2,9 +2,17 @@ @import '../../utils/fonts.less'; .application.sheet.daggerheart.dh-style.feature { - --portrait-size: 130px; + .item-sheet-header { + display: flex; + + .profile { + height: 130px; + width: 130px; + } + } section.tab { + height: 400px; overflow-y: auto; } } diff --git a/styles/less/sheets/items/index.less b/styles/less/sheets/items/index.less index 7f9bb684..7c40a2e3 100644 --- a/styles/less/sheets/items/index.less +++ b/styles/less/sheets/items/index.less @@ -1,6 +1,6 @@ -@import './item-sheet-shared.less'; @import './beastform.less'; @import './class.less'; @import './domain-card.less'; @import './feature.less'; -@import './heritage.less'; \ No newline at end of file +@import './heritage.less'; +@import './item-sheet-shared.less'; \ No newline at end of file diff --git a/styles/less/sheets/items/item-sheet-shared.less b/styles/less/sheets/items/item-sheet-shared.less index 63846b8e..5155ad70 100644 --- a/styles/less/sheets/items/item-sheet-shared.less +++ b/styles/less/sheets/items/item-sheet-shared.less @@ -1,4 +1,4 @@ -.item.daggerheart.dh-style:where(.application.sheet) { +.application.sheet.daggerheart.dh-style.item { &.minimized { .attribution-header-label { display: none; @@ -14,22 +14,4 @@ button.plain.inline-control { flex: 0 0 auto; } - - .tab-navigation { - margin-bottom: 0; - } - - /** Default tab stylings */ - .tab.active { - padding-top: 8px; - .with-scroll-shadows(); - - &.effects { - display: flex; - flex-direction: column; - gap: 10px; - padding: 8px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); - } - } } diff --git a/styles/less/ui/chat/ability-use.less b/styles/less/ui/chat/ability-use.less index 9d3cb84e..d028fa7a 100644 --- a/styles/less/ui/chat/ability-use.less +++ b/styles/less/ui/chat/ability-use.less @@ -117,9 +117,7 @@ } .description { - padding: 0; - margin: 8px; - .typography(); + padding: 8px; } .ability-card-footer { @@ -133,11 +131,6 @@ height: 40px; flex: 1 1 calc(50% - 5px); - span { - font-family: @font-body; - font-weight: 700; - } - &:nth-last-child(1):nth-child(odd) { flex-basis: 100%; } diff --git a/styles/less/ui/chat/action.less b/styles/less/ui/chat/action.less index cff617d8..6eeb7a52 100644 --- a/styles/less/ui/chat/action.less +++ b/styles/less/ui/chat/action.less @@ -46,14 +46,9 @@ padding: 0 8px; button { - height: 36px; + height: 40px; flex: 1 1 calc(50% - 5px); - span { - font-family: @font-body; - font-weight: 700; - } - &:nth-last-child(1):nth-child(odd) { flex-basis: 100%; } diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index 1b18a823..4d627e39 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -621,74 +621,16 @@ } .roll-buttons { - margin-top: 8px; display: flex; - flex-direction: column; gap: 5px; + margin-top: 8px; button { height: 32px; - } + flex: 1; - .main-buttons { - display: flex; - gap: 5px; - - button { - flex: 1; - - &.end-button { - flex: 0; - } - } - } - - .extra-button-row { - width: 100%; - display: flex; - gap: 5px; - - .image-container { - position: relative; - display: flex; - align-items: center; - justify-content: center; - - img { - height: 24px; - filter: @dark-filter; - } - - .dice-result { - position: absolute; - font-size: 18px; - color: @beige; - filter: drop-shadow(0 0 1px @light-white); - } - } - - .reload-data { - flex: 1; - display: flex; - align-items: center; - justify-content: center; - border-radius: 5px; - gap: 5px; - cursor: pointer; - padding: 5px; - transition: all 0.3s ease; - color: @golden; - background: @golden-40; - - &.failed-check { - background: @red-40; - color: @red; - } - - &.passed-check { - background: @green-40; - color: @green; - } + &.end-button { + flex: 0; } } } diff --git a/styles/less/ui/countdown/countdown.less b/styles/less/ui/countdown/countdown.less index 4e64d50a..63e539ba 100644 --- a/styles/less/ui/countdown/countdown.less +++ b/styles/less/ui/countdown/countdown.less @@ -22,6 +22,7 @@ pointer-events: all; align-self: flex-end; transition: 0.3s right ease-in-out; + display: flex; flex-direction: column; @@ -32,7 +33,7 @@ background: var(--background); border-radius: 4px; opacity: var(--ui-fade-opacity); - transition: opacity var(--ui-fade-delay) var(--ui-fade-duration); + transition: opacity var(--ui-fade-duration); } &:not(.performance-low, .noblur) { @@ -41,7 +42,6 @@ &:hover::before { opacity: 1; - transition: opacity var(--ui-fade-duration); } #ui-right:has(#effects-display .effect-container) & { @@ -65,31 +65,12 @@ padding: 0 0.5rem; overflow: hidden; font-size: var(--font-size-13); - .window-title { font-family: @font-body; - } - - - .header-type-toggles { flex: 1; - display: flex; - align-items: center; - gap: 4px; - - .header-type { - flex: 1; - border: 1px solid @beige; - border-radius: 12px; - padding: 2px 4px; - text-align: center; - background-color: @dark-blue; - color: @beige; - - &.inactive { - opacity: 0.4; - } - } + } + .header-control + .header-control { + margin-left: 8px; } } @@ -101,23 +82,9 @@ overflow: auto; max-height: 312px; - .countdown-category-container { - display: flex; - flex-direction: column; - gap: 8px; - - &.hidden { - display: none; - } - } - .countdown-container { display: flex; width: 100%; - border-radius: 6px; - background: linear-gradient(-45deg, transparent 30%, light-dark(@dark-blue-40, @golden-40) 35%, transparent 40%); - background-size: 300%; - background-position-x: 100%; &.icon-only { gap: 8px; @@ -138,7 +105,6 @@ display: flex; align-items: center; gap: 16px; - border-radius: 6px; img { width: 2.75rem; diff --git a/styles/less/ui/game-pause/game-pause.less b/styles/less/ui/game-pause/game-pause.less index daf9a1e4..60d08bec 100644 --- a/styles/less/ui/game-pause/game-pause.less +++ b/styles/less/ui/game-pause/game-pause.less @@ -1,34 +1,23 @@ @import '../../utils/mixin.less'; #pause.dh-style { - animation: none; - - img { - width: 125px; - height: 125px; - } - figcaption { - --base-shadow: drop-shadow(2px 2px 2px black); position: absolute; margin-top: 24px; animation: pause-pulse 3s ease-in-out infinite; - font-size: var(--font-size-30); - letter-spacing: 0.18em; - filter: var(--base-shadow); } @keyframes pause-pulse { 0% { - filter: var(--base-shadow) drop-shadow(0 0 5px @secondary-blue); + filter: drop-shadow(0 0 5px @secondary-blue); } 50% { - filter: var(--base-shadow) drop-shadow(0 0 5px @golden-secondary); + filter: drop-shadow(0 0 5px @golden); } 100% { - filter: var(--base-shadow) drop-shadow(0 0 5px @secondary-blue); + filter: drop-shadow(0 0 5px @secondary-blue); } } } \ No newline at end of file diff --git a/styles/less/ui/resources/resources.less b/styles/less/ui/resources/resources.less index 27f11942..3982d990 100644 --- a/styles/less/ui/resources/resources.less +++ b/styles/less/ui/resources/resources.less @@ -1,221 +1,119 @@ :root { - --hotbar-size: 60px; -} - -#interface.theme-dark, -body.theme-dark { - .daggerheart.dh-style.fear-tracker { - --background: url(../assets/parchments/dh-parchment-dark.png); - } -} - -#interface.theme-light, -body.theme-light { - .daggerheart.dh-style.fear-tracker { - --background: url('../assets/parchments/dh-parchment-light.png') no-repeat center; - } -} - -#ui-middle:has(#hotbar.sm), -#ui-middle:has(#hotbar.md.offset) { - #resources { - &.top-center, - &.bottom-center { - width: calc((var(--hotbar-size) * 5) + 32px) !important; - } - } + --shadow-text-stroke: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000; + --fear-animation: background 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease, opacity 0.3s ease; } #resources { - position: static; min-height: calc(var(--header-height) + 4rem); min-width: 4rem; color: #d3d3d3; - pointer-events: all; - padding: var(--spacer-8); - max-width: 540px; - min-width: 100px; - - &::before { - content: ' '; - position: absolute; - inset: 0; - background: var(--background); - border-radius: 8px; - opacity: var(--ui-fade-opacity); - transition: opacity var(--ui-fade-delay) var(--ui-fade-duration); - + transition: var(--fear-animation); + header, + .controls, + .window-resize-handle { + transition: var(--fear-animation); } - - &:hover::before { - opacity: 1; - transition: opacity var(--ui-fade-duration); - } - - &.free { - position: absolute; - } - - &.topCenter, - &.bottomCenter { - margin: 1rem 0; - width: 100% !important; - transform: translateX(var(--offset)); - transition: all 250ms ease; - } - - &.rightTop { - width: 300px !important; - max-width: 300px; - } - - &.leftBottom { - width: 200px !important; - max-width: 200px; - background: transparent; - } - - &:not(.performance-low, .noblur) { - backdrop-filter: blur(5px); - } - - #ui-right:has(#effects-display .effect-container) & { - right: 62px; - } - - #resource-fear { - position: relative; - - &:hover { - .fear-header { - opacity: 1; - height: 18.75px; - visibility: visible; - } - - .resize-handle { - opacity: 1; - } - } - - .fear-header { - display: flex; - gap: 5px; - pointer-events: all; - margin-bottom: 0.5rem; - opacity: 0; - height: 0; - visibility: hidden; - transition: all 0.3s ease; - - .drag-handle { - cursor: grab; - } - - .fear-title { - font-size: var(--font-size-13); - } - } - - .fear-tokens { + .window-content { + padding: 0.5rem; + #resource-fear { display: flex; flex-direction: row; - flex-wrap: wrap; - justify-content: center; gap: 0.5rem 0.25rem; - - .fear-token { - font-size: var(--font-size-16); - border: 1.5px double light-dark(@dark-15, @dark-golden-80); + flex-wrap: wrap; + i { + font-size: var(--font-size-18); + border: 1px solid rgba(0, 0, 0, 0.5); border-radius: 50%; aspect-ratio: 1; display: flex; justify-content: center; align-items: center; - width: 2.5rem; + width: 3rem; background-color: @primary-color-fear; - color: @beige; + -webkit-box-shadow: 0px 0px 5px 1px rgba(0, 0, 0, 0.75); + box-shadow: 0px 0px 5px 1px rgba(0, 0, 0, 0.75); + color: #d3d3d3; flex-grow: 0; - text-shadow: none; - &.inactive { filter: grayscale(1) !important; opacity: 0.5; } } - } - - .resize-handle { - position: absolute; - bottom: -12px; - right: -9px; - cursor: nwse-resize; - opacity: 0; - transition: all 0.3s ease; - } - - - .resource-bar { - display: flex; - flex-direction: column; - align-items: center; - position: relative; - height: 30px; - width: 100%; - - .progress-bar { - position: absolute; - appearance: none; - width: 100%; - height: 100%; - border: 1px solid light-dark(@dark-15, @dark-golden-80); - border-radius: 999px; - z-index: 0; - background: @dark-blue; - - &::-webkit-progress-bar { - border: none; - background: @dark-blue; - border-radius: 999px; - } - &::-webkit-progress-value { - background: linear-gradient(90deg, rgba(2, 0, 38, 1) 0%, rgba(199, 1, 252, 1) 100%); - border-radius: 999px; - } + .controls, + .resource-bar { + border: 2px solid rgb(153 122 79); + background-color: rgb(24 22 46); } - - .label { - margin: auto 0; - z-index: 2; - height: auto; - text-align: center; - font-size: var(--font-size-18); - color: @beige; - } - } - - .controls { - display: flex; - gap: 8px; - justify-content: center; - align-items: center; - margin-top: 0.5rem; - color: light-dark(@dark, @beige); - - .disabled { - opacity: 0.5; - } - } - - &.isGM { - .fear-token { + .controls { + display: flex; + align-self: center; + border-radius: 50%; + align-items: center; + justify-content: center; + width: 30px; + height: 30px; + font-size: var(--font-size-20); cursor: pointer; - transition: box-shadow 0.15s ease; - &:hover { - box-shadow: 0 0 8px @primary-color-fear ; + font-size: 1.5rem; + } + &.disabled { + opacity: 0.5; + } + } + .resource-bar { + display: flex; + justify-content: center; + border-radius: 6px; + font-size: var(--font-size-20); + overflow: hidden; + position: relative; + padding: 0.25rem 0.5rem; + flex: 1; + text-shadow: var(--shadow-text-stroke); + &:before { + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: var(--fear-percent); + max-width: 100%; + background: linear-gradient(90deg, rgba(2, 0, 38, 1) 0%, rgba(199, 1, 252, 1) 100%); + z-index: 0; + border-radius: 4px; + } + span { + position: inherit; + z-index: 1; + } + &.fear { + } + } + &.isGM { + i { + cursor: pointer; + &:hover { + font-size: var(--font-size-20); + } } } } } + button[data-action='close'] { + display: none; + } + &:not(:hover):not(.minimized) { + background: transparent; + box-shadow: unset; + border-color: transparent; + header, + #resource-fear .controls, + .window-resize-handle { + opacity: 0; + } + } + &:has(.fear-bar) { + min-width: 200px; + } } diff --git a/styles/less/utils/colors.less b/styles/less/utils/colors.less index d9358112..bb219ebb 100755 --- a/styles/less/utils/colors.less +++ b/styles/less/utils/colors.less @@ -107,8 +107,6 @@ --dh-input-color-text: @dark; --dh-trait-color-bg: #b1afb6; --dh-trait-color-border: #8e8d96; - --dh-window-button-color-bg: #e8e6e3; - --dh-window-button-color-text: @dark-blue; } } @scope (.theme-dark) to (.themed) { @@ -126,8 +124,6 @@ --dh-input-color-text: @beige; --dh-trait-color-bg: #50433F; --dh-trait-color-border: #927952; - --dh-window-button-color-bg: @deep-black; - --dh-window-button-color-text: @beige; } } diff --git a/styles/less/utils/fonts.less b/styles/less/utils/fonts.less index 72ee1a85..07da3389 100755 --- a/styles/less/utils/fonts.less +++ b/styles/less/utils/fonts.less @@ -10,7 +10,6 @@ --font-size-8: 0.5rem; --font-size-9: 0.5625rem; --font-size-22: 1.375rem; - --font-size-30: 1.875rem; } @font-title: ~"var(--dh-font-title, 'Cinzel Decorative'), serif"; diff --git a/styles/less/utils/mixin.less b/styles/less/utils/mixin.less index 429fb3ef..e2ef85ef 100644 --- a/styles/less/utils/mixin.less +++ b/styles/less/utils/mixin.less @@ -174,10 +174,10 @@ --fade-start: 0; } 10%, 100% { - --fade-start: 14px; + --fade-start: 12px; } 0%, 90% { - --fade-end: 14px; + --fade-end: 12px; } 100% { --fade-end: 0; @@ -198,43 +198,3 @@ transparent 100% ); } - -.stable-scroll-container() { - overflow-y: auto; - scrollbar-gutter: stable; - .with-scroll-shadows(); -} - -/** Typography stylings for most longform text, usually item descriptions */ -.typography() { - h1 { - font-size: var(--font-size-32); - } - h2 { - font-size: var(--font-size-28); - font-weight: 600; - } - h3 { - font-size: var(--font-size-20); - font-weight: 600; - } - h4 { - font-size: var(--font-size-16); - color: light-dark(@dark, @beige); - font-weight: 600; - } - - ul, - ol { - margin: 0.5rem 0; - padding: 0 0 0 1.25rem; - - li { - margin-bottom: 0.25rem; - } - } - - ul { - list-style: disc; - } -} diff --git a/styles/less/ux/tooltip/index.less b/styles/less/ux/tooltip/index.less index 30cb88df..eeec9354 100644 --- a/styles/less/ux/tooltip/index.less +++ b/styles/less/ux/tooltip/index.less @@ -1,130 +1,4 @@ -#tooltip:has(div.daggerheart.dh-style.tooltip.card-style), -aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip), -#tooltip.bordered-tooltip { - .tooltip-title { - font-size: var(--font-size-20); - color: @color-text-emphatic; - font-weight: 700; - } - - .tooltip-description { - font-style: inherit; - text-align: inherit; - width: 100%; - padding: 5px 10px; - position: relative; - margin-top: 5px; - - &::before { - content: ''; - background: @golden; - mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%); - height: 2px; - width: calc(100% - 10px); - } - - &::before { - position: absolute; - top: -5px; - } - } - - .tooltip-separator { - background: @golden; - mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%); - height: 2px; - width: calc(100% - 10px); - margin-bottom: 2px; - } - - .tooltip-tags { - display: flex; - flex-direction: column; - gap: 10px; - width: 100%; - padding: 5px 10px; - position: relative; - max-height: 150px; - overflow-y: auto; - position: relative; - - .tooltip-tag { - display: flex; - gap: 10px; - flex-direction: column; - - .tooltip-tag-label-container { - display: flex; - align-items: center; - gap: 5px; - - img { - width: 40px; - height: 40px; - border-radius: 3px; - } - } - } - } - - .tags { - display: flex; - gap: 5px 10px; - padding-bottom: 4px; - flex-wrap: wrap; - justify-content: center; - - &.advantages { - width: 100%; - padding: 5px 10px; - padding-bottom: 16px; - position: relative; - margin-top: 5px; - - &::before { - content: ''; - background: @golden; - mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%); - height: 2px; - width: calc(100% - 10px); - } - - &::before { - position: absolute; - top: -5px; - } - - .tag { - background: @green-10; - color: @green; - border-color: @green; - } - } - - .tag { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - padding: 3px 5px; - font-size: var(--font-size-12); - font: @font-body; - - background: light-dark(@dark-15, @beige-15); - border: 1px solid light-dark(@dark, @beige); - border-radius: 3px; - } - - .label { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - font-size: var(--font-size-12); - } - } -} - +@import './sheet.less'; @import './armorManagement.less'; @import './battlepoints.less'; @import './bordered-tooltip.less'; diff --git a/styles/less/ux/tooltip/sheet.less b/styles/less/ux/tooltip/sheet.less new file mode 100644 index 00000000..cc4166da --- /dev/null +++ b/styles/less/ux/tooltip/sheet.less @@ -0,0 +1,126 @@ +#tooltip:has(div.daggerheart.dh-style.tooltip.card-style), +aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip), +#tooltip.bordered-tooltip { + .tooltip-title { + font-size: var(--font-size-20); + color: @color-text-emphatic; + font-weight: 700; + } + + .tooltip-description { + font-style: inherit; + text-align: inherit; + width: 100%; + padding: 5px 10px; + position: relative; + margin-top: 5px; + + &::before { + content: ''; + background: @golden; + mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%); + height: 2px; + width: calc(100% - 10px); + } + + &::before { + position: absolute; + top: -5px; + } + } + + .tooltip-separator { + background: @golden; + mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%); + height: 2px; + width: calc(100% - 10px); + margin-bottom: 2px; + } + + .tooltip-tags { + display: flex; + flex-direction: column; + gap: 10px; + width: 100%; + padding: 5px 10px; + position: relative; + max-height: 150px; + overflow-y: auto; + position: relative; + + .tooltip-tag { + display: flex; + gap: 10px; + flex-direction: column; + + .tooltip-tag-label-container { + display: flex; + align-items: center; + gap: 5px; + + img { + width: 40px; + height: 40px; + border-radius: 3px; + } + } + } + } + + .tags { + display: flex; + gap: 5px 10px; + padding-bottom: 16px; + flex-wrap: wrap; + justify-content: center; + + &.advantages { + width: 100%; + padding: 5px 10px; + padding-bottom: 16px; + position: relative; + margin-top: 5px; + + &::before { + content: ''; + background: @golden; + mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%); + height: 2px; + width: calc(100% - 10px); + } + + &::before { + position: absolute; + top: -5px; + } + + .tag { + background: @green-10; + color: @green; + border-color: @green; + } + } + + .tag { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 3px 5px; + font-size: var(--font-size-12); + font: @font-body; + + background: light-dark(@dark-15, @beige-15); + border: 1px solid light-dark(@dark, @beige); + border-radius: 3px; + } + + .label { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + font-size: var(--font-size-12); + } + } +} diff --git a/styles/less/ux/tooltip/tooltip.less b/styles/less/ux/tooltip/tooltip.less index 26ecb5c3..f02499e2 100644 --- a/styles/less/ux/tooltip/tooltip.less +++ b/styles/less/ux/tooltip/tooltip.less @@ -4,7 +4,6 @@ #tooltip:has(div.daggerheart.dh-style.tooltip.card-style), aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip.card-style) { padding: 0; - padding-bottom: 8px; border: none; border-radius: 10px; height: max-content; @@ -135,6 +134,7 @@ aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip.card-style) { background: light-dark(@dark-blue-60, @rustic-brown-80); color: @color-text-emphatic; font-size: 12px; + margin-bottom: 10px; } } diff --git a/system.json b/system.json index 0aafe3f5..a471683b 100644 --- a/system.json +++ b/system.json @@ -2,15 +2,15 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.5.4", + "version": "2.3.3", "compatibility": { "minimum": "14.364", - "verified": "14.365", + "verified": "14.364", "maximum": "14" }, "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.5.4/system.zip", + "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.3.3/system.zip", "authors": [ { "name": "WBHarry" @@ -256,34 +256,34 @@ }, "Item": { "ancestry": { - "htmlFields": ["description", "gmNotes"] + "htmlFields": ["description"] }, "community": { - "htmlFields": ["description", "gmNotes"] + "htmlFields": ["description"] }, "class": { - "htmlFields": ["description", "gmNotes"] + "htmlFields": ["description"] }, "subclass": { - "htmlFields": ["description", "gmNotes"] + "htmlFields": ["description"] }, "feature": { - "htmlFields": ["description", "gmNotes"] + "htmlFields": ["description"] }, "domainCard": { - "htmlFields": ["description", "gmNotes"] + "htmlFields": ["description"] }, "loot": { - "htmlFields": ["description", "gmNotes"] + "htmlFields": ["description"] }, "consumable": { - "htmlFields": ["description", "gmNotes"] + "htmlFields": ["description"] }, "weapon": { - "htmlFields": ["description", "gmNotes"] + "htmlFields": ["description"] }, "armor": { - "htmlFields": ["description", "gmNotes"] + "htmlFields": ["description"] }, "beastform": {} }, diff --git a/templates/actionTypes/areas.hbs b/templates/actionTypes/areas.hbs index 662716f5..2e010c72 100644 --- a/templates/actionTypes/areas.hbs +++ b/templates/actionTypes/areas.hbs @@ -11,10 +11,9 @@ - {{formField ../fields.type value=area.type name=(concat "areas." index ".type") localize=true blank=false}} - {{formField ../fields.shape value=area.shape name=(concat "areas." index ".shape") localize=true blank=false}} - {{formField ../fields.size value=area.size name=(concat "areas." index ".size") localize=true blank=false}} - {{formField ../fields.hasHole value=area.hasHole name=(concat "areas." index ".hasHole") localize=true classes="auto-sized" }} + {{formField ../fields.type value=area.type name=(concat "areas." index ".type") localize=true}} + {{formField ../fields.shape value=area.shape name=(concat "areas." index ".shape") localize=true}} + {{formField ../fields.size value=area.size name=(concat "areas." index ".size") localize=true}} diff --git a/templates/actionTypes/cost.hbs b/templates/actionTypes/cost.hbs index b8661b5b..7a9f33d9 100644 --- a/templates/actionTypes/cost.hbs +++ b/templates/actionTypes/cost.hbs @@ -9,7 +9,7 @@ {{/if}} {{formField ../fields.scalable label="DAGGERHEART.GENERAL.scalable" value=cost.scalable name=(concat "cost." index ".scalable") classes="checkbox" localize=true}} - {{formField ../fields.key choices=(@root.disableOption index @root.costOptions ../source) label="DAGGERHEART.GENERAL.Resource.single" value=cost.key name=(concat "cost." index ".key") localize=true blank=false}} + {{formField ../fields.key choices=(@root.disableOption index @root.costOptions ../source) label="DAGGERHEART.GENERAL.resource" value=cost.key name=(concat "cost." index ".key") localize=true blank=false}} {{formField ../fields.value label="DAGGERHEART.GENERAL.amount" value=cost.value name=(concat "cost." index ".value") localize=true}} {{formField ../fields.step label="DAGGERHEART.GENERAL.step" value=cost.step name=(concat "cost." index ".step") disabled=(not cost.scalable) localize=true}} diff --git a/templates/actionTypes/damage.hbs b/templates/actionTypes/damage.hbs index d430b51f..03300840 100644 --- a/templates/actionTypes/damage.hbs +++ b/templates/actionTypes/damage.hbs @@ -1,114 +1,92 @@ -{{#unless (eq @root.source.type 'healing')}} - - + + + + {{#if (eq @root.source.type 'healing')}} + {{localize "DAGGERHEART.GENERAL.healing"}} + {{else}} {{localize "DAGGERHEART.GENERAL.damage"}} - {{#if source.main}} - - {{else}} - - {{/if}} - - - {{#if source.main}} - - {{#if @root.hasBaseDamage}} - {{formField @root.fields.damage.fields.main.fields.includeBase value=source.main.includeBase name="damage.main.includeBase" classes="checkbox" localize=true }} - {{/if}} - {{#unless (eq @root.source.type 'healing')}} - {{formField baseFields.main.fields.direct value=source.main.direct name=(concat path "damage.main.direct") localize=true classes="checkbox"}} - {{/unless}} - {{#if (and @root.isNPC (not (eq path 'system.attack.')))}} - {{formField baseFields.main.fields.groupAttack value=source.main.groupAttack name=(concat path "damage.main.groupAttack") localize=true classes="select"}} - {{/if}} - - {{> damageData damage=source.main fields=fields.main.fields basePath=(concat path "damage.main")}} - {{#if horde}} - {{> hordeDamage source=source.main fields=fields.main.fields basePath=(concat path "damage.main")}} - {{/if}} - {{#if (ne @root.source.type 'healing')}} - {{formField fields.main.fields.type value=source.main.type name=(concat path "damage.main.type") localize=true}} - {{/if}} {{/if}} - -{{/unless}} + {{#unless (eq path 'system.attack.')}}{{/unless}} + + + {{#if @root.hasBaseDamage}} + {{formField @root.fields.damage.fields.includeBase value=@root.source.damage.includeBase name="damage.includeBase" classes="checkbox" localize=true }} + {{/if}} + {{#unless (eq @root.source.type 'healing')}} + {{formField baseFields.direct value=source.direct name=(concat path "damage.direct") localize=true classes="checkbox"}} + {{/unless}} + {{#if (and @root.isNPC (not (eq path 'system.attack.')))}} + {{formField baseFields.groupAttack value=source.groupAttack name=(concat path "damage.groupAttack") localize=true classes="select"}} + {{/if}} + -{{#unless (eq path 'system.attack.')}} - {{! In the future, consider allowing this even on NPCs}} - - - {{#if (eq @root.source.type 'healing')}} - {{localize "DAGGERHEART.GENERAL.healing"}} - {{else}} - {{localize "DAGGERHEART.ACTIONS.Config.damage.markResources"}} - {{/if}} - {{#unless @root.allDamageTypesUsed}}{{/unless}} - - {{#each source.resources as |dmg key|}} - - - - {{localize (concat "DAGGERHEART.CONFIG.HealingType." dmg.applyTo ".name")}} - {{#unless (or dmg.base ../path)}} - - {{/unless}} - - {{> damageData damage=dmg fields=../fields.resources.element.fields basePath=(concat ../path "damage.resources." dmg.applyTo)}} - - - {{/each}} - -{{/unless}} + {{!-- Handlebars uses Symbol.Iterator to produce index|key. This isn't compatible with our parts object, so we instead use applyTo, which is the same value --}} + {{#each source.parts as |dmg key|}} + + + + {{localize (concat "DAGGERHEART.CONFIG.HealingType." dmg.applyTo ".name")}} + {{#unless (or dmg.base ../path)}} + + {{/unless}} + + + {{#if (and (not @root.isNPC) @root.hasRoll (not dmg.base))}} + {{formField ../fields.resultBased value=dmg.resultBased name=(concat "damage.parts." dmg.applyTo ".resultBased") localize=true classes="checkbox"}} + {{/if}} + {{#if (and (not @root.isNPC) @root.hasRoll (not dmg.base) dmg.resultBased)}} + + + {{localize "DAGGERHEART.GENERAL.withThing" thing=(localize "DAGGERHEART.GENERAL.hope")}} + {{> formula fields=../fields.value.fields type=../fields.type dmg=dmg source=dmg.value target="value" key=dmg.applyTo path=../path}} + + + {{localize "DAGGERHEART.GENERAL.withThing" thing=(localize "DAGGERHEART.GENERAL.fear")}} + {{> formula fields=../fields.valueAlt.fields type=../fields.type dmg=dmg source=dmg.valueAlt target="valueAlt" key=dmg.applyTo path=../path}} + + + {{else}} + {{> formula fields=../fields.value.fields type=../fields.type dmg=dmg source=dmg.value target="value" key=dmg.applyTo path=../path}} + {{/if}} + + {{#if (and (eq dmg.applyTo 'hitPoints') (ne @root.source.type 'healing'))}} + {{formField ../fields.type value=dmg.type name=(concat ../path "damage.parts." dmg.applyTo ".type") localize=true}} + {{/if}} + + {{#if ../horde}} + + {{localize "DAGGERHEART.ACTORS.Adversary.hordeDamage"}} + + + {{formField ../fields.valueAlt.fields.flatMultiplier value=dmg.valueAlt.flatMultiplier name=(concat ../path "damage.parts." dmg.applyTo ".valueAlt.flatMultiplier") label="DAGGERHEART.ACTIONS.Settings.multiplier" classes="inline-child" localize=true }} + {{formField ../fields.valueAlt.fields.dice value=dmg.valueAlt.dice name=(concat ../path "damage.parts." dmg.applyTo ".valueAlt.dice") classes="inline-child" localize=true}} + {{formField ../fields.valueAlt.fields.bonus value=dmg.valueAlt.bonus name=(concat ../path "damage.parts." dmg.applyTo ".valueAlt.bonus") localize=true classes="inline-child"}} + + + {{/if}} + + + + {{/each}} + {{#*inline "formula"}} - {{#unless isBase}} - {{formField fields.custom.fields.enabled value=source.custom.enabled name=(concat basePath ".custom.enabled") classes="checkbox" localize=true}} - {{/unless}} - {{#if source.custom.enabled}} - {{formField fields.custom.fields.formula value=source.custom.formula name=(concat basePath ".custom.formula") localize=true}} - {{else}} - - {{#unless @root.isNPC}} - {{formField fields.multiplier value=source.multiplier name=(concat basePath ".multiplier") localize=true}} - {{/unless}} - {{#if (eq source.multiplier 'flat')}}{{formField fields.flatMultiplier value=source.flatMultiplier name=(concat basePath ".flatMultiplier") localize=true }}{{/if}} - {{formField fields.dice value=source.dice name=(concat basePath ".dice") localize=true}} - {{formField fields.bonus value=source.bonus name=(concat basePath ".bonus") localize=true}} - - {{/if}} - {{#if @root.isNPC}} - - {{/if}} -{{/inline}} - -{{#*inline "damageData"}} - {{#if (and (not @root.isNPC) @root.hasRoll (not damage.base))}} - {{formField fields.resultBased value=damage.resultBased name=(concat basePath ".resultBased") localize=true classes="checkbox"}} - {{/if}} - {{#if (and (not @root.isNPC) @root.hasRoll (not damage.base) damage.resultBased)}} - - - {{localize "DAGGERHEART.GENERAL.withThing" thing=(localize "DAGGERHEART.GENERAL.hope")}} - {{> formula key=damage.applyTo fields=fields.value.fields type=fields.type isBase=damage.base source=damage.value basePath=(concat basePath ".value")}} - - - {{localize "DAGGERHEART.GENERAL.withThing" thing=(localize "DAGGERHEART.GENERAL.fear")}} - {{> formula key=damage.applyTo fields=fields.valueAlt.fields type=fields.type isBase=damage.base source=damage.valueAlt basePath=(concat basePath ".valueAlt")}} - - - {{else}} - {{> formula key=damage.applyTo fields=fields.value.fields type=fields.type isBase=damage.base source=damage.value basePath=(concat basePath ".value")}} - {{/if}} - -{{/inline}} - -{{#*inline "hordeDamage"}} - - {{localize "DAGGERHEART.ACTORS.Adversary.hordeDamage"}} - - - {{formField fields.valueAlt.fields.flatMultiplier value=source.valueAlt.flatMultiplier name=(concat basePath ".valueAlt.flatMultiplier") label="DAGGERHEART.ACTIONS.Settings.multiplier" classes="inline-child" localize=true }} - {{formField fields.valueAlt.fields.dice value=source.valueAlt.dice name=(concat basePath ".valueAlt.dice") classes="inline-child" localize=true}} - {{formField fields.valueAlt.fields.bonus value=source.valueAlt.bonus name=(concat basePath ".valueAlt.bonus") localize=true classes="inline-child"}} - - + {{#unless dmg.base}} + {{formField fields.custom.fields.enabled value=source.custom.enabled name=(concat path "damage.parts." key "." target ".custom.enabled") classes="checkbox" localize=true}} + {{/unless}} + {{#if source.custom.enabled}} + {{formField fields.custom.fields.formula value=source.custom.formula name=(concat path "damage.parts." key "." target ".custom.formula") localize=true}} + {{else}} + + {{#unless @root.isNPC}} + {{formField fields.multiplier value=source.multiplier name=(concat path "damage.parts." key "." target ".multiplier") localize=true}} + {{/unless}} + {{#if (eq source.multiplier 'flat')}}{{formField fields.flatMultiplier value=source.flatMultiplier name=(concat path "damage.parts." key "." target ".flatMultiplier") localize=true }}{{/if}} + {{formField fields.dice value=source.dice name=(concat path "damage.parts." key "." target ".dice") localize=true}} + {{formField fields.bonus value=source.bonus name=(concat path "damage.parts." key "." target ".bonus") localize=true}} + + {{/if}} + {{#if @root.isNPC}} + + {{/if}} {{/inline}} \ No newline at end of file diff --git a/templates/actionTypes/resource.hbs b/templates/actionTypes/resource.hbs index 97304b9a..9c8fc965 100644 --- a/templates/actionTypes/resource.hbs +++ b/templates/actionTypes/resource.hbs @@ -1,7 +1,7 @@ - {{localize "DAGGERHEART.GENERAL.Resource.single"}} + {{localize "DAGGERHEART.GENERAL.resource"}} diff --git a/templates/dialogs/dice-roll/damageSelection.hbs b/templates/dialogs/dice-roll/damageSelection.hbs index e865ebe6..7bcd7063 100644 --- a/templates/dialogs/dice-roll/damageSelection.hbs +++ b/templates/dialogs/dice-roll/damageSelection.hbs @@ -15,7 +15,34 @@ {{/each}} {{/if}} - + + {{#each @root.formula}} + + {{localize "DAGGERHEART.GENERAL.formula"}}: {{roll.formula}} + + {{#with (lookup @root.config.GENERAL.healingTypes applyTo)}} + {{localize label}} + {{/with}} + {{#unless @root.hasHealing}} + {{#if damageTypes}} + {{#each damageTypes as | type | }} + {{#with (lookup @root.config.GENERAL.damageTypes type)}} + + {{/with}} + {{/each}} + {{/if}} + {{/unless}} + + + + + + + {{localize "DAGGERHEART.GENERAL.criticalShort"}} + + + {{/each}} + {{#if damageOptions.groupAttack}} {{localize "DAGGERHEART.ACTIONS.Settings.groupAttack.label"}} @@ -32,45 +59,6 @@ {{/if}} - - {{#if @root.damageFormula}} - {{#with @root.damageFormula}} - - {{localize "DAGGERHEART.GENERAL.formula"}}: {{roll.formula}} - - {{localize "DAGGERHEART.GENERAL.damage"}} - {{#if damageTypes}} - {{#each damageTypes as | type | }} - {{#with (lookup @root.config.GENERAL.damageTypes type)}} - - {{/with}} - {{/each}} - {{/if}} - - - - - - - {{localize "DAGGERHEART.GENERAL.criticalShort"}} - - - {{/with}} - {{/if}} - - {{#each @root.resourceFormulas}} - - {{localize "DAGGERHEART.GENERAL.formula"}}: {{roll.formula}} - - {{#with (lookup @root.config.GENERAL.healingTypes applyTo)}} - {{localize label}} - {{/with}} - - - - - - {{/each}} {{#unless (empty @root.modifiers)}} @@ -88,7 +76,6 @@ {{/each}} {{/unless}} - {{#if directDamage}} diff --git a/templates/dialogs/groupRollDialog/initialization.hbs b/templates/dialogs/groupRollDialog/initialization.hbs index d15e2d24..a01a00bb 100644 --- a/templates/dialogs/groupRollDialog/initialization.hbs +++ b/templates/dialogs/groupRollDialog/initialization.hbs @@ -9,7 +9,7 @@ {{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.members"}} - {{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.selectParticipantsHint"}} + {{"DAGGERHEART.APPLICATIONS.GroupRollSelect.selectParticipantsHint"}} {{#each memberSelection as |member|}} - + {{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.FIELDS.initiator.cost.label"}} - - - - + + + diff --git a/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs b/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs index e8bec150..2a366269 100644 --- a/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs +++ b/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs @@ -1,36 +1,25 @@ -{{#if damage.main}} - {{> damage roll=damage.main label=(localize "DAGGERHEART.GENERAL.damage") memberKey=key}} -{{/if}} - -{{#each damage.resources as |roll key|}} - {{> damage roll=roll label=(localize (concat "DAGGERHEART.CONFIG.HealingType." key ".name")) memberKey=../key isResource="true" }} -{{/each}} - -{{#*inline "damage"}} +{{#each damage as |damage key|}} - {{label}}: - {{roll.total}} + {{localize (concat "DAGGERHEART.CONFIG.HealingType." key ".name")}}: + {{damage.total}} - - - {{#each roll.dice}} - {{#each results as |result index|}} - {{#if result.active}} - - {{result.result}} - - - {{/if}} + {{#each damage.parts as |part|}} + + {{#each part.dice as |dice index|}} + + {{dice.total}} + + + {{#unless @last}} + + + {{/unless}} {{/each}} - {{#unless @last}} - + - {{/unless}} - {{/each}} - {{#if roll.modifierTotal}} - {{#if roll.dice.length}}{{#if (gte roll.modifierTotal 0)}}+{{else}}-{{/if}}{{/if}} - {{positive roll.modifierTotal}} - {{/if}} - + {{#if part.modifierTotal}} + {{#if part.dice.length}}{{#if (gte part.modifierTotal 0)}}+{{else}}-{{/if}}{{/if}} + {{positive part.modifierTotal}} + {{/if}} + + {{/each}} -{{/inline}} \ No newline at end of file +{{/each}} \ No newline at end of file diff --git a/templates/dialogs/tagTeamDialog/result.hbs b/templates/dialogs/tagTeamDialog/result.hbs index 88f579a6..151c8c87 100644 --- a/templates/dialogs/tagTeamDialog/result.hbs +++ b/templates/dialogs/tagTeamDialog/result.hbs @@ -6,19 +6,19 @@ {{#if hintText}} {{localize hintText}} {{else}} - {{#if joinedRoll.rollData}} + {{#if joinedRoll.roll}} {{localize "DAGGERHEART.GENERAL.dualityRoll"}} - {{joinedRoll.rollData.total}} + {{joinedRoll.roll.total}} {{localize "DAGGERHEART.GENERAL.withThing" thing=joinedRoll.roll.totalLabel}} {{/if}} - {{#if joinedRoll.damageRollData}} + {{#if joinedRoll.rollData.options.hasDamage}} {{localize "DAGGERHEART.GENERAL.damage"}} - {{#each joinedRoll.damageRollData.types as |damage key|}} + {{#each joinedRoll.rollData.options.damage as |damage key|}} {{localize (concat "DAGGERHEART.CONFIG.HealingType." key ".name")}} {{damage.total}} diff --git a/templates/dialogs/tagTeamDialog/tagTeamMember.hbs b/templates/dialogs/tagTeamDialog/tagTeamMember.hbs index 7758979b..7510422f 100644 --- a/templates/dialogs/tagTeamDialog/tagTeamMember.hbs +++ b/templates/dialogs/tagTeamDialog/tagTeamMember.hbs @@ -64,10 +64,7 @@ {{#if roll}} - - {{roll.total}} - {{#if roll.isCritical}}{{roll.totalLabel}}{{else}}{{localize "DAGGERHEART.GENERAL.withThing" thing=roll.totalLabel}}{{/if}} - + {{roll.total}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.totalLabel}} {{roll.dHope.total}} @@ -103,12 +100,15 @@ - - - + + {{#if damage}} + + + + {{/if}} - {{#if damage.active}} + {{#if damage}} {{#if useCritDamage}} {{> "systems/daggerheart/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs" damage=critDamage isCritical=true }} {{else}} diff --git a/templates/settings/appearance-settings/main.hbs b/templates/settings/appearance-settings/main.hbs index 324ea653..32dd9e63 100644 --- a/templates/settings/appearance-settings/main.hbs +++ b/templates/settings/appearance-settings/main.hbs @@ -8,10 +8,6 @@ value=setting.displayFear localize=true}} {{formGroup - fields.fearPosition - value=setting.fearPosition - localize=true}} - {{formGroup fields.displayCountdownUI value=setting.displayCountdownUI localize=true}} diff --git a/templates/settings/automation-settings/roll.hbs b/templates/settings/automation-settings/roll.hbs index a0b19ee4..dc65f8ae 100644 --- a/templates/settings/automation-settings/roll.hbs +++ b/templates/settings/automation-settings/roll.hbs @@ -18,7 +18,6 @@ {{localize (concat "DAGGERHEART.SETTINGS.Automation.FIELDS.roll." field.name ".hint")}} {{/each}} - {{formGroup settingFields.schema.fields.reload value=settingFields.reload localize=true}} diff --git a/templates/sheets-settings/action-settings/effect.hbs b/templates/sheets-settings/action-settings/effect.hbs index 67017a5a..567cb81c 100644 --- a/templates/sheets-settings/action-settings/effect.hbs +++ b/templates/sheets-settings/action-settings/effect.hbs @@ -5,7 +5,7 @@ > {{#if fields.roll}}{{> 'systems/daggerheart/templates/actionTypes/roll.hbs' fields=fields.roll.fields source=source.roll}}{{/if}} {{#if fields.save}}{{> 'systems/daggerheart/templates/actionTypes/save.hbs' fields=fields.save.fields source=source.save}}{{/if}} - {{#if fields.damage}}{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=fields.damage.fields source=source.damage baseFields=fields.damage.fields }}{{/if}} + {{#if fields.damage}}{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=fields.damage.fields.parts.element.fields source=source.damage baseFields=fields.damage.fields }}{{/if}} {{#if fields.macro}}{{> 'systems/daggerheart/templates/actionTypes/macro.hbs' fields=fields.macro source=source.macro}}{{/if}} {{#if fields.effects}}{{> 'systems/daggerheart/templates/actionTypes/effect.hbs' fields=fields.effects.element.fields source=source.effects}}{{/if}} {{#if fields.beastform}}{{> 'systems/daggerheart/templates/actionTypes/beastform.hbs' fields=fields.beastform.fields source=source.beastform}}{{/if}} diff --git a/templates/sheets-settings/adversary-settings/attack.hbs b/templates/sheets-settings/adversary-settings/attack.hbs index f81f0477..41960032 100644 --- a/templates/sheets-settings/adversary-settings/attack.hbs +++ b/templates/sheets-settings/adversary-settings/attack.hbs @@ -22,5 +22,5 @@ {{formGroup systemFields.criticalThreshold value=document._source.system.criticalThreshold label="DAGGERHEART.ACTIONS.Settings.criticalThreshold" name="system.criticalThreshold" localize=true}} - {{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields source=document.system.attack.damage path="system.attack." baseFields=systemFields.attack.fields.damage.fields horde=(eq document._source.system.type 'horde')}} + {{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." baseFields=systemFields.attack.fields.damage.fields horde=(eq document._source.system.type 'horde')}} \ No newline at end of file diff --git a/templates/sheets-settings/adversary-settings/features.hbs b/templates/sheets-settings/adversary-settings/features.hbs index 1cab8cfe..2f2f5f47 100644 --- a/templates/sheets-settings/adversary-settings/features.hbs +++ b/templates/sheets-settings/adversary-settings/features.hbs @@ -3,31 +3,27 @@ data-tab='{{tabs.features.id}}' data-group='{{tabs.features.group}}' > - {{#each featureGroups as |group|}} - - - {{group.label}} - - - - - - {{#each group.features as |feature|}} - {{> 'daggerheart.inventory-item' - item=feature - type='feature' - actorType=@root.document.type - hideTags=true - hideContextMenu=true - hideResources=true - showActions=false - hideTooltip=true - }} - {{/each}} - - - {{/each}} - - {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}} - + + {{localize "DOCUMENT.New" type=(localize "TYPES.Item.feature")}} + + + {{localize tabs.features.label}} + + {{#each @root.features as |feature|}} + + + + {{feature.name}} + + + + + + + {{/each}} + + + {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}} + + \ No newline at end of file diff --git a/templates/sheets-settings/environment-settings/features.hbs b/templates/sheets-settings/environment-settings/features.hbs index 1cab8cfe..579fe74e 100644 --- a/templates/sheets-settings/environment-settings/features.hbs +++ b/templates/sheets-settings/environment-settings/features.hbs @@ -3,31 +3,24 @@ data-tab='{{tabs.features.id}}' data-group='{{tabs.features.group}}' > - {{#each featureGroups as |group|}} - - - {{group.label}} - - - - - - {{#each group.features as |feature|}} - {{> 'daggerheart.inventory-item' - item=feature - type='feature' - actorType=@root.document.type - hideTags=true - hideContextMenu=true - hideResources=true - showActions=false - hideTooltip=true - }} - {{/each}} - - - {{/each}} - - {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}} - + + {{localize "DOCUMENT.New" type=(localize "TYPES.Item.feature")}} + + + {{localize tabs.features.label}} + + {{#each @root.features as |feature|}} + + + + {{feature.name}} + + + + + + + {{/each}} + + \ No newline at end of file diff --git a/templates/sheets-settings/npc-settings/features.hbs b/templates/sheets-settings/npc-settings/features.hbs index 1cab8cfe..2f2f5f47 100644 --- a/templates/sheets-settings/npc-settings/features.hbs +++ b/templates/sheets-settings/npc-settings/features.hbs @@ -3,31 +3,27 @@ data-tab='{{tabs.features.id}}' data-group='{{tabs.features.group}}' > - {{#each featureGroups as |group|}} - - - {{group.label}} - - - - - - {{#each group.features as |feature|}} - {{> 'daggerheart.inventory-item' - item=feature - type='feature' - actorType=@root.document.type - hideTags=true - hideContextMenu=true - hideResources=true - showActions=false - hideTooltip=true - }} - {{/each}} - - - {{/each}} - - {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}} - + + {{localize "DOCUMENT.New" type=(localize "TYPES.Item.feature")}} + + + {{localize tabs.features.label}} + + {{#each @root.features as |feature|}} + + + + {{feature.name}} + + + + + + + {{/each}} + + + {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}} + + \ No newline at end of file diff --git a/templates/sheets/activeEffect/changes.hbs b/templates/sheets/activeEffect/changes.hbs index 4d33d8b4..37feb845 100644 --- a/templates/sheets/activeEffect/changes.hbs +++ b/templates/sheets/activeEffect/changes.hbs @@ -14,7 +14,7 @@ {{/each}} - + {{localize "DAGGERHEART.GENERAL.armor"}} diff --git a/templates/sheets/activeEffect/settings.hbs b/templates/sheets/activeEffect/settings.hbs index 60df488b..09b78856 100644 --- a/templates/sheets/activeEffect/settings.hbs +++ b/templates/sheets/activeEffect/settings.hbs @@ -1,5 +1,5 @@ - + {{localize "DAGGERHEART.ACTIVEEFFECT.Config.stacking.title"}} @@ -13,19 +13,14 @@ {{/if}} - - - {{localize "DAGGERHEART.ACTIVEEFFECT.Config.rangeDependence.title"}} - - + + {{localize "DAGGERHEART.ACTIVEEFFECT.Config.rangeDependence.title"}} - {{#if source.system.rangeDependence}} - {{formGroup systemFields.rangeDependence.fields.type value=source.system.rangeDependence.type localize=true }} - {{formGroup systemFields.rangeDependence.fields.target value=source.system.rangeDependence.target localize=true }} - {{formGroup systemFields.rangeDependence.fields.range value=source.system.rangeDependence.range localize=true }} - {{/if}} + {{formGroup systemFields.rangeDependence.fields.enabled value=source.system.rangeDependence.enabled localize=true }} + {{formGroup systemFields.rangeDependence.fields.type value=source.system.rangeDependence.type localize=true }} + {{formGroup systemFields.rangeDependence.fields.target value=source.system.rangeDependence.target localize=true }} + {{formGroup systemFields.rangeDependence.fields.range value=source.system.rangeDependence.range localize=true }} - {{localize "EFFECT.DURATION.Label"}} diff --git a/templates/sheets/actors/adversary/features.hbs b/templates/sheets/actors/adversary/features.hbs index 05e95737..3b495e74 100644 --- a/templates/sheets/actors/adversary/features.hbs +++ b/templates/sheets/actors/adversary/features.hbs @@ -1,15 +1,14 @@ - - {{#each @root.features as |item|}} - {{> "daggerheart.inventory-item" - item=item - type="feature" - actorType=@root.document.type - hideContextMenu=true - hideModifyControls=true - showActions=@root.editable - }} - {{/each}} + + {{> 'daggerheart.inventory-items' + title=tabs.features.label + type='feature' + collection=@root.features + hideContextMenu=true + hideModifyControls=true + canCreate=@root.editable + showActions=@root.editable + }} \ No newline at end of file diff --git a/templates/sheets/actors/adversary/notes.hbs b/templates/sheets/actors/adversary/notes.hbs index d329d318..a5c3f706 100644 --- a/templates/sheets/actors/adversary/notes.hbs +++ b/templates/sheets/actors/adversary/notes.hbs @@ -1,9 +1,13 @@ - {{formInput notes.field value=notes.value enriched=notes.enriched toggled=true}} + + {{localize tabs.notes.label}} + {{formInput notes.field value=notes.value enriched=notes.enriched toggled=true}} + + {{#if (and showAttribution document.system.attribution.artist)}} {{localize "DAGGERHEART.GENERAL.artistAttribution" artist=document.system.attribution.artist}} {{/if}} diff --git a/templates/sheets/actors/adversary/sidebar.hbs b/templates/sheets/actors/adversary/sidebar.hbs index 213c96ee..d2fca5f1 100644 --- a/templates/sheets/actors/adversary/sidebar.hbs +++ b/templates/sheets/actors/adversary/sidebar.hbs @@ -1,102 +1,100 @@ -
When the Flickerfly makes an attack, the target’s Evasion is halved against the attack.
When the Flickerfl y makes an attack, the target’s Evasion is halved against the attack.
When you succeed on an attack against a target within Melee range, you can spend a Hope to clamp that opponent in your jaws, making them temporarily Restrained and Vulnerable.
Spend a Fear to summon a @UUID[Compendium.daggerheart.adversaries.Actor.sRn4bqerfARvhgSV]{Minor Chaos Elemental} drawn to the echoes of violence and discord. They appear within Far range of a chosen PC and immediately take the spotlight.
What color does the grass turn as the elemental appears? How does the chaos warp insects and small wildlife within the grove?
When a PC starts the ambush on unsuspecting adversaries, you lose 2 Fear and the first attack roll a PC makes has advantage.
What are the adversaries in the middle of doing when the ambush starts? How does this impact their approach to the fight?
When an adversary is defeated, you can spend a Fear to have a stray attack from a siege weapon hit a point on the battlefield. All targets within Very Close range of that point must make an Agility Reaction Roll.
Targets who fail take 3d8+3 physical or magic damage and must mark a Stress.
Targets who succeed must mark a Stress.
What debris is scattered by the attack? What is broken by the strike that can’t be easily mended?
Previous climbers left behind large metal rods that climbers can use to aid their ascent. If a PC using the pitons fails an action roll to climb, they can mark a Stress instead of ticking the countdown up.
What do the shape and material of these pitons tell you about the previous climbers? How far apart are they from one another?
Spend a Fear to have a PC’s handhold fail, plummeting them toward the ground. If they aren’t saved on the next action, they hit the ground and tick up the countdown by 2. The PC takes 1d12 physical damage if the countdown is between 8 and 12, 2d12 between 4 and 7, and 3d12 at 3 or lower.
How can you tell many others have fallen here before? What lives in these walls that might try to scare adventurers into falling for an easy meal?
A portion of the ritual’s power is diverted into a cult member to fight off interlopers. Choose one adversary to become Imbued with terrible magic until the scene ends or they’re defeated. An Imbued adversary immediately takes the spotlight and gains one of the following benefits, or all three if you spend a Fear:
They gain advantage on all attacks.
They deal an extra 1d10 damage on a successful attack.
They gain the following feature: Relentless (2) - Passive. This adversary can be spotlighted up to two times per GM turn. Spend Fear as usual to spotlight them.
How does the enemy change in appearance? What fears do their blows bring to the surface?
An Imbued adversary immediately takes the spotlight and gains one of the following benefits, or all three if you spend a Fear:
A PC who takes a rest in the Hallowed Temple automatically clears all HP.
What does the incense smell like? What kinds of songs do the acolytes sing?
When the PCs have trespassed, blasphemed, or offended the clergy, you can spend a Fear to summon a @UUID[Compendium.daggerheart.adversaries.Actor.r1mbfSSwKWdcFdAU]{High Seraph} and [[/r 1d4]] @UUID[Compendium.daggerheart.adversaries.Actor.B4LZcGuBAHzyVdzy]{Bladed Guard} within Close range of the senior priest to reinforce their will.
What symbols or icons do they bear that signal they are anointed agents of the divinity? Who leads the group and what led them to this calling?
Spend a Fear to manifest the echo of a past disaster that ravaged the city. Activate a Progress Countdown (5) as the disaster replays around the PCs. To complete the countdown and escape the catastrophe, the PCs must overcome threats such as rampaging fires, stampeding civilians, collapsing buildings, or crumbling streets, while recalling history and finding clues to escape the inevitable.
Is this the disaster that led the city to be abandoned? What is known about this disaster and how could that help the PCs escape?
Spend a Fear to tick down a long-term countdown related to the empire’s agenda by [[/r 1d4]]. If this triggers the countdown, a proclamation related to the agenda is announced at court as the plan is executed.
What display of power or transfer of wealth was needed to expedite this plan? Whose lives were disrupted or upended to make this happen?
A feature or action that clears HP requires spending a Hope to use. If it already costs Hope, a PC must spend an additional Hope.
What does it feel like to try to heal in a place so antithetical to life?
All targets within Close range of a point you choose in this environment must succeed on an Agility Reaction Roll or take 4d8+8 physical damage from skeletal shrapnel as part of the ossuary detonates around them.
What ancient skeletal architecture is destroyed? What bones stick in your armor?
Spend a Fear to summon [[/r 1d6]] @UUID[Compendium.daggerheart.adversaries.Actor.gP3fWTLzSFnpA8EJ]{Rotted Zombie}, two @UUID[Compendium.daggerheart.adversaries.Actor.CP6iRfHdyFWniTHY]{Perfected Zombie}, or a @UUID[Compendium.daggerheart.adversaries.Actor.YhJrP7rTBiRdX5Fp]{Zombie Legion}, who appear at Close range of a chosen PC.
Who were these people before they became the necromancer’s pawns? What vestiges of those lives remain for the heroes to see?
Spend a Fear as a mage from one side uses large-scale destructive magic. Pick a point on the battlefield within Very Far range of the mage. All targets within Close range of that point must make an Agility Reaction Roll. Targets who fail take 3d12+8 magic damage and must mark a Stress.
What form does the attack take—fireball raining acid a storm of blades? What tactical objective is this attack meant to accomplish and what comes next?
Add this Secondary Weapon's tier + 1 to your primary weapon against targets within Melee range
Your allies gain a +1 bonus to Strength.
When an adversary marks 1 or more Hit Points, they must also mark a Stress.
When you or an ally takes damage from an attack beyond Melee range, reduce the damage by 1d8.
{{localize (concat "DAGGERHEART.SETTINGS.Automation.FIELDS.roll." field.name ".hint")}}