diff --git a/.editorconfig b/.editorconfig index 8bbc2b52..6cfef2fc 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,5 @@ [*] indent_size = 4 indent_style = spaces +[*.yml] +indent_size = 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..fd9b922e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,42 @@ +name: Project CI + +on: + pull_request: + branches: [main] + push: + branches: [main] + workflow_dispatch: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [24.x] + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Cache NPM Deps + id: cache-npm + uses: actions/cache@v3 + with: + path: node_modules/ + key: npm-${{ hashFiles('package-lock.json') }} + + - name: Install NPM Deps + if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }} + run: npm ci + + - name: Lint + run: npm run lint \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e245c7fa..553a1a17 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -35,7 +35,7 @@ jobs: env: version: ${{steps.get_version.outputs.version-without-v}} url: https://github.com/${{github.repository}} - manifest: https://raw.githubusercontent.com/${{github.repository}}/main/system.json + manifest: https://raw.githubusercontent.com/${{github.repository}}/v14/system.json download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/system.zip # Create a zip file with all files required by the module to add to the release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b9099005..261c26bd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,78 +1,9 @@ -# Contributing to Foundryborne +# Contributing to Daggerheart -Welcome! This is a community-driven project to bring [Daggerheart](https://www.daggerheart.com/) to [FoundryVTT](https://foundryvtt.com/) as a full system. We're excited to have you here and appreciate your interest in contributing. +Thank you for your interest in contributing to the Foundryborne project! ---- +To ensure that all contributions align with our project goals and architectural standards, we ask that you **do not submit outside contributions without first receiving feedback from the development team.** -## 🀝 How to Contribute +If you have an idea or a fix you'd like to contribute, please start a discussion or open an issue first. We'd love to hear from you and collaborate on the best way to move forward! -We welcome contributions of all kinds: - -- Bug reports -- Feature suggestions -- Code contributions -- UI/UX mockups -- Documentation improvements -- Questions and discussions - -Please be respectful and collaborative β€” we’re all here to build something great together. - -### Community Translations - -Please note that we are not accepting community translations in the main project. Instead, community translations should be published as a module. - ---- - -## 🧭 General Guidelines - -- **Use GitHub Issues** to report bugs or propose features -- **Start a Discussion** for larger ideas or questions -- **Open a Pull Request** once you've confirmed your work aligns with project direction -- **Keep things modular and maintainable** β€” if you're not sure how to structure something, ask! -- **Orient your code on existing examples**, and feel free to suggest a standard if it makes things clearer - ---- - -## πŸ—‚οΈ Project Structure - -Please try to follow the general logic of the existing code when submitting PRs. - -We encourage contributors to leave comments or open Discussions when proposing structural or organizational changes. - ---- - -## 🧾 Issue & PR Best Practices - -**For Issues:** - -- Use clear, descriptive titles -- Provide a concise explanation of the problem or idea -- Include reproduction steps or example scenarios if it's a bug -- Add screenshots or logs if helpful - -**For Pull Requests:** - -- Use a clear title summarizing the change -- Provide a brief description of what your code does and why -- Link to any related Issues -- Keep PRs focused β€” smaller is better - ---- - -## πŸ”– Labels and Boards - -We use GitHub labels to help organize contributions. If your issue or PR relates to a specific category, feel free to tag it. There is also a GitHub Project Board to help track active work and priorities. - ---- - -## πŸ“£ Communication - -Discussions are currently happening on GitHub β€” in Issues, PRs, and [GitHub Discussions](https://github.com/Foundryborne/daggerheart/discussions). You're welcome to use any of these, though we may consolidate to one in the future. - ---- - -## πŸ€— Thank You! - -Whether you're fixing a typo or designing entire mechanics β€” every contribution matters. Thank you for helping bring _Daggerheart_ to life in FoundryVTT through **Foundryborne**! - -πŸΈπŸ› οΈ +Thank you for your understanding and support. diff --git a/daggerheart.mjs b/daggerheart.mjs index 43aafce4..e25f1b09 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -32,6 +32,11 @@ CONFIG.Dice.daggerheart = { FateRoll: FateRoll }; +CONFIG.RegionBehavior.dataModels = { + ...CONFIG.RegionBehavior.dataModels, + ...data.regionBehaviors +}; + Object.assign(CONFIG.Dice.termTypes, dice.diceTypes); CONFIG.Actor.documentClass = documents.DhpActor; @@ -355,6 +360,8 @@ Hooks.on(CONFIG.DH.HOOKS.hooksConfig.groupRollStart, async data => { }); const updateActorsRangeDependentEffects = async token => { + if (!token) return; + const rangeMeasurement = game.settings.get( CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..ce2bb86f --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,14 @@ +import globals from 'globals'; +import { defineConfig } from 'eslint/config'; +import prettier from 'eslint-plugin-prettier'; + +export default defineConfig([ + { files: ['**/*.{js,mjs,cjs}'], languageOptions: { globals: globals.browser } }, + { plugins: { prettier } }, + { + files: ['**/*.{js,mjs,cjs}'], + rules: { + 'prettier/prettier': 'error' + } + } +]); diff --git a/lang/en.json b/lang/en.json index 65323790..2efd6d7b 100755 --- a/lang/en.json +++ b/lang/en.json @@ -74,9 +74,7 @@ "name": "Summon", "tooltip": "Create tokens in the scene.", "error": "You do not have permission to summon tokens or there is no active scene.", - "invalidDrop": "You can only drop Actor entities to summon.", - "chatMessageTitle": "Test2", - "chatMessageHeaderTitle": "Summoning" + "invalidDrop": "You can only drop Actor entities to summon." }, "transform": { "name": "Transform", @@ -111,11 +109,18 @@ "customFormula": "Custom Formula", "formula": "Formula" }, + "area": { + "sectionTitle": "Areas", + "shape": "Shape", + "size": "Size" + }, "displayInChat": "Display in chat", "deleteTriggerTitle": "Delete Trigger", "deleteTriggerContent": "Are you sure you want to delete the {trigger} trigger?", "advantageState": "Advantage State", - "damageOnSave": "Damage on Save" + "damageOnSave": "Damage on Save", + "useDefaultItemValues": "Use default Item values", + "itemDamageIsUsed": "Item Damage Is Used" }, "RollField": { "diceRolling": { @@ -130,7 +135,7 @@ "attackModifier": "Attack Modifier", "attackName": "Attack Name", "criticalThreshold": "Critical Threshold", - "includeBase": { "label": "Include Item Damage" }, + "includeBase": { "label": "Use Item Damage" }, "groupAttack": { "label": "Group Attack" }, "multiplier": "Multiplier", "saveHint": "Set a default Trait to enable Reaction Roll. It can be changed later in Reaction Roll Dialog.", @@ -163,7 +168,8 @@ "rangeDependence": { "title": "Range Dependence" }, - "stacking": { "title": "Stacking" } + "stacking": { "title": "Stacking" }, + "targetDispositions": "Affected Dispositions" }, "RangeDependance": { "hint": "Settings for an optional distance at which this effect should activate", @@ -210,7 +216,13 @@ "type": { "label": "Type" } }, "hordeDamage": "Horde Damage", - "horderHp": "Horde/HP" + "horderHp": "Horde/HP", + "adversaryReactionRoll": { + "headerTitle": "Adversary Reaction Roll" + } + }, + "Base": { + "CannotAddType": "Cannot add {itemType} items to {actorType} actors." }, "Character": { "advantageSources": { @@ -235,6 +247,8 @@ }, "defaultHopeDice": "Default Hope Dice", "defaultFearDice": "Default Fear Dice", + "defaultAdvantageDice": "Default Advantage Dice", + "defaultDisadvantageDice": "Default Disadvantage Dice", "disadvantageSources": { "label": "Disadvantage Sources", "hint": "Add single words or short text as reminders and hints of what a character has disadvantage on." @@ -333,7 +347,8 @@ "minor": "MIN", "major": "MAJ", "severe": "SEV" - } + }, + "triggerRestContent": "This will trigger a dialog to players make their downtime moves. Are you sure?" } }, "APPLICATIONS": { @@ -467,6 +482,10 @@ "defaultOwnershipTooltip": "The default player ownership of countdowns", "hideNewCountdowns": "Hide New Countdowns" }, + "CreateItemDialog": { + "createItem": "Create Item", + "browseCompendium": "Browse Compendium" + }, "DaggerheartMenu": { "title": "GM Tools", "refreshFeatures": "Refresh Features", @@ -681,6 +700,12 @@ "noPlayers": "No players to assign ownership to", "default": "Default Ownership" }, + "PendingReactionsDialog": { + "title": "Pending Reaction Rolls Found", + "unfinishedRolls": "Some Tokens still need to roll their Reaction Roll.", + "confirmation": "Are you sure you want to continue ?", + "warning": "Undone reaction rolls will be considered as failed" + }, "ReactionRoll": { "title": "Reaction Roll: {trait}" }, @@ -706,7 +731,7 @@ "FIELDS": { "initiator": { "memberId": { "label": "Initiating Character" }, - "cost": { "label": "Initiation Cost" } + "cost": { "label": "Hope Cost" } } }, "leaderTitle": "Initiating Character", @@ -735,11 +760,11 @@ }, "GroupRollSelect": { "title": "Group Roll", + "aidingCharacters": "Aiding Characters", "leader": "Leader", "leaderRoll": "Leader Roll", "openDialogForAll": "Open Dialog For All", "startGroupRoll": "Start Group Roll", - "cancelGroupRoll": "Cancel", "finishGroupRoll": "Finish Group Roll", "cancelConfirmTitle": "Cancel Group Roll", "cancelConfirmText": "Are you sure you want to cancel the Group Roll? This will close it for all other players too." @@ -764,6 +789,11 @@ "session": "Next Session", "custom": "Custom" }, + "ActionAutomationChoices": { + "never": "Never", + "showDialog": "Show Dialog Only", + "always": "Always" + }, "AdversaryTrait": { "relentless": { "name": "Relentless", @@ -1293,6 +1323,11 @@ "on": "On", "onWithToggle": "On With Toggle" }, + "SceneRangeMeasurementTypes": { + "disable": "Disable Daggerheart Range Measurement", + "default": "Default", + "custom": "Custom" + }, "SelectAction": { "selectType": "Select Action Type", "selectAction": "Action Selection" @@ -1992,6 +2027,10 @@ "hint": "Multiply any damage dealt to you by this number" } }, + "Battlepoints": { + "full": "Battlepoints", + "short": "BP" + }, "Bonuses": { "rest": { "downtimeAction": "Downtime Action", @@ -2402,10 +2441,13 @@ "maxWithThing": "Max {thing}", "missingDragDropThing": "Drop {thing} here", "multiclass": "Multiclass", + "name": "Name", "newCategory": "New Category", "newThing": "New {thing}", + "next": "Next", "none": "None", "noTarget": "No current target", + "optionalThing": "Optional {thing}", "partner": "Partner", "player": { "single": "Player", @@ -2432,9 +2474,11 @@ "rollDamage": "Roll Damage", "rollWith": "{roll} Roll", "save": "Save", + "saveSettings": "Save Settings", "scalable": "Scalable", "scars": "Scars", "situationalBonus": "Situational Bonus", + "searchPlaceholder": "Search...", "spent": "Spent", "step": "Step", "stress": "Stress", @@ -2585,8 +2629,14 @@ }, "Weapon": { "weaponType": "Weapon Type", - "primaryWeapon": "Primary Weapon", - "secondaryWeapon": "Secondary Weapon" + "primaryWeapon": { + "full": "Primary Weapon", + "short": "Primary" + }, + "secondaryWeapon": { + "full": "Secondary Weapon", + "short": "Secondary" + } } }, "MACROS": { @@ -2840,6 +2890,10 @@ } }, "Keybindings": { + "partySheet": { + "name": "Toggle Party Sheet", + "hint": "Open or close the active party's sheet" + }, "spotlight": { "name": "Spotlight Combatant", "hint": "Move the spotlight to a hovered or selected token that's present in an active encounter" @@ -3010,6 +3064,9 @@ "resourceRoll": { "playerMessage": "{user} rerolled their {name}" }, + "saveRoll": { + "reactionRollAllTargets": "Reaction Roll All Targets" + }, "tagTeam": { "title": "Tag Team", "membersTitle": "Members" @@ -3038,9 +3095,9 @@ }, "ItemBrowser": { "title": "Daggerheart Compendium Browser", + "windowTitle": "Compendium Browser", "hint": "Select a Folder in sidebar to start browsing through the compendium", "browserSettings": "Browser Settings", - "searchPlaceholder": "Search...", "columnName": "Name", "tooltipFilters": "Filters", "tooltipErase": "Erase", @@ -3076,7 +3133,7 @@ "weapons": "Weapons", "armors": "Armors", "consumables": "Consumables", - "loots": "Loots" + "loots": "Loot" } }, "Notifications": { @@ -3171,6 +3228,9 @@ "companion": "Level {level} - {partner}", "companionNoPartner": "No Partner", "duplicateToNewTier": "Duplicate to New Tier", + "activateParty": "Make Active Party", + "partyIsActive": "Active", + "createAdversary": "Create Adversary", "pickTierTitle": "Pick a new tier for this adversary" }, "daggerheartMenu": { @@ -3182,6 +3242,7 @@ "Tooltip": { "disableEffect": "Disable Effect", "enableEffect": "Enable Effect", + "edit": "Edit", "openItemWorld": "Open Item World", "openActorWorld": "Open Actor World", "sendToChat": "Send to Chat", diff --git a/module/applications/characterCreation/characterCreation.mjs b/module/applications/characterCreation/characterCreation.mjs index e6c0f299..936bb79d 100644 --- a/module/applications/characterCreation/characterCreation.mjs +++ b/module/applications/characterCreation/characterCreation.mjs @@ -11,7 +11,10 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl this.character = character; this.setup = { - traits: this.character.system.traits, + traits: Object.keys(this.character.system.traits).reduce((acc, key) => { + acc[key] = { value: null }; + return acc; + }, {}), ancestryName: { primary: '', secondary: '' @@ -377,8 +380,10 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl ]; return Object.values(this.setup.traits).reduce((acc, x) => { const index = traitCompareArray.indexOf(x.value); + if (index === -1) return acc; + traitCompareArray.splice(index, 1); - acc += index !== -1; + acc += 1; return acc; }, 0); } diff --git a/module/applications/dialogs/actionSelectionDialog.mjs b/module/applications/dialogs/actionSelectionDialog.mjs index c421a577..995c4894 100644 --- a/module/applications/dialogs/actionSelectionDialog.mjs +++ b/module/applications/dialogs/actionSelectionDialog.mjs @@ -72,8 +72,8 @@ export default class ActionSelectionDialog extends HandlebarsApplicationMixin(Ap static async #onChooseAction(event, button) { const { actionId } = button.dataset; - this.#action = this.#item.system.actionsList.find(a => a._id === actionId); - Object.defineProperty(this.#event, 'shiftKey', { + this.action = this.item.system.actionsList.find(a => a._id === actionId); + Object.defineProperty(this.event, 'shiftKey', { get() { return event.shiftKey; } diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index 64fa168a..067aa473 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -123,6 +123,10 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio context.advantage = this.config.roll?.advantage; context.disadvantage = this.config.roll?.disadvantage; context.diceOptions = CONFIG.DH.GENERAL.diceTypes; + context.dieFaces = CONFIG.DH.GENERAL.dieFaces.reduce((acc, face) => { + acc[face] = `d${face}`; + return acc; + }, {}); context.isLite = this.config.roll?.lite; context.extraFormula = this.config.extraFormula; context.formula = this.roll.constructFormula(this.config); @@ -152,9 +156,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio } if (this.config.uses) this.config.uses = foundry.utils.mergeObject(this.config.uses, rest.uses); if (rest.roll?.dice) { - Object.entries(rest.roll.dice).forEach(([key, value]) => { - this.roll[key] = value; - }); + this.roll = foundry.utils.mergeObject(this.roll, rest.roll.dice); } if (rest.hasOwnProperty('trait')) { this.config.roll.trait = rest.trait; @@ -173,6 +175,15 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio this.disadvantage = advantage === -1; this.config.roll.advantage = this.config.roll.advantage === advantage ? 0 : advantage; + + if (this.config.roll.advantage === 1 && this.config.data.rules.roll.defaultAdvantageDice) { + const faces = Number.parseInt(this.config.data.rules.roll.defaultAdvantageDice); + this.roll.advantageFaces = Number.isNaN(faces) ? this.roll.advantageFaces : faces; + } else if (this.config.roll.advantage === -1 && this.config.data.rules.roll.defaultDisadvantageDice) { + const faces = Number.parseInt(this.config.data.rules.roll.defaultDisadvantageDice); + this.roll.advantageFaces = Number.isNaN(faces) ? this.roll.advantageFaces : faces; + } + this.render(); } diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index 3475dee7..989e4625 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -259,8 +259,9 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV const resetValue = increasing ? 0 : feature.system.resource.max - ? Roll.replaceFormulaData(feature.system.resource.max, this.actor) + ? new Roll(Roll.replaceFormulaData(feature.system.resource.max, this.actor)).evaluateSync().total : 0; + await feature.update({ 'system.resource.value': resetValue }); } diff --git a/module/applications/dialogs/groupRollDialog.mjs b/module/applications/dialogs/groupRollDialog.mjs index 2a7be791..a47dd0a8 100644 --- a/module/applications/dialogs/groupRollDialog.mjs +++ b/module/applications/dialogs/groupRollDialog.mjs @@ -116,7 +116,7 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat initializationPart.insertAdjacentHTML('afterend', '
'); initializationPart.insertAdjacentHTML( 'afterend', - `
${game.i18n.localize('Aiding Characters')}
` + `
${game.i18n.localize('DAGGERHEART.APPLICATIONS.GroupRollSelect.aidingCharacters')}
` ); const teamContainer = this.element.querySelector('.team-container'); diff --git a/module/applications/dialogs/itemTransfer.mjs b/module/applications/dialogs/itemTransfer.mjs index ad3cf103..42e3a727 100644 --- a/module/applications/dialogs/itemTransfer.mjs +++ b/module/applications/dialogs/itemTransfer.mjs @@ -38,13 +38,15 @@ export default class ItemTransferDialog extends HandlebarsApplicationMixin(Appli originActor ??= item?.actor; const homebrewKey = CONFIG.DH.SETTINGS.gameSettings.Homebrew; const currencySetting = game.settings.get(CONFIG.DH.id, homebrewKey).currency?.[currency] ?? null; + const max = item?.system.quantity ?? originActor.system.gold[currency] ?? 0; return { originActor, targetActor, itemImage: item?.img, currencyIcon: currencySetting?.icon, - max: item?.system.quantity ?? originActor.system.gold[currency] ?? 0, + max, + initial: targetActor.system.metadata.quantifiable?.includes(item.type) ? max : 1, title: item?.name ?? currencySetting?.label }; } diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 054331b5..026c4bc0 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -20,7 +20,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio owned: member.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) })); - this.initiator = null; + this.initiator = { cost: 3 }; this.openForAllPlayers = true; this.tabGroups.application = Object.keys(party.system.tagTeam.members).length @@ -115,6 +115,12 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio async _onRender(context, options) { await super._onRender(context, options); + // if (this.element.querySelector('.roll-selection')) { + // for (const element of this.element.querySelectorAll('.team-member-container')) { + // element.classList.add('select-padding'); + // } + // } + if (this.element.querySelector('.team-container')) return; const initializationPart = this.element.querySelector('.initialization-container'); initializationPart.insertAdjacentHTML('afterend', '
'); @@ -133,7 +139,10 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio context.members = {}; context.allHaveRolled = Object.keys(this.party.system.tagTeam.members).every(key => { const data = this.party.system.tagTeam.members[key]; - return Boolean(data.rollData); + const hasRolled = Boolean(data.rollData); + if (!hasRolled) return false; + + return !data.rollData.options.hasDamage || Boolean(data.rollData.options.damage); }); return context; diff --git a/module/applications/hud/tokenHUD.mjs b/module/applications/hud/tokenHUD.mjs index 77caaaff..943f3506 100644 --- a/module/applications/hud/tokenHUD.mjs +++ b/module/applications/hud/tokenHUD.mjs @@ -122,15 +122,14 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { async toggleClowncar(actors) { const animationDuration = 500; - const activeTokens = actors.flatMap(member => member.getActiveTokens()); + const scene = game.scenes.get(game.user.viewedScene); + /* getDependentTokens returns already removed tokens with id = null. Need to filter that until it's potentially fixed from Foundry */ + const activeTokens = actors.flatMap(member => member.getDependentTokens({ scenes: scene }).filter(x => x._id)); const { x: actorX, y: actorY } = this.document; if (activeTokens.length > 0) { for (let token of activeTokens) { - await token.document.update( - { x: actorX, y: actorY, alpha: 0 }, - { animation: { duration: animationDuration } } - ); - setTimeout(() => token.document.delete(), animationDuration); + await token.update({ x: actorX, y: actorY, alpha: 0 }, { animation: { duration: animationDuration } }); + setTimeout(() => token.delete(), animationDuration); } } else { const activeScene = game.scenes.find(x => x.id === game.user.viewedScene); @@ -140,11 +139,16 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { tokenData.push(data.toObject()); } + const viewedLevel = game.scenes.get(game.user.viewedScene).levels.get(game.user.viewedLevel); + const elevation = this.actor.token?.elevation ?? viewedLevel.elevation.bottom; + const newTokens = await activeScene.createEmbeddedDocuments( 'Token', tokenData.map(tokenData => ({ ...tokenData, alpha: 0, + level: viewedLevel, + elevation: elevation, x: actorX, y: actorY })) diff --git a/module/applications/settings/appearanceSettings.mjs b/module/applications/settings/appearanceSettings.mjs index 151648e1..9de9e752 100644 --- a/module/applications/settings/appearanceSettings.mjs +++ b/module/applications/settings/appearanceSettings.mjs @@ -118,8 +118,13 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App break; case 'footer': partContext.buttons = [ - { type: 'button', action: 'reset', icon: 'fa-solid fa-arrow-rotate-left', label: 'Reset' }, - { type: 'submit', icon: 'fa-solid fa-floppy-disk', label: 'Save Changes' } + { + type: 'button', + action: 'reset', + icon: 'fa-solid fa-arrow-rotate-left', + label: game.i18n.localize('SETTINGS.UI.ACTIONS.Reset') + }, + { type: 'submit', icon: 'fa-solid fa-floppy-disk', label: game.i18n.localize('EDITOR.Save') } ]; break; } diff --git a/module/applications/sheets-configs/action-base-config.mjs b/module/applications/sheets-configs/action-base-config.mjs index 0ae39477..a94abb26 100644 --- a/module/applications/sheets-configs/action-base-config.mjs +++ b/module/applications/sheets-configs/action-base-config.mjs @@ -264,7 +264,9 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) key = event.target.closest('[data-key]').dataset.key; if (!this.action[key]) return; - data[key].push(this.action.defaultValues[key] ?? {}); + const value = key === 'areas' ? { name: this.action.item.name } : {}; + + data[key].push(this.action.defaultValues[key] ?? value); this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); } diff --git a/module/applications/sheets-configs/action-config.mjs b/module/applications/sheets-configs/action-config.mjs index e073cfa6..ef529e9b 100644 --- a/module/applications/sheets-configs/action-config.mjs +++ b/module/applications/sheets-configs/action-config.mjs @@ -19,15 +19,17 @@ export default class DHActionConfig extends DHActionBaseConfig { return context; } - static async addEffect(_event) { + static async addEffect(event) { + const { areaIndex } = event.target.dataset; if (!this.action.effects) return; const data = this.action.toObject(); const created = await this.action.item.createEmbeddedDocuments('ActiveEffect', [ - game.system.api.data.activeEffects.BaseEffect.getDefaultObject() + game.system.api.data.activeEffects.BaseEffect.getDefaultObject({ transfer: false }) ]); - data.effects.push({ _id: created[0]._id }); + if (areaIndex !== undefined) data.areas[areaIndex].effects.push(created[0]._id); + else data.effects.push({ _id: created[0]._id }); this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); this.action.item.effects.get(created[0]._id).sheet.render(true); } @@ -52,9 +54,19 @@ export default class DHActionConfig extends DHActionBaseConfig { static removeEffect(event, button) { if (!this.action.effects) return; - const index = button.dataset.index, + + const { areaIndex, index } = button.dataset; + let effectId = null; + if (areaIndex !== undefined) { + effectId = this.action.areas[areaIndex].effects[index]; + const data = this.action.toObject(); + data.areas[areaIndex].effects.splice(index, 1); + this.constructor.updateForm.call(this, null, null, { object: foundry.utils.flattenObject(data) }); + } else { effectId = this.action.effects[index]._id; - this.constructor.removeElement.bind(this)(event, button); + this.constructor.removeElement.call(this, event, button); + } + this.action.item.deleteEmbeddedDocuments('ActiveEffect', [effectId]); } diff --git a/module/applications/sheets-configs/action-settings-config.mjs b/module/applications/sheets-configs/action-settings-config.mjs index 9cb866bc..24553069 100644 --- a/module/applications/sheets-configs/action-settings-config.mjs +++ b/module/applications/sheets-configs/action-settings-config.mjs @@ -31,21 +31,35 @@ export default class DHActionSettingsConfig extends DHActionBaseConfig { } static async addEffect(_event) { + const { areaIndex } = event.target.dataset; if (!this.action.effects) return; - const effectData = game.system.api.data.activeEffects.BaseEffect.getDefaultObject(); + + const effectData = game.system.api.data.activeEffects.BaseEffect.getDefaultObject({ transfer: false }); const data = this.action.toObject(); this.sheetUpdate(data, effectData); this.effects = [...this.effects, effectData]; - data.effects.push({ _id: effectData.id }); + + if (areaIndex !== undefined) data.areas[areaIndex].effects.push(effectData.id); + else data.effects.push({ _id: effectData.id }); + this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); } static removeEffect(event, button) { if (!this.action.effects) return; - const index = button.dataset.index, + const { areaIndex, index } = button.dataset; + let effectId = null; + if (areaIndex !== undefined) { + effectId = this.action.areas[areaIndex].effects[index]; + const data = this.action.toObject(); + data.areas[areaIndex].effects.splice(index, 1); + this.constructor.updateForm.call(this, null, null, { object: foundry.utils.flattenObject(data) }); + } else { effectId = this.action.effects[index]._id; - this.constructor.removeElement.bind(this)(event, button); + this.constructor.removeElement.call(this, event, button); + } + this.sheetUpdate( this.action.toObject(), this.effects.find(x => x.id === effectId), diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index d8a3df29..04be3efb 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -217,8 +217,8 @@ export default class AdversarySheet extends DHBaseActorSheet { static #reactionRoll(event) { const config = { event, - title: `Reaction Roll: ${this.actor.name}`, - headerTitle: 'Adversary Reaction Roll', + title: game.i18n.localize('DAGGERHEART.GENERAL.reactionRoll'), + headerTitle: game.i18n.localize('DAGGERHEART.ACTORS.Adversary.adversaryReactionRoll.headerTitle'), roll: { type: 'trait' }, diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index f2686fdd..c59dd64e 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -12,8 +12,6 @@ export default class CharacterSheet extends DHBaseActorSheet { static DEFAULT_OPTIONS = { classes: ['character'], position: { width: 850, height: 800 }, - /* Foundry adds disabled to all buttons and inputs if editPermission is missing. This is not desired. */ - editPermission: CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER, actions: { toggleVault: CharacterSheet.#toggleVault, rollAttribute: CharacterSheet.#rollAttribute, @@ -68,7 +66,7 @@ export default class CharacterSheet extends DHBaseActorSheet { } }, { - handler: CharacterSheet.#getEquipamentContextOptions, + handler: CharacterSheet.#getEquipmentContextOptions, selector: '[data-item-uuid][data-type="armor"], [data-item-uuid][data-type="weapon"]', options: { parentClassHooks: false, @@ -170,6 +168,16 @@ export default class CharacterSheet extends DHBaseActorSheet { return applicationOptions; } + /** @inheritdoc */ + _toggleDisabled(disabled) { + // Overriden to only disable text inputs by default. + // Everything else is done by checking @root.editable in the sheet + const form = this.form; + for (const input of form.querySelectorAll('input:not([type=search]), .editor.prosemirror')) { + input.disabled = disabled; + } + } + /** @inheritDoc */ async _onRender(context, options) { await super._onRender(context, options); @@ -315,11 +323,11 @@ export default class CharacterSheet extends DHBaseActorSheet { /**@type {import('@client/applications/ux/context-menu.mjs').ContextMenuEntry[]} */ const options = [ { - name: 'toLoadout', + label: 'toLoadout', icon: 'fa-solid fa-arrow-up', - condition: target => { + visible: target => { const doc = getDocFromElementSync(target); - return doc && doc.system.inVault; + return doc?.isOwner && doc.system.inVault; }, callback: async target => { const doc = await getDocFromElement(target); @@ -329,11 +337,11 @@ export default class CharacterSheet extends DHBaseActorSheet { } }, { - name: 'recall', + label: 'recall', icon: 'fa-solid fa-bolt-lightning', - condition: target => { + visible: target => { const doc = getDocFromElementSync(target); - return doc && doc.system.inVault; + return doc?.isOwner && doc.system.inVault; }, callback: async (target, event) => { const doc = await getDocFromElement(target); @@ -368,17 +376,17 @@ export default class CharacterSheet extends DHBaseActorSheet { } }, { - name: 'toVault', + label: 'toVault', icon: 'fa-solid fa-arrow-down', - condition: target => { + visible: target => { const doc = getDocFromElementSync(target); - return doc && !doc.system.inVault; + return doc?.isOwner && !doc.system.inVault; }, callback: async target => (await getDocFromElement(target)).update({ 'system.inVault': true }) } ].map(option => ({ ...option, - name: `DAGGERHEART.APPLICATIONS.ContextMenu.${option.name}`, + label: `DAGGERHEART.APPLICATIONS.ContextMenu.${option.label}`, icon: `` })); @@ -391,29 +399,29 @@ export default class CharacterSheet extends DHBaseActorSheet { * @this {CharacterSheet} * @protected */ - static #getEquipamentContextOptions() { + static #getEquipmentContextOptions() { const options = [ { - name: 'equip', + label: 'equip', icon: 'fa-solid fa-hands', - condition: target => { + visible: target => { const doc = getDocFromElementSync(target); - return doc && !doc.system.equipped; + return doc.isOwner && doc && !doc.system.equipped; }, callback: (target, event) => CharacterSheet.#toggleEquipItem.call(this, event, target) }, { - name: 'unequip', + label: 'unequip', icon: 'fa-solid fa-hands', - condition: target => { + visible: target => { const doc = getDocFromElementSync(target); - return doc && doc.system.equipped; + return doc.isOwner && doc && doc.system.equipped; }, callback: (target, event) => CharacterSheet.#toggleEquipItem.call(this, event, target) } ].map(option => ({ ...option, - name: `DAGGERHEART.APPLICATIONS.ContextMenu.${option.name}`, + label: `DAGGERHEART.APPLICATIONS.ContextMenu.${option.label}`, icon: `` })); diff --git a/module/applications/sheets/actors/party.mjs b/module/applications/sheets/actors/party.mjs index d4545f63..a7eeccdf 100644 --- a/module/applications/sheets/actors/party.mjs +++ b/module/applications/sheets/actors/party.mjs @@ -288,7 +288,7 @@ export default class Party extends DHBaseActorSheet { title: game.i18n.localize(`DAGGERHEART.APPLICATIONS.Downtime.${button.dataset.type}.title`), icon: button.dataset.type === 'shortRest' ? 'fa-solid fa-utensils' : 'fa-solid fa-bed' }, - content: 'This will trigger a dialog to players make their downtime moves, are you sure?', + content: game.i18n.localize('DAGGERHEART.ACTORS.Party.triggerRestContent'), classes: ['daggerheart', 'dialog', 'dh-style'] }); diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 64f62405..5faa5d5c 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -418,18 +418,18 @@ export default function DHApplicationMixin(Base) { /**@type {import('@client/applications/ux/context-menu.mjs').ContextMenuEntry[]} */ const options = [ { - name: 'disableEffect', + label: 'disableEffect', icon: 'fa-solid fa-lightbulb', - condition: element => { + visible: element => { const target = element.closest('[data-item-uuid]'); return !target.dataset.disabled && target.dataset.itemType !== 'beastform'; }, callback: async target => (await getDocFromElement(target)).update({ disabled: true }) }, { - name: 'enableEffect', + label: 'enableEffect', icon: 'fa-regular fa-lightbulb', - condition: element => { + visible: element => { const target = element.closest('[data-item-uuid]'); return target.dataset.disabled && target.dataset.itemType !== 'beastform'; }, @@ -437,7 +437,7 @@ export default function DHApplicationMixin(Base) { } ].map(option => ({ ...option, - name: `DAGGERHEART.APPLICATIONS.ContextMenu.${option.name}`, + label: `DAGGERHEART.APPLICATIONS.ContextMenu.${option.label}`, icon: `` })); @@ -468,14 +468,14 @@ export default function DHApplicationMixin(Base) { _getContextMenuCommonOptions({ usable = false, toChat = false, deletable = true }) { const options = [ { - name: 'CONTROLS.CommonEdit', + label: 'CONTROLS.CommonEdit', icon: 'fa-solid fa-pen-to-square', - condition: target => { + visible: target => { const { dataset } = target.closest('[data-item-uuid]'); const doc = getDocFromElementSync(target); return ( (!dataset.noCompendiumEdit && !doc) || - (doc && (!doc?.hasOwnProperty('systemPath') || doc?.inCollection)) + (doc?.isOwner && (!doc?.hasOwnProperty('systemPath') || doc?.inCollection)) ); }, callback: async target => (await getDocFromElement(target)).sheet.render({ force: true }) @@ -484,14 +484,14 @@ export default function DHApplicationMixin(Base) { if (usable) { options.unshift({ - name: 'DAGGERHEART.GENERAL.damage', + label: 'DAGGERHEART.GENERAL.damage', icon: 'fa-solid fa-explosion', - condition: target => { + visible: target => { const doc = getDocFromElementSync(target); - return ( + const hasDamage = !foundry.utils.isEmpty(doc?.system?.attack?.damage.parts) || - !foundry.utils.isEmpty(doc?.damage?.parts) - ); + !foundry.utils.isEmpty(doc?.damage?.parts); + return doc?.isOwner && hasDamage; }, callback: async (target, event) => { const doc = await getDocFromElement(target), @@ -507,11 +507,11 @@ export default function DHApplicationMixin(Base) { }); options.unshift({ - name: 'DAGGERHEART.APPLICATIONS.ContextMenu.useItem', + label: 'DAGGERHEART.APPLICATIONS.ContextMenu.useItem', icon: 'fa-solid fa-burst', - condition: target => { + visible: target => { const doc = getDocFromElementSync(target); - return doc && !(doc.type === 'domainCard' && doc.system.inVault); + return doc?.isOwner && !(doc.type === 'domainCard' && doc.system.inVault); }, callback: async (target, event) => (await getDocFromElement(target)).use(event) }); @@ -519,18 +519,19 @@ export default function DHApplicationMixin(Base) { if (toChat) options.push({ - name: 'DAGGERHEART.APPLICATIONS.ContextMenu.sendToChat', + label: 'DAGGERHEART.APPLICATIONS.ContextMenu.sendToChat', icon: 'fa-solid fa-message', callback: async target => (await getDocFromElement(target)).toChat(this.document.uuid) }); if (deletable) options.push({ - name: 'CONTROLS.CommonDelete', + label: 'CONTROLS.CommonDelete', icon: 'fa-solid fa-trash', - condition: element => { + visible: element => { const target = element.closest('[data-item-uuid]'); - return target.dataset.itemType !== 'beastform'; + const doc = getDocFromElementSync(target); + return doc?.isOwner && target.dataset.itemType !== 'beastform'; }, callback: async (target, event) => { const doc = await getDocFromElement(target); @@ -644,12 +645,12 @@ export default function DHApplicationMixin(Base) { buttons: [ { action: 'create', - label: 'Create Item', + label: game.i18n.localize('DAGGERHEART.APPLICATIONS.CreateItemDialog.createItem'), icon: 'fa-solid fa-plus' }, { action: 'browse', - label: 'Browse Compendium', + label: game.i18n.localize('DAGGERHEART.APPLICATIONS.CreateItemDialog.browseCompendium'), icon: 'fa-solid fa-book' } ] diff --git a/module/applications/sheets/api/base-actor.mjs b/module/applications/sheets/api/base-actor.mjs index 4a550d72..e23a4426 100644 --- a/module/applications/sheets/api/base-actor.mjs +++ b/module/applications/sheets/api/base-actor.mjs @@ -73,7 +73,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { .hideAttribution; // Prepare inventory data - if (['party', 'character'].includes(this.document.type)) { + if (this.document.system.metadata.hasInventory) { context.inventory = { currencies: {}, weapons: this.document.itemTypes.weapon.sort((a, b) => a.sort - b.sort), @@ -283,11 +283,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { async _onDropItem(event, item) { const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event); const originActor = item.actor; - if ( - item.actor?.uuid === this.document.uuid || - !originActor || - !['character', 'party'].includes(this.document.type) - ) { + if (!originActor || originActor.uuid === this.document.uuid || !this.document.system.metadata.hasInventory) { return super._onDropItem(event, item); } @@ -302,47 +298,79 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { ); } - if (item.system.metadata.isQuantifiable) { - const actorItem = originActor.items.get(data.originId); - const quantityTransfered = await game.system.api.applications.dialogs.ItemTransferDialog.configure({ + // Perform the actual transfer, showing a dialog when doing it + const availableQuantity = Math.max(1, item.system.quantity); + const actorItem = originActor.items.get(data.originId) ?? item; + if (availableQuantity > 1) { + const quantityTransferred = await game.system.api.applications.dialogs.ItemTransferDialog.configure({ item, targetActor: this.document }); - - if (quantityTransfered) { - const existingItem = this.document.items.find(x => itemIsIdentical(x, item)); - if (existingItem) { - await existingItem.update({ - 'system.quantity': existingItem.system.quantity + quantityTransfered - }); - } else { - const createData = item.toObject(); - await this.document.createEmbeddedDocuments('Item', [ - { - ...createData, - system: { - ...createData.system, - quantity: quantityTransfered - } - } - ]); - } - - if (quantityTransfered === actorItem.system.quantity) { - await originActor.deleteEmbeddedDocuments('Item', [data.originId]); - } else { - await actorItem.update({ - 'system.quantity': actorItem.system.quantity - quantityTransfered - }); - } - } + return this.#transferItem(actorItem, quantityTransferred); } else { - await this.document.createEmbeddedDocuments('Item', [item.toObject()]); - await originActor.deleteEmbeddedDocuments('Item', [data.originId]); + return this.#transferItem(actorItem, availableQuantity); } } } + /** + * Helper to perform the actual transfer of an item to this actor, including stack/unstack logic based on target quantifiability. + * Make sure item is the actor item before calling this method or there will be issues + */ + async #transferItem(item, quantity) { + const originActor = item.actor; + const targetActor = this.document; + const allowStacking = targetActor.system.metadata.quantifiable?.includes(item.type); + + const batch = []; + + // First add/update the item to the target actor + const existing = allowStacking ? targetActor.items.find(x => itemIsIdentical(x, item)) : null; + if (existing) { + batch.push({ + action: 'update', + documentName: 'Item', + parent: targetActor, + updates: [{ '_id': existing.id, 'system.quantity': existing.system.quantity + quantity }] + }); + } else { + const itemsToCreate = []; + if (allowStacking) { + itemsToCreate.push(foundry.utils.mergeObject(item.toObject(true), { system: { quantity } })); + } else { + const createData = new Array(Math.max(1, quantity)) + .fill(0) + .map(() => foundry.utils.mergeObject(item.toObject(), { system: { quantity: 1 } })); + itemsToCreate.push(...createData); + } + batch.push({ + action: 'create', + documentName: 'Item', + parent: targetActor, + data: itemsToCreate + }); + } + + // Remove the item from the original actor (by either deleting it, or updating its quantity) + if (quantity >= item.system.quantity) { + batch.push({ + action: 'delete', + documentName: 'Item', + parent: originActor, + ids: [item.id] + }); + } else { + batch.push({ + action: 'update', + documentName: 'Item', + parent: originActor, + updates: [{ '_id': item.id, 'system.quantity': item.system.quantity - quantity }] + }); + } + + return foundry.documents.modifyBatch(batch); + } + /** * On dragStart on the item. * @param {DragEvent} event - The drag event diff --git a/module/applications/sheets/items/ancestry.mjs b/module/applications/sheets/items/ancestry.mjs index 8c0a5620..cf040e02 100644 --- a/module/applications/sheets/items/ancestry.mjs +++ b/module/applications/sheets/items/ancestry.mjs @@ -31,11 +31,12 @@ export default class AncestrySheet extends DHHeritageSheet { if (data.type === 'ActiveEffect') return super._onDrop(event); const target = event.target.closest('fieldset.drop-section'); - const typeField = - this.document.system[target.dataset.type === 'primary' ? 'primaryFeature' : 'secondaryFeature']; - - if (!typeField) { - super._onDrop(event); + if (target) { + const typeField = + this.document.system[target.dataset.type === 'primary' ? 'primaryFeature' : 'secondaryFeature']; + if (!typeField) { + super._onDrop(event); + } } } } diff --git a/module/applications/sheets/items/feature.mjs b/module/applications/sheets/items/feature.mjs index 6ff98ca7..7f9028d5 100644 --- a/module/applications/sheets/items/feature.mjs +++ b/module/applications/sheets/items/feature.mjs @@ -31,7 +31,7 @@ export default class FeatureSheet extends DHBaseItemSheet { labelPrefix: 'DAGGERHEART.GENERAL.Tabs' } }; -//Might be wrong location but testing out if here is okay. + //Might be wrong location but testing out if here is okay. /**@override */ async _prepareContext(options) { const context = await super._prepareContext(options); diff --git a/module/applications/sidebar/tabs/actorDirectory.mjs b/module/applications/sidebar/tabs/actorDirectory.mjs index 9d8f16e1..89da1426 100644 --- a/module/applications/sidebar/tabs/actorDirectory.mjs +++ b/module/applications/sidebar/tabs/actorDirectory.mjs @@ -46,50 +46,67 @@ export default class DhActorDirectory extends foundry.applications.sidebar.tabs. _getEntryContextOptions() { const options = super._getEntryContextOptions(); - options.push({ - name: 'DAGGERHEART.UI.Sidebar.actorDirectory.duplicateToNewTier', - icon: ``, - condition: li => { - const actor = game.actors.get(li.dataset.entryId); - return actor?.type === 'adversary' && actor.system.type !== 'social'; - }, - callback: async li => { - const actor = game.actors.get(li.dataset.entryId); - if (!actor) throw new Error('Unexpected missing actor'); + options.push( + { + label: 'DAGGERHEART.UI.Sidebar.actorDirectory.duplicateToNewTier', + icon: ``, + visible: li => { + const actor = game.actors.get(li.dataset.entryId); + return actor?.type === 'adversary' && actor.system.type !== 'social'; + }, + callback: async li => { + const actor = game.actors.get(li.dataset.entryId); + if (!actor) throw new Error('Unexpected missing actor'); - const tiers = [1, 2, 3, 4].filter(t => t !== actor.system.tier); - const content = document.createElement('div'); - const select = document.createElement('select'); - select.name = 'tier'; - select.append( - ...tiers.map(t => { - const option = document.createElement('option'); - option.value = t; - option.textContent = game.i18n.localize(`DAGGERHEART.GENERAL.Tiers.${t}`); - return option; - }) - ); - content.append(select); + const tiers = [1, 2, 3, 4].filter(t => t !== actor.system.tier); + const content = document.createElement('div'); + const select = document.createElement('select'); + select.name = 'tier'; + select.append( + ...tiers.map(t => { + const option = document.createElement('option'); + option.value = t; + option.textContent = game.i18n.localize(`DAGGERHEART.GENERAL.Tiers.${t}`); + return option; + }) + ); + content.append(select); - const tier = await foundry.applications.api.Dialog.input({ - classes: ['dh-style', 'dialog'], - window: { title: 'DAGGERHEART.UI.Sidebar.actorDirectory.pickTierTitle' }, - content, - ok: { - label: 'Create Adversary', - callback: (event, button, dialog) => Number(button.form.elements.tier.value) + const tier = await foundry.applications.api.Dialog.input({ + classes: ['dh-style', 'dialog'], + window: { title: 'DAGGERHEART.UI.Sidebar.actorDirectory.pickTierTitle' }, + content, + ok: { + label: 'DAGGERHEART.UI.Sidebar.actorDirectory.createAdversary', + callback: (event, button, dialog) => Number(button.form.elements.tier.value) + } + }); + + if (tier === actor.system.tier) { + ui.notifications.warn('This actor is already at this tier'); + } else if (tier) { + const source = actor.system.adjustForTier(tier); + await Actor.create(source); + ui.notifications.info(`Tier ${tier} ${actor.name} created`); } - }); + } + }, + { + label: 'DAGGERHEART.UI.Sidebar.actorDirectory.activateParty', + icon: ``, + visible: li => { + const actor = game.actors.get(li.dataset.entryId); + return actor && actor.type === 'party' && !actor.system.active; + }, + callback: async li => { + const actor = game.actors.get(li.dataset.entryId); + if (!actor) throw new Error('Unexpected missing actor'); - if (tier === actor.system.tier) { - ui.notifications.warn('This actor is already at this tier'); - } else if (tier) { - const source = actor.system.adjustForTier(tier); - await Actor.create(source); - ui.notifications.info(`Tier ${tier} ${actor.name} created`); + await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.ActiveParty, actor.id); + ui.actors.render(); } } - }); + ); return options; } diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 59939963..34b25591 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -103,23 +103,10 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo _getEntryContextOptions() { return [ ...super._getEntryContextOptions(), - // { - // name: 'Reroll', - // icon: '', - // condition: li => { - // const message = game.messages.get(li.dataset.messageId); - - // return (game.user.isGM || message.isAuthor) && message.rolls.length > 0; - // }, - // callback: li => { - // const message = game.messages.get(li.dataset.messageId); - // new game.system.api.applications.dialogs.RerollDialog(message).render({ force: true }); - // } - // }, { - name: game.i18n.localize('DAGGERHEART.UI.ChatLog.rerollDamage'), + label: 'DAGGERHEART.UI.ChatLog.rerollDamage', icon: '', - condition: li => { + visible: li => { const message = game.messages.get(li.dataset.messageId); const hasRolledDamage = message.system.hasDamage ? Object.keys(message.system.damage).length > 0 diff --git a/module/applications/ui/combatTracker.mjs b/module/applications/ui/combatTracker.mjs index 1043e128..fb19a17e 100644 --- a/module/applications/ui/combatTracker.mjs +++ b/module/applications/ui/combatTracker.mjs @@ -84,15 +84,15 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C _getCombatContextOptions() { return [ { - name: 'COMBAT.ClearMovementHistories', + label: 'COMBAT.ClearMovementHistories', icon: '', - condition: () => game.user.isGM && this.viewed?.combatants.size > 0, + visible: () => game.user.isGM && this.viewed?.combatants.size > 0, callback: () => this.viewed.clearMovementHistories() }, { - name: 'COMBAT.Delete', + label: 'COMBAT.Delete', icon: '', - condition: () => game.user.isGM && !!this.viewed, + visible: () => game.user.isGM && !!this.viewed, callback: () => this.viewed.endCombat() } ]; diff --git a/module/applications/ui/fearTracker.mjs b/module/applications/ui/fearTracker.mjs index 82dda215..4e5e1132 100644 --- a/module/applications/ui/fearTracker.mjs +++ b/module/applications/ui/fearTracker.mjs @@ -22,7 +22,7 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV tag: 'div', window: { frame: true, - title: 'Fear', + title: 'DAGGERHEART.GENERAL.fear', positioned: true, resizable: true, minimizable: false diff --git a/module/applications/ui/itemBrowser.mjs b/module/applications/ui/itemBrowser.mjs index 2d2e8cdc..67a16f6a 100644 --- a/module/applications/ui/itemBrowser.mjs +++ b/module/applications/ui/itemBrowser.mjs @@ -37,7 +37,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { tag: 'div', window: { frame: true, - title: 'Compendium Browser', + title: 'DAGGERHEART.UI.ItemBrowser.windowTitle', icon: 'fa-solid fa-book-atlas', positioned: true, resizable: true @@ -207,8 +207,23 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { label: game.i18n.localize(col.label) })); + const splitPath = folderId?.split('.') ?? []; + const { pathLabels } = splitPath.reduce( + (acc, curr) => { + acc.currentPath = !acc.currentPath ? curr : [acc.currentPath, curr].join('.'); + if (curr === 'folder') return acc; + + const label = foundry.utils.getProperty(this.config, acc.currentPath)?.label; + if (label) acc.pathLabels.push(game.i18n.localize(label)); + + return acc; + }, + { pathLabels: [], currentPath: '' } + ); + this.selectedMenu = { - path: folderId?.split('.') ?? [], + path: splitPath, + pathLabels: pathLabels, data: { ...folderData, columns: columns @@ -568,7 +583,9 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { const { itemUuid } = event.target.closest('[data-item-uuid]').dataset, item = await foundry.utils.fromUuid(itemUuid), dragData = item.toDragData(); + event.dataTransfer.setData('text/plain', JSON.stringify(dragData)); + event.dataTransfer.setDragImage(event.target.querySelector('img'), 0, 0); } _canDragStart() { diff --git a/module/applications/ux/contextMenu.mjs b/module/applications/ux/contextMenu.mjs index 4e4ec6a4..0b208585 100644 --- a/module/applications/ux/contextMenu.mjs +++ b/module/applications/ux/contextMenu.mjs @@ -6,8 +6,11 @@ export default class DHContextMenu extends foundry.applications.ux.ContextMenu { static triggerContextMenu(event, altSelector) { event.preventDefault(); event.stopPropagation(); - const { clientX, clientY } = event; + const selector = altSelector ?? '[data-item-uuid]'; + if (ui.context?.selector === selector) return; + + const { clientX, clientY } = event; const target = event.target.closest(selector) ?? event.currentTarget.closest(selector); target?.dispatchEvent( new PointerEvent('contextmenu', { diff --git a/module/applications/ux/filter-menu.mjs b/module/applications/ux/filter-menu.mjs index 065d08f9..791c0e1f 100644 --- a/module/applications/ux/filter-menu.mjs +++ b/module/applications/ux/filter-menu.mjs @@ -188,7 +188,7 @@ export default class FilterMenu extends foundry.applications.ux.ContextMenu { })); const damageTypeFilter = Object.values(CONFIG.DH.GENERAL.damageTypes).map(({ id, abbreviation }) => ({ - group: 'Damage Type', //TODO localize + group: game.i18n.localize('DAGGERHEART.GENERAL.damageType'), name: game.i18n.localize(abbreviation), filter: { field: 'system.damage.type', diff --git a/module/canvas/placeables/regionLayer.mjs b/module/canvas/placeables/regionLayer.mjs index 81fd96db..c53cf782 100644 --- a/module/canvas/placeables/regionLayer.mjs +++ b/module/canvas/placeables/regionLayer.mjs @@ -95,4 +95,61 @@ export default class DhRegionLayer extends foundry.canvas.layers.RegionLayer { }); return inBounds.length === 1 ? inBounds[0] : null; } + + static getTemplateShape({ type, angle, range, direction } = {}) { + const { line, rectangle, inFront, cone, circle, emanation } = CONFIG.DH.GENERAL.templateTypes; + + /* Length calculation */ + const { grid, distance } = CONFIG.Scene.documentClass.schema.fields.grid.fields; + const sceneGridSize = canvas.scene?.grid.size ?? grid.size.initial; + const sceneGridDistance = canvas.scene?.grid.distance ?? distance.getInitialValue(); + const dimensionConstant = sceneGridSize / sceneGridDistance; + + const settings = canvas.scene?.rangeSettings; + const rangeNumber = Number(range); + const length = (!Number.isNaN(rangeNumber) ? rangeNumber : settings ? settings[range] : 0) * dimensionConstant; + /*----*/ + + const shapeData = { + ...canvas.mousePosition, + type: type, + direction: direction ?? 0 + }; + + switch (type) { + case rectangle.id: + shapeData.width = length; + shapeData.height = length; + break; + case line.id: + shapeData.length = length; + shapeData.width = 5 * dimensionConstant; + break; + case cone.id: + shapeData.angle = angle ?? CONFIG.MeasuredTemplate.defaults.angle; + shapeData.radius = length; + break; + case inFront.id: + shapeData.angle = '180'; + shapeData.radius = length; + shapeData.type = cone.id; + break; + case circle.id: + shapeData.radius = length; + break; + case emanation.id: + shapeData.radius = length; + shapeData.base = { + type: 'token', + x: 0, + y: 0, + width: 1, + height: 1, + shape: game.canvas.grid.isHexagonal ? CONST.TOKEN_SHAPES.ELLIPSE_1 : CONST.TOKEN_SHAPES.RECTANGLE_1 + }; + break; + } + + return shapeData; + } } diff --git a/module/canvas/tokens.mjs b/module/canvas/tokens.mjs index 9813cd48..9ca140e0 100644 --- a/module/canvas/tokens.mjs +++ b/module/canvas/tokens.mjs @@ -1,16 +1 @@ -export default class DhTokenLayer extends foundry.canvas.layers.TokenLayer { - async _createPreview(createData, options) { - if (options.actor) { - const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes; - if (options.actor?.system.metadata.usesSize) { - const tokenSize = tokenSizes[options.actor.system.size]; - if (tokenSize && options.actor.system.size !== CONFIG.DH.ACTOR.tokenSize.custom.id) { - createData.width = tokenSize; - createData.height = tokenSize; - } - } - } - - return super._createPreview(createData, options); - } -} +export default class DhTokenLayer extends foundry.canvas.layers.TokenLayer {} diff --git a/module/config/actionConfig.mjs b/module/config/actionConfig.mjs index 0b1bf91d..a6c04e18 100644 --- a/module/config/actionConfig.mjs +++ b/module/config/actionConfig.mjs @@ -115,3 +115,10 @@ export const advantageState = { value: 1 } }; + +export const areaTypes = { + placed: { + id: 'placed', + label: 'Placed Area' + } +}; diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 4a3d672d..6fc85ec5 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -80,12 +80,30 @@ export const groupAttackRange = { /* circle|cone|rect|ray used to be CONST.MEASURED_TEMPLATE_TYPES. Hardcoded for now */ export const templateTypes = { - CIRCLE: 'circle', - CONE: 'cone', - RECTANGLE: 'rectangle', - LINE: 'line', - EMANATION: 'emanation', - INFRONT: 'inFront' + circle: { + id: 'circle', + label: 'Circle' + }, + cone: { + id: 'cone', + label: 'Cone' + }, + rectangle: { + id: 'rectangle', + label: 'Rectangle' + }, + line: { + id: 'line', + label: 'Line' + }, + emanation: { + id: 'emanation', + label: 'Emanation' + }, + inFront: { + id: 'inFront', + label: 'In Front' + } }; export const rangeInclusion = { @@ -955,15 +973,15 @@ export const countdownAppMode = { export const sceneRangeMeasurementSetting = { disable: { id: 'disable', - label: 'Disable Daggerheart Range Measurement' + label: 'DAGGERHEART.CONFIG.SceneRangeMeasurementTypes.disable' }, default: { id: 'default', - label: 'Default' + label: 'DAGGERHEART.CONFIG.SceneRangeMeasurementTypes.default' }, custom: { id: 'custom', - label: 'Custom' + label: 'DAGGERHEART.CONFIG.SceneRangeMeasurementTypes.custom' } }; @@ -1092,3 +1110,18 @@ export const fallAndCollisionDamage = { damageFormula: '1d20 + 5' } }; + +export const simpleDispositions = { + [-1]: { + id: -1, + label: 'TOKEN.DISPOSITION.HOSTILE' + }, + [0]: { + id: 0, + label: 'TOKEN.DISPOSITION.NEUTRAL' + }, + [1]: { + id: 1, + label: 'TOKEN.DISPOSITION.FRIENDLY' + } +}; diff --git a/module/config/itemBrowserConfig.mjs b/module/config/itemBrowserConfig.mjs index 3b10409c..5c0a219b 100644 --- a/module/config/itemBrowserConfig.mjs +++ b/module/config/itemBrowserConfig.mjs @@ -7,7 +7,12 @@ export const typeConfig = { }, { key: 'system.type', - label: 'DAGGERHEART.GENERAL.type' + label: 'DAGGERHEART.GENERAL.type', + format: type => { + if (!type) return '-'; + + return CONFIG.DH.ACTOR.allAdversaryTypes()[type].label; + } } ], filters: [ @@ -69,12 +74,18 @@ export const typeConfig = { columns: [ { key: 'type', - label: 'DAGGERHEART.GENERAL.type' + label: 'DAGGERHEART.GENERAL.type', + format: type => (type ? `TYPES.Item.${type}` : '-') }, { key: 'system.secondary', label: 'DAGGERHEART.UI.ItemBrowser.subtype', - format: isSecondary => (isSecondary ? 'secondary' : isSecondary === false ? 'primary' : '-') + format: isSecondary => + isSecondary + ? 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.short' + : isSecondary === false + ? 'DAGGERHEART.ITEMS.Weapon.primaryWeapon.short' + : '-' }, { key: 'system.tier', @@ -94,8 +105,8 @@ export const typeConfig = { key: 'system.secondary', label: 'DAGGERHEART.UI.ItemBrowser.subtype', choices: [ - { value: false, label: 'DAGGERHEART.ITEMS.Weapon.primaryWeapon' }, - { value: true, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon' } + { value: false, label: 'DAGGERHEART.ITEMS.Weapon.primaryWeapon.full' }, + { value: true, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.full' } ] }, { @@ -253,11 +264,13 @@ export const typeConfig = { columns: [ { key: 'system.type', - label: 'DAGGERHEART.GENERAL.type' + label: 'DAGGERHEART.GENERAL.type', + format: type => (type ? `DAGGERHEART.CONFIG.DomainCardTypes.${type}` : '-') }, { key: 'system.domain', - label: 'DAGGERHEART.GENERAL.Domain.single' + label: 'DAGGERHEART.GENERAL.Domain.single', + format: domain => (domain ? CONFIG.DH.DOMAIN.allDomains()[domain].label : '-') }, { key: 'system.level', @@ -318,7 +331,14 @@ export const typeConfig = { }, { key: 'system.domains', - label: 'DAGGERHEART.GENERAL.Domain.plural' + label: 'DAGGERHEART.GENERAL.Domain.plural', + format: domains => { + const config = CONFIG.DH.DOMAIN.allDomains(); + return domains + .map(x => (x ? game.i18n.localize(config[x].label) : null)) + .filter(x => x) + .join(', '); + } } ], filters: [ @@ -362,18 +382,19 @@ export const typeConfig = { columns: [ { key: 'system.linkedClass', - label: 'Class', + label: 'TYPES.Item.class', format: linkedClass => linkedClass?.name ?? 'DAGGERHEART.UI.ItemBrowser.missing' }, { key: 'system.spellcastingTrait', - label: 'DAGGERHEART.ITEMS.Subclass.spellcastingTrait' + label: 'DAGGERHEART.ITEMS.Subclass.spellcastingTrait', + format: trait => (trait ? `DAGGERHEART.CONFIG.Traits.${trait}.name` : '-') } ], filters: [ { key: 'system.linkedClass.uuid', - label: 'Class', + label: 'TYPES.Item.class', choices: items => { const list = items .filter(item => item.system.linkedClass) @@ -397,7 +418,8 @@ export const typeConfig = { }, { key: 'system.mainTrait', - label: 'DAGGERHEART.GENERAL.Trait.single' + label: 'DAGGERHEART.GENERAL.Trait.single', + format: trait => (trait ? `DAGGERHEART.CONFIG.Traits.${trait}.name` : '-') } ], filters: [ diff --git a/module/config/settingsConfig.mjs b/module/config/settingsConfig.mjs index de4d96be..50841084 100644 --- a/module/config/settingsConfig.mjs +++ b/module/config/settingsConfig.mjs @@ -1,5 +1,6 @@ export const keybindings = { - spotlight: 'DHSpotlight' + spotlight: 'DHSpotlight', + partySheet: 'DHPartySheet' }; export const menu = { @@ -40,24 +41,21 @@ export const gameSettings = { LastMigrationVersion: 'LastMigrationVersion', SpotlightRequestQueue: 'SpotlightRequestQueue', CompendiumBrowserSettings: 'CompendiumBrowserSettings', - SpotlightTracker: 'SpotlightTracker' + SpotlightTracker: 'SpotlightTracker', + ActiveParty: 'ActiveParty' }; export const actionAutomationChoices = { never: { id: 'never', - label: 'Never' + label: 'DAGGERHEART.CONFIG.ActionAutomationChoices.never' }, showDialog: { id: 'showDialog', - label: 'Show Dialog only' + label: 'DAGGERHEART.CONFIG.ActionAutomationChoices.showDialog' }, - // npcOnly: { - // id: "npcOnly", - // label: "Always for non-characters" - // }, always: { id: 'always', - label: 'Always' + label: 'DAGGERHEART.CONFIG.ActionAutomationChoices.always' } }; diff --git a/module/data/_module.mjs b/module/data/_module.mjs index cd691ee1..a54da0e1 100644 --- a/module/data/_module.mjs +++ b/module/data/_module.mjs @@ -15,3 +15,4 @@ export * as chatMessages from './chat-message/_modules.mjs'; export * as fields from './fields/_module.mjs'; export * as items from './item/_module.mjs'; export * as scenes from './scene/_module.mjs'; +export * as regionBehaviors from './regionBehavior/_module.mjs'; diff --git a/module/data/action/attackAction.mjs b/module/data/action/attackAction.mjs index a2d47309..15cc1696 100644 --- a/module/data/action/attackAction.mjs +++ b/module/data/action/attackAction.mjs @@ -13,7 +13,7 @@ export default class DHAttackAction extends DHDamageAction { if (!!this.item?.system?.attack) { if (this.damage.includeBase) { const baseDamage = this.getParentDamage(); - this.damage.parts.unshift(new DHDamageData(baseDamage)); + this.damage.parts.hitPoints = new DHDamageData(baseDamage); } if (this.roll.useDefault) { this.roll.trait = this.item.system.attack.roll.trait; @@ -51,7 +51,7 @@ export default class DHAttackAction extends DHDamageAction { async use(event, options) { const result = await super.use(event, options); - if (result.message?.system.action.roll?.type === 'attack') { + if (result?.message?.system.action?.roll?.type === 'attack') { const { updateCountdowns } = game.system.api.applications.ui.DhCountdowns; await updateCountdowns(CONFIG.DH.GENERAL.countdownProgressionTypes.characterAttack.id); } diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index 0992350b..b3775dc9 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -15,7 +15,7 @@ const fields = foundry.data.fields; */ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel) { - static extraSchemas = ['cost', 'uses', 'range']; + static extraSchemas = ['areas', 'cost', 'uses', 'range']; /** @inheritDoc */ static defineSchema() { @@ -110,6 +110,11 @@ 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 */ + get isOwner() { + return this.item?.isOwner ?? true; + } + /** * Return Item the action is attached too. */ @@ -143,6 +148,12 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel : null; } + /** Returns true if the action is usable */ + get usable() { + const actor = this.actor; + return this.isOwner && actor?.type === 'character'; + } + static getRollType(parent) { return 'trait'; } diff --git a/module/data/activeEffect/baseEffect.mjs b/module/data/activeEffect/baseEffect.mjs index bac50c56..9b17164d 100644 --- a/module/data/activeEffect/baseEffect.mjs +++ b/module/data/activeEffect/baseEffect.mjs @@ -93,6 +93,12 @@ export default class BaseEffect extends foundry.data.ActiveEffectTypeDataModel { max: new fields.NumberField({ integer: true, label: 'DAGGERHEART.GENERAL.max' }) }, { nullable: true, initial: null } + ), + targetDispositions: new fields.SetField( + new fields.NumberField({ + choices: CONFIG.DH.GENERAL.simpleDispositions + }), + { label: 'DAGGERHEART.ACTIVEEFFECT.Config.targetDispositions' } ) }; } @@ -131,13 +137,14 @@ export default class BaseEffect extends foundry.data.ActiveEffectTypeDataModel { return armorChange.getArmorData(); } - static getDefaultObject() { + static getDefaultObject(options = { transfer: true }) { return { name: 'New Effect', id: foundry.utils.randomID(), disabled: false, img: 'icons/magic/life/heart-cross-blue.webp', description: '', + transfer: options.transfer, statuses: [], changes: [], system: { diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs index 73673896..d30e090a 100644 --- a/module/data/actor/adversary.mjs +++ b/module/data/actor/adversary.mjs @@ -133,7 +133,7 @@ export default class DhpAdversary extends DhCreature { } isItemValid(source) { - return source.type === 'feature'; + return super.isItemValid(source) || source.type === 'feature'; } async _preUpdate(changes, options, user) { diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index 89ba5db2..13ff0a38 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -107,7 +107,8 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel { hasResistances: true, hasAttribution: false, hasLimitedView: true, - usesSize: false + usesSize: false, + hasInventory: false }; } @@ -168,6 +169,11 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel { /* -------------------------------------------- */ + isItemValid(source) { + const inventoryTypes = ['weapon', 'armor', 'consumable', 'loot']; + return this.metadata.hasInventory && inventoryTypes.includes(source.type); + } + /** * Obtain a data object used to evaluate any dice rolls associated with this Item Type * @param {object} [options] - Options which modify the getRollData method. diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 2878ad0c..1bb3560f 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -3,7 +3,7 @@ import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs'; import DhLevelData from '../levelData.mjs'; import { commonActorRules } from './base.mjs'; import DhCreature from './creature.mjs'; -import { attributeField, stressDamageReductionRule, bonusField } from '../fields/actorField.mjs'; +import { attributeField, stressDamageReductionRule, bonusField, GoldField } from '../fields/actorField.mjs'; import { ActionField } from '../fields/actionField.mjs'; import DHCharacterSettings from '../../applications/sheets-configs/character-settings.mjs'; import { getArmorSources } from '../../helpers/utils.mjs'; @@ -18,7 +18,9 @@ export default class DhCharacter extends DhCreature { label: 'TYPES.Actor.character', type: 'character', settingSheet: DHCharacterSettings, - isNPC: false + isNPC: false, + hasInventory: true, + quantifiable: ['loot', 'consumable'] }); } @@ -62,12 +64,7 @@ export default class DhCharacter extends DhCreature { core: new fields.BooleanField({ initial: false }) }) ), - gold: new fields.SchemaField({ - coins: new fields.NumberField({ initial: 0, integer: true }), - handfuls: new fields.NumberField({ initial: 1, integer: true }), - bags: new fields.NumberField({ initial: 0, integer: true }), - chests: new fields.NumberField({ initial: 0, integer: true }) - }), + gold: new GoldField(), scars: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.GENERAL.scars' }), biography: new fields.SchemaField({ background: new fields.HTMLField(), @@ -153,7 +150,6 @@ export default class DhCharacter extends DhCreature { shortMoves: new fields.NumberField({ required: true, integer: true, - min: 0, initial: 0, label: 'DAGGERHEART.GENERAL.Bonuses.rest.shortRest.shortRestMoves.label', hint: 'DAGGERHEART.GENERAL.Bonuses.rest.shortRest.shortRestMoves.hint' @@ -161,7 +157,6 @@ export default class DhCharacter extends DhCreature { longMoves: new fields.NumberField({ required: true, integer: true, - min: 0, initial: 0, label: 'DAGGERHEART.GENERAL.Bonuses.rest.shortRest.longRestMoves.label', hint: 'DAGGERHEART.GENERAL.Bonuses.rest.shortRest.longRestMoves.hint' @@ -171,7 +166,6 @@ export default class DhCharacter extends DhCreature { shortMoves: new fields.NumberField({ required: true, integer: true, - min: 0, initial: 0, label: 'DAGGERHEART.GENERAL.Bonuses.rest.longRest.shortRestMoves.label', hint: 'DAGGERHEART.GENERAL.Bonuses.rest.longRest.shortRestMoves.hint' @@ -179,7 +173,6 @@ export default class DhCharacter extends DhCreature { longMoves: new fields.NumberField({ required: true, integer: true, - min: 0, initial: 0, label: 'DAGGERHEART.GENERAL.Bonuses.rest.longRest.longRestMoves.label', hint: 'DAGGERHEART.GENERAL.Bonuses.rest.longRest.longRestMoves.hint' @@ -293,6 +286,22 @@ export default class DhCharacter extends DhCreature { guaranteedCritical: new fields.BooleanField({ label: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.label', hint: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.hint' + }), + defaultAdvantageDice: new fields.NumberField({ + nullable: true, + required: true, + integer: true, + choices: CONFIG.DH.GENERAL.dieFaces, + initial: null, + label: 'DAGGERHEART.ACTORS.Character.defaultAdvantageDice' + }), + defaultDisadvantageDice: new fields.NumberField({ + nullable: true, + required: true, + integer: true, + choices: CONFIG.DH.GENERAL.dieFaces, + initial: null, + label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice' }) }) }) @@ -438,6 +447,11 @@ export default class DhCharacter extends DhCreature { return attack; } + /* All items are valid on characters */ + isItemValid() { + return true; + } + /** @inheritDoc */ isItemAvailable(item) { if (!super.isItemAvailable(this)) return false; @@ -736,13 +750,22 @@ export default class DhCharacter extends DhCreature { } } + /* Armor and ArmorEffects can set a Base Damage Threshold. Characters only gain level*2 bonus to severe if this is not present */ + const severeThresholdMulitplier = + this.armor || + this.parent.appliedEffects.some(x => + x.system.changes.some(x => x.type === 'armor' && x.value.damageThresholds) + ) + ? 1 + : 2; + this.damageThresholds = { major: this.armor ? this.armor.system.baseThresholds.major + this.levelData.level.current : this.levelData.level.current, severe: this.armor ? this.armor.system.baseThresholds.severe + this.levelData.level.current - : this.levelData.level.current * 2 + : this.levelData.level.current * severeThresholdMulitplier }; const globalHopeMax = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxHope; diff --git a/module/data/actor/companion.mjs b/module/data/actor/companion.mjs index 81d0aa8a..538031fb 100644 --- a/module/data/actor/companion.mjs +++ b/module/data/actor/companion.mjs @@ -61,6 +61,24 @@ export default class DhCompanion extends DhCreature { initial: false, label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.vulnerable' }) + }), + roll: new fields.SchemaField({ + defaultAdvantageDice: new fields.NumberField({ + nullable: true, + required: true, + integer: true, + choices: CONFIG.DH.GENERAL.dieFaces, + initial: null, + label: 'DAGGERHEART.ACTORS.Character.defaultAdvantageDice' + }), + defaultDisadvantageDice: new fields.NumberField({ + nullable: true, + required: true, + integer: true, + choices: CONFIG.DH.GENERAL.dieFaces, + initial: null, + label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice' + }) }) }), attack: new ActionField({ @@ -118,10 +136,6 @@ export default class DhCompanion extends DhCreature { return this.levelupChoicesLeft > 0; } - isItemValid() { - return false; - } - prepareBaseData() { super.prepareBaseData(); this.attack.roll.bonus = this.partner?.system?.spellcastModifier ?? 0; diff --git a/module/data/actor/environment.mjs b/module/data/actor/environment.mjs index e06f038c..e037e004 100644 --- a/module/data/actor/environment.mjs +++ b/module/data/actor/environment.mjs @@ -56,7 +56,7 @@ export default class DhEnvironment extends BaseDataActor { } isItemValid(source) { - return source.type === 'feature'; + return super.isItemValid(source) || source.type === 'feature'; } _onUpdate(changes, options, userId) { diff --git a/module/data/actor/party.mjs b/module/data/actor/party.mjs index ec1beb99..93596cda 100644 --- a/module/data/actor/party.mjs +++ b/module/data/actor/party.mjs @@ -2,8 +2,17 @@ import BaseDataActor from './base.mjs'; import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; import TagTeamData from '../tagTeamData.mjs'; import GroupRollData from '../groupRollData.mjs'; +import { GoldField } from '../fields/actorField.mjs'; export default class DhParty extends BaseDataActor { + /** @inheritdoc */ + static get metadata() { + return foundry.utils.mergeObject(super.metadata, { + hasInventory: true, + quantifiable: ['weapon', 'armor', 'loot', 'consumable'] + }); + } + /**@inheritdoc */ static defineSchema() { const fields = foundry.data.fields; @@ -11,17 +20,16 @@ export default class DhParty extends BaseDataActor { ...super.defineSchema(), partyMembers: new ForeignDocumentUUIDArrayField({ type: 'Actor' }, { prune: true }), notes: new fields.HTMLField(), - gold: new fields.SchemaField({ - coins: new fields.NumberField({ initial: 0, integer: true }), - handfuls: new fields.NumberField({ initial: 1, integer: true }), - bags: new fields.NumberField({ initial: 0, integer: true }), - chests: new fields.NumberField({ initial: 0, integer: true }) - }), + gold: new GoldField(), tagTeam: new fields.EmbeddedDataField(TagTeamData), groupRoll: new fields.EmbeddedDataField(GroupRollData) }; } + get active() { + return game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.ActiveParty) === this.parent.id; + } + /* -------------------------------------------- */ /**@inheritdoc */ @@ -29,10 +37,6 @@ export default class DhParty extends BaseDataActor { /* -------------------------------------------- */ - isItemValid(source) { - return ['weapon', 'armor', 'consumable', 'loot'].includes(source.type); - } - prepareBaseData() { super.prepareBaseData(); @@ -44,6 +48,16 @@ export default class DhParty extends BaseDataActor { } } + _onCreate(data, options, userId) { + super._onCreate(data, options, userId); + + if (game.user.isActiveGM && !game.actors.party) { + game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.ActiveParty, this.parent.id).then(_ => { + ui.actors.render(); + }); + } + } + _onDelete(options, userId) { super._onDelete(options, userId); @@ -51,5 +65,11 @@ export default class DhParty extends BaseDataActor { for (const member of this.partyMembers) { member?.parties?.delete(this.parent); } + + // If this *was* the active party, delete it. We can't use game.actors.party as this actor was already deleted + const isWorldActor = !this.parent?.parent && !this.parent.compendium; + const activePartyId = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.ActiveParty); + if (isWorldActor && this.id === activePartyId) + game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.ActiveParty, null); } } diff --git a/module/data/chat-message/abilityUse.mjs b/module/data/chat-message/abilityUse.mjs index 07209fe2..465461c0 100644 --- a/module/data/chat-message/abilityUse.mjs +++ b/module/data/chat-message/abilityUse.mjs @@ -7,26 +7,31 @@ export default class DHAbilityUse extends foundry.abstract.TypeDataModel { img: new fields.StringField({}), name: new fields.StringField({}), description: new fields.StringField({}), - actions: new fields.ArrayField( - new fields.ObjectField({ - name: new fields.StringField({}), - damage: new fields.SchemaField({ - type: new fields.StringField({}), - value: new fields.StringField({}) - }), - healing: new fields.SchemaField({ - type: new fields.StringField({}), - value: new fields.StringField({}) - }), - cost: new fields.SchemaField({ - type: new fields.StringField({}), - value: new fields.NumberField({}) - }), - target: new fields.SchemaField({ - type: new fields.StringField({ nullable: true }) - }) - }) - ) + source: new fields.SchemaField({ + actor: new fields.StringField(), + item: new fields.StringField(), + action: new fields.StringField() + }) }; } + + get actionActor() { + if (!this.source.actor) return null; + return fromUuidSync(this.source.actor); + } + + get actionItem() { + const actionActor = this.actionActor; + if (!actionActor || !this.source.item) return null; + + const item = actionActor.items.get(this.source.item); + return item ? item.system.actions?.find(a => a.id === this.source.action) : null; + } + + get action() { + const { actionItem: itemAction } = this; + if (!this.source.action) return null; + if (itemAction) return itemAction; + return null; + } } diff --git a/module/data/fields/action/_module.mjs b/module/data/fields/action/_module.mjs index fa3b1cd5..f6c34817 100644 --- a/module/data/fields/action/_module.mjs +++ b/module/data/fields/action/_module.mjs @@ -1,3 +1,4 @@ +export { default as AreasField } from './areasField.mjs'; export { default as CostField } from './costField.mjs'; export { default as CountdownField } from './countdownField.mjs'; export { default as UsesField } from './usesField.mjs'; diff --git a/module/data/fields/action/areasField.mjs b/module/data/fields/action/areasField.mjs new file mode 100644 index 00000000..52110045 --- /dev/null +++ b/module/data/fields/action/areasField.mjs @@ -0,0 +1,40 @@ +const fields = foundry.data.fields; + +export default class AreasField extends fields.ArrayField { + /** + * Action Workflow order + */ + static order = 150; + + /** @inheritDoc */ + constructor(options = {}, context = {}) { + const element = new fields.SchemaField({ + name: new fields.StringField({ + nullable: false, + initial: 'Area', + label: 'DAGGERHEART.GENERAL.name' + }), + type: new fields.StringField({ + nullable: false, + choices: CONFIG.DH.ACTIONS.areaTypes, + initial: CONFIG.DH.ACTIONS.areaTypes.placed.id, + label: 'DAGGERHEART.GENERAL.type' + }), + shape: new fields.StringField({ + nullable: false, + choices: CONFIG.DH.GENERAL.templateTypes, + initial: CONFIG.DH.GENERAL.templateTypes.circle.id, + label: 'DAGGERHEART.ACTIONS.Config.area.shape' + }), + /* Could be opened up to allow numbers to be input aswell. Probably best handled via an autocomplete in that case to allow the select options but also free text */ + size: new fields.StringField({ + nullable: false, + choices: CONFIG.DH.GENERAL.range, + initial: CONFIG.DH.GENERAL.range.veryClose.id, + label: 'DAGGERHEART.ACTIONS.Config.area.size' + }), + effects: new fields.ArrayField(new fields.DocumentIdField()) + }); + super(element, options, context); + } +} diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index 7839bf5a..30a5ad7c 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -320,7 +320,7 @@ export class DHDamageData extends DHResourceData { required: true }), { - label: 'Type' + label: game.i18n.localize('DAGGERHEART.GENERAL.type') } ) }; diff --git a/module/data/fields/action/summonField.mjs b/module/data/fields/action/summonField.mjs index dce6414c..ec7881f7 100644 --- a/module/data/fields/action/summonField.mjs +++ b/module/data/fields/action/summonField.mjs @@ -1,3 +1,4 @@ +import { itemAbleRollParse } from '../../../helpers/utils.mjs'; import FormulaField from '../formulaField.mjs'; const fields = foundry.data.fields; @@ -36,20 +37,23 @@ export default class DHSummonField extends fields.ArrayField { const rolls = []; const summonData = []; for (const summon of this.summon) { - let count = summon.count; - const roll = new Roll(summon.count); - if (!roll.isDeterministic) { - await roll.evaluate(); - if (game.modules.get('dice-so-nice')?.active) rolls.push(roll); - count = roll.total; - } + const roll = new Roll(itemAbleRollParse(summon.count, this.actor, this.item)); + await roll.evaluate(); + const count = roll.total; + if (!roll.isDeterministic && game.modules.get('dice-so-nice')?.active) rolls.push(roll); - const actor = DHSummonField.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.rolledCount = count; summon.actor = actor.toObject(); - summonData.push({ actor, count: count }); + const countNumber = Number.parseInt(count); + for (let i = 0; i < countNumber; i++) { + const remaining = countNumber - i; + summonData.push({ + actor, + tokenPreviewName: `${actor.prototypeToken.name}${remaining > 1 ? ` (${remaining}x)` : ''}` + }); + } } if (rolls.length) await Promise.all(rolls.map(roll => game.dice3d.showForRoll(roll, game.user, true))); @@ -58,32 +62,22 @@ export default class DHSummonField extends fields.ArrayField { 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 */ - static getWorldActor(baseActor) { + /* 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); - return worldActorCopy ?? baseActor; + if (worldActorCopy) return worldActorCopy; + + return await game.system.api.documents.DhpActor.create(baseActor.toObject()); } return baseActor; } - static async handleSummon(summonData, actionActor, summonIndex = 0) { - const summon = summonData[summonIndex]; - const result = await CONFIG.ux.TokenManager.createPreviewAsync(summon.actor, { - name: `${summon.actor.prototypeToken.name}${summon.count > 1 ? ` (${summon.count}x)` : ''}` - }); + static async handleSummon(summonData, actionActor) { + await CONFIG.ux.TokenManager.createTokensWithPreview(summonData, { elevation: actionActor.token?.elevation }); - if (!result) return actionActor.sheet?.maximize(); - summon.actor = result.actor; - - summon.count--; - if (summon.count <= 0) { - summonIndex++; - if (summonIndex === summonData.length) return actionActor.sheet?.maximize(); - } - - DHSummonField.handleSummon(summonData, actionActor, summonIndex); + return actionActor.sheet?.maximize(); } } diff --git a/module/data/fields/actionField.mjs b/module/data/fields/actionField.mjs index ffdc25cd..83672c8e 100644 --- a/module/data/fields/actionField.mjs +++ b/module/data/fields/actionField.mjs @@ -281,8 +281,14 @@ export function ActionMixin(Base) { name: this.name, img: this.baseAction ? this.parent.parent.img : this.img, tags: this.tags ? this.tags : ['Spell', 'Arcana', 'Lv 10'], + areas: this.areas, summon: this.summon }, + source: { + actor: this.actor.uuid, + item: this.item.id, + action: this.id + }, itemOrigin: this.item, description: this.description || (this.item instanceof Item ? this.item.system.description : '') }; diff --git a/module/data/fields/actorField.mjs b/module/data/fields/actorField.mjs index ae6f060c..d6b58675 100644 --- a/module/data/fields/actorField.mjs +++ b/module/data/fields/actorField.mjs @@ -103,4 +103,15 @@ class ResourcesField extends fields.TypedObjectField { } } -export { attributeField, ResourcesField, stressDamageReductionRule, bonusField }; +class GoldField extends fields.SchemaField { + constructor() { + super({ + coins: new fields.NumberField({ initial: 0, integer: true }), + handfuls: new fields.NumberField({ initial: 1, integer: true }), + bags: new fields.NumberField({ initial: 0, integer: true }), + chests: new fields.NumberField({ initial: 0, integer: true }) + }); + } +} + +export { attributeField, ResourcesField, GoldField, stressDamageReductionRule, bonusField }; diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs index 21a11149..f6c794f1 100644 --- a/module/data/item/base.mjs +++ b/module/data/item/base.mjs @@ -4,7 +4,6 @@ * @property {string} label - A localizable label used on application. * @property {string} type - The system type that this data model represents. * @property {boolean} hasDescription - Indicates whether items of this type have description field - * @property {boolean} isQuantifiable - Indicates whether items of this type have quantity field * @property {boolean} isInventoryItem- Indicates whether items of this type is a Inventory Item */ @@ -24,7 +23,6 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { type: 'base', hasDescription: false, hasResource: false, - isQuantifiable: false, isInventoryItem: false, hasActions: false, hasAttribution: true @@ -83,7 +81,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { ); } - if (this.metadata.isQuantifiable) + if (this.metadata.isInventoryItem) schema.quantity = new fields.NumberField({ integer: true, initial: 1, min: 0, required: true }); if (this.metadata.hasActions) schema.actions = new ActionsField(); @@ -110,6 +108,10 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { } get actionsList() { + // No actions on non-characters + if (this.metadata.isInventoryItem && this.actor && this.actor.type !== 'character') { + return []; + } return this.actions; } diff --git a/module/data/item/consumable.mjs b/module/data/item/consumable.mjs index ab527967..e83a1a53 100644 --- a/module/data/item/consumable.mjs +++ b/module/data/item/consumable.mjs @@ -7,7 +7,6 @@ export default class DHConsumable extends BaseDataItem { label: 'TYPES.Item.consumable', type: 'consumable', hasDescription: true, - isQuantifiable: true, isInventoryItem: true, hasActions: true }); diff --git a/module/data/item/loot.mjs b/module/data/item/loot.mjs index cdb0855e..d4092934 100644 --- a/module/data/item/loot.mjs +++ b/module/data/item/loot.mjs @@ -7,7 +7,6 @@ export default class DHLoot extends BaseDataItem { label: 'TYPES.Item.loot', type: 'loot', hasDescription: true, - isQuantifiable: true, isInventoryItem: true, hasActions: true }); diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index 9335037c..75e6dc8e 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -99,7 +99,9 @@ export default class DHWeapon extends AttachableItem { /* -------------------------------------------- */ get actionsList() { - return [this.attack, ...this.actions]; + // No actions on non-characters + if (this.actor && this.actor.type !== 'character') return []; + return [this.attack, ...super.actionsList]; } get customActions() { diff --git a/module/data/regionBehavior/_module.mjs b/module/data/regionBehavior/_module.mjs new file mode 100644 index 00000000..d0c8172d --- /dev/null +++ b/module/data/regionBehavior/_module.mjs @@ -0,0 +1 @@ +export { default as applyActiveEffect } from './applyActiveEffect.mjs'; diff --git a/module/data/regionBehavior/applyActiveEffect.mjs b/module/data/regionBehavior/applyActiveEffect.mjs new file mode 100644 index 00000000..51406cfa --- /dev/null +++ b/module/data/regionBehavior/applyActiveEffect.mjs @@ -0,0 +1,40 @@ +export default class DhApplyActiveEffect extends CONFIG.RegionBehavior.dataModels.applyActiveEffect { + static async #getApplicableEffects(token) { + const effects = await Promise.all(this.effects.map(foundry.utils.fromUuid)); + return effects.filter( + effect => !effect.system.targetDispositions.size || effect.system.targetDispositions.has(token.disposition) + ); + } + + static async #onTokenEnter(event) { + if (!event.user.isSelf) return; + const { token, movement } = event.data; + const actor = token.actor; + if (!actor) return; + const resumeMovement = movement ? token.pauseMovement() : undefined; + const effects = await DhApplyActiveEffect.#getApplicableEffects.bind(this)(event.data.token); + const toCreate = []; + for (const effect of effects) { + const data = effect.toObject(); + delete data._id; + if (effect.compendium) { + data._stats.duplicateSource = null; + data._stats.compendiumSource = effect.uuid; + } else { + data._stats.duplicateSource = effect.uuid; + data._stats.compendiumSource = null; + } + data._stats.exportSource = null; + data.origin = this.parent.uuid; + toCreate.push(data); + } + if (toCreate.length) await actor.createEmbeddedDocuments('ActiveEffect', toCreate); + await resumeMovement?.(); + } + + /** @override */ + static events = { + ...CONFIG.RegionBehavior.dataModels.applyActiveEffect.events, + [CONST.REGION_EVENTS.TOKEN_ENTER]: this.#onTokenEnter + }; +} diff --git a/module/data/tagTeamData.mjs b/module/data/tagTeamData.mjs index 25158606..640c2f6c 100644 --- a/module/data/tagTeamData.mjs +++ b/module/data/tagTeamData.mjs @@ -33,7 +33,7 @@ export class MemberData extends foundry.abstract.DataModel { required: true, choices: CONFIG.DH.GENERAL.tagTeamRollTypes, initial: CONFIG.DH.GENERAL.tagTeamRollTypes.trait.id, - label: 'Roll Type' + label: game.i18n.localize('DAGGERHEART.APPLICATIONS.TagTeamSelect.rollType') }), rollChoice: new fields.StringField({ nullable: true, initial: null }), rollData: new fields.JSONField({ nullable: true, initial: null }), diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index aa4dd75f..209631f6 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -145,6 +145,7 @@ export default class DHRoll extends Roll { roll: this, parent: chatData.parent, targetMode: chatData.targetMode, + areas: chatData.action?.areas, metagamingSettings }); } diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index f9a06d37..5e03a680 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -3,7 +3,6 @@ import D20Roll from './d20Roll.mjs'; import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs'; export default class DualityRoll extends D20Roll { - _advantageFaces = 6; _advantageNumber = 1; _rallyIndex; @@ -11,6 +10,11 @@ export default class DualityRoll extends D20Roll { super(formula, data, options); this.rallyChoices = this.setRallyChoices(); this.guaranteedCritical = options.guaranteedCritical; + + const advantageFaces = data.rules?.roll?.defaultAdvantageDice + ? Number.parseInt(data.rules.roll.defaultAdvantageDice) + : 6; + this.advantageFaces = Number.isNaN(advantageFaces) ? 6 : advantageFaces; } static messageType = 'dualityRoll'; @@ -51,14 +55,6 @@ export default class DualityRoll extends D20Roll { return this.dice[2] instanceof game.system.api.dice.diceTypes.DisadvantageDie ? this.dice[2] : null; } - get advantageFaces() { - return this._advantageFaces; - } - - set advantageFaces(faces) { - this._advantageFaces = this.getFaces(faces); - } - get advantageNumber() { return this._advantageNumber; } diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index 8ec7a751..227e2613 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -200,7 +200,6 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { static effectSafeEval(expression) { let result; try { - // eslint-disable-next-line no-new-func const evl = new Function('sandbox', `with (sandbox) { return ${expression}}`); result = evl(Roll.MATH_PROXY); } catch (err) { diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 3e3dfde4..db249033 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -113,11 +113,13 @@ export default class DhpActor extends Actor { _onUpdate(changes, options, userId) { super._onUpdate(changes, options, userId); for (const party of this.parties) { - party.render(); + party.render({ parts: ['partyMembers'] }); } } - async _preDelete() { + async _preDelete(options, user) { + if ((await super._preDelete(options, user)) === false) return false; + if (this.prototypeToken.actorLink) { game.system.registeredTriggers.unregisterItemTriggers(this.items); } else { @@ -130,7 +132,7 @@ export default class DhpActor extends Actor { _onDelete(options, userId) { super._onDelete(options, userId); for (const party of this.parties) { - party.render(); + party.render({ parts: ['partyMembers'] }); } } @@ -600,6 +602,7 @@ export default class DhpActor extends Actor { rollData.system = this.system.getRollData(); rollData.prof = this.system.proficiency ?? 1; rollData.cast = this.system.spellcastModifier ?? 1; + return rollData; } diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs index 307677bb..2e20fb87 100644 --- a/module/documents/chatMessage.mjs +++ b/module/documents/chatMessage.mjs @@ -137,6 +137,10 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { element.addEventListener('click', this.onApplyEffect.bind(this)) ); + for (const element of html.querySelectorAll('.action-areas')) { + element.addEventListener('click', this.onCreateAreas.bind(this)); + } + html.querySelectorAll('.roll-target').forEach(element => { element.addEventListener('mouseenter', this.hoverTarget); element.addEventListener('mouseleave', this.unhoverTarget); @@ -178,8 +182,8 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { const pendingingSaves = targets.filter(t => t.saved.success === null); if (pendingingSaves.length) { const confirm = await foundry.applications.api.DialogV2.confirm({ - window: { title: 'Pending Reaction Rolls found' }, - content: `

Some Tokens still need to roll their Reaction Roll.

Are you sure you want to continue ?

Undone reaction rolls will be considered as failed

` + window: { title: game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.title') }, + content: `

${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.unfinishedRolls')}

${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.confirmation')}

${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.warning')}

` }); if (!confirm) return; } @@ -249,6 +253,54 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { this.system.action?.workflow.get('effects')?.execute(config, targets, true); } + async onCreateAreas(event) { + const createArea = async selectedArea => { + const effects = selectedArea.effects.map(effect => this.system.action.item.effects.get(effect).uuid); + const { shape: type, size: range } = selectedArea; + const shapeData = CONFIG.Canvas.layers.regions.layerClass.getTemplateShape({ type, range }); + + await canvas.regions.placeRegion( + { + name: selectedArea.name, + shapes: [shapeData], + restriction: { enabled: false, type: 'move', priority: 0 }, + behaviors: [ + { + name: game.i18n.localize('TYPES.RegionBehavior.applyActiveEffect'), + type: 'applyActiveEffect', + system: { + effects: effects + } + } + ], + displayMeasurements: true, + locked: false, + ownership: { default: CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE }, + visibility: CONST.REGION_VISIBILITY.ALWAYS + }, + { create: true } + ); + }; + + if (this.system.action.areas.length === 1) createArea(this.system.action.areas[0]); + else if (this.system.action.areas.length > 1) { + new foundry.applications.ux.ContextMenu.implementation( + event.target, + '.action-areas', + this.system.action.areas.map(area => ({ + label: area.name, + onClick: () => createArea(area) + })), + { + jQuery: false, + fixed: true + } + ); + + CONFIG.ux.ContextMenu.triggerContextMenu(event, '.action-areas'); + } + } + filterPermTargets(targets) { return targets.filter(t => fromUuidSync(t.actorId)?.canUserModify(game.user, 'update')); } diff --git a/module/documents/collections/actorCollection.mjs b/module/documents/collections/actorCollection.mjs index a3714b30..115dd694 100644 --- a/module/documents/collections/actorCollection.mjs +++ b/module/documents/collections/actorCollection.mjs @@ -1,4 +1,11 @@ export default class DhActorCollection extends foundry.documents.collections.Actors { + /** @returns the active party */ + get party() { + const id = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.ActiveParty); + const actor = game.actors.get(id); + return actor?.type === 'party' ? actor : null; + } + /** Ensure companions are initialized after all other subtypes. */ _initialize() { super._initialize(); diff --git a/module/documents/item.mjs b/module/documents/item.mjs index d1a618c7..8ece56fa 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -31,8 +31,13 @@ export default class DHItem extends foundry.documents.Item { static async createDocuments(sources, operation) { // Ensure that items being created are valid to the actor its being added to const actor = operation.parent; - sources = actor?.system?.isItemValid ? sources.filter(s => actor.system.isItemValid(s)) : sources; - return super.createDocuments(sources, operation); + const filtered = actor ? sources.filter(s => actor.system.isItemValid(s)) : sources; + if (actor && filtered.length === 0 && sources.length > 0) { + const itemType = _loc(`TYPES.Item.${sources[0].type}`); + const actorType = _loc(`TYPES.Actor.${actor.type}`); + ui.notifications.error('DAGGERHEART.ACTORS.Base.CannotAddType', { format: { itemType, actorType } }); + } + return super.createDocuments(filtered, operation); } /* -------------------------------------------- */ @@ -71,6 +76,13 @@ export default class DHItem extends foundry.documents.Item { return this.system.metadata.isInventoryItem ?? false; } + /** Returns true if the item can be used */ + get usable() { + const actor = this.actor; + const actionsList = this.system.actionsList; + return this.isOwner && actor?.type === 'character' && (actionsList?.size || actionsList?.length); + } + /** @inheritdoc */ static async createDialog(data = {}, createOptions = {}, options = {}) { const { folders, types, template, context = {}, ...dialogOptions } = options; diff --git a/module/documents/tokenManager.mjs b/module/documents/tokenManager.mjs index f766a677..3ccff4e2 100644 --- a/module/documents/tokenManager.mjs +++ b/module/documents/tokenManager.mjs @@ -1,104 +1,68 @@ /** - * A singleton class that handles preview tokens. + * A singleton class that handles creating tokens. */ export default class DhTokenManager { - #activePreview; - #actor; - #resolve; - /** - * Create a template preview, deactivating any existing ones. - * @param {object} data + * Create a token previer + * @param {Actor} actor + * @param {object} tokenData */ async createPreview(actor, tokenData) { - this.#actor = actor; - const token = await canvas.tokens._createPreview( - { - ...actor.prototypeToken, - displayName: 50, - ...tokenData - }, - { renderSheet: false, actor } + const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes; + if (actor?.system.metadata.usesSize) { + const tokenSize = tokenSizes[actor.system.size]; + if (tokenSize && actor.system.size !== CONFIG.DH.ACTOR.tokenSize.custom.id) { + tokenData.width = tokenSize; + tokenData.height = tokenSize; + } + } + + return await canvas.tokens.placeTokens( + [ + { + ...actor.prototypeToken.toObject(), + actorId: actor.id, + displayName: 50, + ...tokenData + } + ], + { create: false } ); - - this.#activePreview = { - document: token.document, - object: token, - origin: { x: token.document.x, y: token.document.y } - }; - - this.#activePreview.events = { - contextmenu: this.#cancelTemplate.bind(this), - mousedown: this.#confirmTemplate.bind(this), - mousemove: this.#onDragMouseMove.bind(this) - }; - - canvas.stage.on('mousemove', this.#activePreview.events.mousemove); - canvas.stage.on('mousedown', this.#activePreview.events.mousedown); - canvas.app.view.addEventListener('contextmenu', this.#activePreview.events.contextmenu); - } - - /* Currently intended for using as a preview of where to create a token. (note the flag) */ - async createPreviewAsync(actor, tokenData = {}) { - return new Promise(resolve => { - this.#resolve = resolve; - this.createPreview(actor, { ...tokenData, flags: { daggerheart: { createPlacement: true } } }); - }); } /** - * Handles the movement of the token preview on mousedrag. - * @param {mousemove Event} event + * Creates new tokens on the canvas by placing previews. + * @param {object} tokenData + * @param {object} options */ - #onDragMouseMove(event) { - event.stopPropagation(); - const { moveTime, object } = this.#activePreview; - const update = {}; + async createTokensWithPreview(tokensData, { elevation } = {}) { + const scene = game.scenes.get(game.user.viewedScene); + if (!scene) return; - const now = Date.now(); - if (now - (moveTime || 0) <= 16) return; - this.#activePreview.moveTime = now; + const level = scene.levels.get(game.user.viewedLevel); + if (!level) return; - let cursor = event.getLocalPosition(canvas.templates); + const createElevation = elevation ?? level.elevation.bottom; + for (const tokenData of tokensData) { + const previewTokens = await this.createPreview(tokenData.actor, { + name: tokenData.tokenPreviewName, + level: game.user.viewedLevel, + elevation: createElevation, + flags: { daggerheart: { createPlacement: true } } + }); + if (!previewTokens?.length) return null; - Object.assign(update, canvas.grid.getTopLeftPoint(cursor)); - - object.document.updateSource(update); - object.renderFlags.set({ refresh: true }); - } - - /** - * Cancels the preview token on right-click. - * @param {contextmenu Event} event - */ - #cancelTemplate(_event, resolved) { - const { mousemove, mousedown, contextmenu } = this.#activePreview.events; - this.#activePreview.object.destroy(); - - canvas.stage.off('mousemove', mousemove); - canvas.stage.off('mousedown', mousedown); - canvas.app.view.removeEventListener('contextmenu', contextmenu); - if (this.#resolve && !resolved) this.#resolve(false); - } - - /** - * Creates a real Actor and token at the preview location and cancels the preview. - * @param {click Event} event - */ - async #confirmTemplate(event) { - event.stopPropagation(); - this.#cancelTemplate(event, true); - - const actor = this.#actor.inCompendium - ? await game.system.api.documents.DhpActor.create(this.#actor.toObject()) - : this.#actor; - const tokenData = await actor.getTokenDocument(); - const result = await canvas.scene.createEmbeddedDocuments('Token', [ - { ...tokenData.toObject(), x: this.#activePreview.document.x, y: this.#activePreview.document.y } - ]); - - this.#activePreview = undefined; - if (this.#resolve && result.length) this.#resolve(result[0]); + await canvas.scene.createEmbeddedDocuments( + 'Token', + 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/enrichers/TemplateEnricher.mjs b/module/enrichers/TemplateEnricher.mjs index cd0e7d9c..8db3ec14 100644 --- a/module/enrichers/TemplateEnricher.mjs +++ b/module/enrichers/TemplateEnricher.mjs @@ -12,7 +12,7 @@ export default function DhTemplateEnricher(match, _options) { )?.id : params.range; - if (!Object.values(CONFIG.DH.GENERAL.templateTypes).find(x => x === type) || !range) return match[0]; + if (!CONFIG.DH.GENERAL.templateTypes[type] || !range) return match[0]; const label = game.i18n.localize(`DAGGERHEART.CONFIG.TemplateTypes.${type}`); const rangeDisplay = Number.isNaN(Number(range)) @@ -49,8 +49,6 @@ export default function DhTemplateEnricher(match, _options) { } export const renderMeasuredTemplate = async event => { - const { LINE, RECTANGLE, INFRONT, CONE } = CONFIG.DH.GENERAL.templateTypes; - const button = event.currentTarget, type = button.dataset.type, range = button.dataset.range, @@ -59,49 +57,16 @@ export const renderMeasuredTemplate = async event => { if (!type || !range || !game.canvas.scene) return; - const usedType = type === 'inFront' ? 'cone' : type; - const usedAngle = - type === CONE ? (angle ?? CONFIG.MeasuredTemplate.defaults.angle) : type === INFRONT ? '180' : undefined; - - let baseDistance = getTemplateDistance(range); - - const { grid, distance } = CONFIG.Scene.documentClass.schema.fields.grid.fields; - const sceneGridSize = canvas.scene?.grid.size ?? grid.size.initial; - const sceneGridDistance = canvas.scene?.grid.distance ?? distance.getInitialValue(); - const dimensionConstant = sceneGridSize / sceneGridDistance; - - baseDistance *= dimensionConstant; - - const length = baseDistance; - const radius = length; - - const shapeWidth = type === LINE ? 5 * dimensionConstant : type === RECTANGLE ? length : undefined; - - const { width, height } = game.canvas.scene.dimensions; - const shapeData = { - x: width / 2, - y: height / 2, - base: { - type: 'token', - x: 0, - y: 0, - width: 1, - height: 1, - shape: game.canvas.grid.isHexagonal ? CONST.TOKEN_SHAPES.ELLIPSE_1 : CONST.TOKEN_SHAPES.RECTANGLE_1 - }, - t: usedType, - length: length, - width: shapeWidth, - height: length, - angle: usedAngle, - radius: radius, - direction: direction, - type: usedType - }; + const shapeData = CONFIG.Canvas.layers.regions.layerClass.getTemplateShape({ + type, + angle, + range, + direction + }); await canvas.regions.placeRegion( { - name: usedType.capitalize(), + name: type.capitalize(), shapes: [shapeData], restriction: { enabled: false, type: 'move', priority: 0 }, behaviors: [], @@ -113,11 +78,3 @@ export const renderMeasuredTemplate = async event => { { create: true } ); }; - -const getTemplateDistance = range => { - const rangeNumber = Number(range); - if (!Number.isNaN(rangeNumber)) return rangeNumber; - - const settings = canvas.scene?.rangeSettings; - return settings ? settings[range] : 0; -}; diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index 131f94b7..4527da1a 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -189,7 +189,13 @@ export const getDeleteKeys = (property, innerProperty, innerPropertyDefaultValue // Fix on Foundry native formula replacement for DH const nativeReplaceFormulaData = Roll.replaceFormulaData; -Roll.replaceFormulaData = function (formula, data = {}, { missing, warn = false } = {}) { +Roll.replaceFormulaData = function (formula, baseData = {}, { missing, warn = false } = {}) { + /* Inserting global data */ + const data = { + ...baseData, + partySize: game.actors?.party?.system.partyMembers.length ?? 0 + }; + const terms = Object.keys(CONFIG.DH.GENERAL.multiplierTypes).map(type => { return { term: type, default: 1 }; }); diff --git a/module/systemRegistration/handlebars.mjs b/module/systemRegistration/handlebars.mjs index 63e591c6..1b08e0ad 100644 --- a/module/systemRegistration/handlebars.mjs +++ b/module/systemRegistration/handlebars.mjs @@ -10,6 +10,7 @@ export const preloadHandlebarsTemplates = async function () { 'templates/generic/tab-navigation.hbs', 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs', 'systems/daggerheart/templates/sheets/global/partials/action-item.hbs', + 'systems/daggerheart/templates/sheets/global/partials/gold.hbs', 'systems/daggerheart/templates/sheets/global/partials/domain-card-item.hbs', 'systems/daggerheart/templates/sheets/global/partials/item-resource.hbs', 'systems/daggerheart/templates/sheets/global/partials/resource-section/resource-section.hbs', @@ -28,6 +29,7 @@ export const preloadHandlebarsTemplates = async function () { 'systems/daggerheart/templates/actionTypes/uses.hbs', 'systems/daggerheart/templates/actionTypes/roll.hbs', 'systems/daggerheart/templates/actionTypes/save.hbs', + 'systems/daggerheart/templates/actionTypes/areas.hbs', 'systems/daggerheart/templates/actionTypes/cost.hbs', 'systems/daggerheart/templates/actionTypes/range-target.hbs', 'systems/daggerheart/templates/actionTypes/effect.hbs', diff --git a/module/systemRegistration/settings.mjs b/module/systemRegistration/settings.mjs index 63611cda..41cab011 100644 --- a/module/systemRegistration/settings.mjs +++ b/module/systemRegistration/settings.mjs @@ -52,6 +52,27 @@ export const registerKeyBindings = () => { reservedModifiers: [], precedence: CONST.KEYBINDING_PRECEDENCE.NORMAL }); + + game.keybindings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.keybindings.partySheet, { + name: _loc('DAGGERHEART.SETTINGS.Keybindings.partySheet.name'), + hint: _loc('DAGGERHEART.SETTINGS.Keybindings.partySheet.hint'), + editable: [{ key: 'KeyP' }], + onDown: () => { + const controlled = canvas.ready ? canvas.tokens.controlled : []; + const selectedParty = controlled.find(c => c.actor?.type === 'party')?.actor; + const party = selectedParty ?? game.actors.party; + if (!party) return; + + const sheet = party.sheet; + if (!sheet.rendered) { + sheet.render(true); + } else if (sheet.minimized) { + sheet.maximize(); + } else { + sheet.close(); + } + } + }); }; const registerMenuSettings = () => { @@ -189,4 +210,11 @@ const registerNonConfigSettings = () => { config: false, type: SpotlightTracker }); + + game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.ActiveParty, { + scope: 'world', + config: false, + type: String, + default: null + }); }; diff --git a/package-lock.json b/package-lock.json index 864d027c..b8fef1cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,9 @@ "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "concurrently": "^8.2.2", + "eslint": "^10.2.1", + "eslint-plugin-prettier": "^5.5.5", + "globals": "^17.5.0", "husky": "^9.1.5", "lint-staged": "^15.2.10", "postcss": "^8.4.32", @@ -32,6 +35,152 @@ "node": ">=6.9.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz", + "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", + "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, "node_modules/@foundryvtt/foundryvtt-cli": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@foundryvtt/foundryvtt-cli/-/foundryvtt-cli-1.1.0.tgz", @@ -72,12 +221,91 @@ "node": ">=10.13.0" } }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, "node_modules/@rollup/plugin-commonjs": { "version": "25.0.8", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", @@ -415,11 +643,25 @@ "node": ">=10.13.0" } }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -458,6 +700,46 @@ "node": ">=12" } }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -1417,6 +1699,13 @@ } } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -1622,6 +1911,190 @@ "node": ">=6" } }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.1.tgz", + "integrity": "sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.5.5", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", + "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.12" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -1631,12 +2104,76 @@ "node": ">=6" } }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -1694,11 +2231,32 @@ "node": ">=0.10.0" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-levenshtein": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", @@ -1723,6 +2281,19 @@ "reusify": "^1.0.4" } }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -1734,6 +2305,23 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/findup-sync": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", @@ -1771,6 +2359,27 @@ "node": ">= 10.13.0" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -2033,6 +2642,19 @@ "which": "bin/which" } }, + "node_modules/globals": { + "version": "17.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.5.0.tgz", + "integrity": "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glogg": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/glogg/-/glogg-2.2.0.tgz", @@ -2381,6 +3003,16 @@ } ] }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/image-size": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", @@ -2423,6 +3055,16 @@ "node": ">=8" } }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2769,6 +3411,37 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/last-run": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/last-run/-/last-run-2.0.0.tgz", @@ -2832,6 +3505,20 @@ "node": ">=12" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lie": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", @@ -2932,6 +3619,22 @@ "lie": "3.1.1" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -3202,6 +3905,13 @@ "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==", "dev": true }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/nedb-promises": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/nedb-promises/-/nedb-promises-6.2.3.tgz", @@ -3370,6 +4080,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optionator/node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -3379,6 +4114,38 @@ "node": ">=4" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-queue": { "version": "6.6.2", "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", @@ -3442,6 +4209,16 @@ "node": ">=0.10.0" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4140,6 +4917,16 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", @@ -4155,6 +4942,19 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/promise.series": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", @@ -4181,6 +4981,16 @@ "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", "optional": true }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4950,6 +5760,22 @@ "node": ">= 10" } }, + "node_modules/synckit": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/teex": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", @@ -5010,6 +5836,19 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -5070,6 +5909,16 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -5222,6 +6071,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", @@ -5313,6 +6172,19 @@ "engines": { "node": ">=12" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 183d2de2..28c83549 100644 --- a/package.json +++ b/package.json @@ -17,13 +17,18 @@ "pullYMLtoLDB": "node ./tools/pullYMLtoLDB.mjs", "pullYMLtoLDBBuild": "node ./tools/pullYMLtoLDB.mjs --build", "createSymlink": "node ./tools/create-symlink.mjs", - "setup:dev": "node ./tools/dev-setup.mjs" + "setup:dev": "node ./tools/dev-setup.mjs", + "lint": "eslint", + "lint:fix": "eslint --fix" }, "devDependencies": { "@foundryvtt/foundryvtt-cli": "^1.0.2", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "concurrently": "^8.2.2", + "eslint": "^10.2.1", + "eslint-plugin-prettier": "^5.5.5", + "globals": "^17.5.0", "husky": "^9.1.5", "lint-staged": "^15.2.10", "postcss": "^8.4.32", diff --git a/src/packs/adversaries/adversary_Acid_Burrower_89yAh30vaNQOALlz.json b/src/packs/adversaries/adversary_Acid_Burrower_89yAh30vaNQOALlz.json index 0dd182fa..d3c8c955 100644 --- a/src/packs/adversaries/adversary_Acid_Burrower_89yAh30vaNQOALlz.json +++ b/src/packs/adversaries/adversary_Acid_Burrower_89yAh30vaNQOALlz.json @@ -169,12 +169,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -225,7 +222,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -251,7 +248,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -319,7 +317,7 @@ "_id": "ctXYwil2D1zfsekT", "img": "icons/magic/earth/barrier-stone-explosion-red.webp", "system": { - "description": "

Mark a Stress to have the @Lookup[@name] burst out of the ground. All creatures within Very Close range must succeed on an Agility Reaction Roll or be knocked over, making them Vulnerable until they next act.

@Template[type:emanation|range:vc]

", + "description": "

Mark a Stress to have the @Lookup[@name] burst out of the ground. All creatures within Very Close range must succeed on an Agility Reaction Roll or be knocked over, making them Vulnerable until they next act.

", "resource": null, "actions": { "4ppSeiTdbqnMzWAs": { @@ -344,7 +342,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -378,7 +377,16 @@ }, "name": "Roll Save", "img": "icons/magic/earth/barrier-stone-explosion-red.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Earth Eruption", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, @@ -581,7 +589,7 @@ "_id": "aNIVT5LKhwLyjKpI", "img": "icons/magic/acid/dissolve-drip-droplet-smoke.webp", "system": { - "description": "

When the @Lookup[@name] takes Severe damage, all creatures within Close range are bathed in their acidic blood, taking 1d10 physical damage. This splash covers the ground within Very Close range with blood, and all creatures other than the @Lookup[@name] who move through it take 1d6 physical damage.

@Template[type:emanation|range:c]

", + "description": "

When the @Lookup[@name] takes Severe damage, all creatures within Close range are bathed in their acidic blood, taking 1d10 physical damage. This splash covers the ground within Very Close range with blood, and all creatures other than the @Lookup[@name] who move through it take 1d6 physical damage.

", "resource": null, "actions": { "XbtTzOBvlTaxOKTy": { @@ -627,7 +635,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -636,7 +645,23 @@ "effects": [], "name": "Splash", "img": "icons/magic/acid/dissolve-drip-droplet-smoke.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Acid Bath: Damage Area", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + }, + { + "name": "Acid Ground", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] }, "xpcp1ECTWF20kxve": { "type": "damage", @@ -690,7 +715,8 @@ "effects": [], "name": "Acid Ground", "img": "icons/magic/acid/dissolve-pool-bubbles.webp", - "range": "" + "range": "", + "areas": [] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json b/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json index c4b4eb2a..ecb93d1b 100644 --- a/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json +++ b/src/packs/adversaries/adversary_Adult_Flickerfly_G7jiltRjgvVhZewm.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -376,7 +374,7 @@ "name": "Whirlwind", "type": "feature", "system": { - "description": "

Spend a Fear to whirl, making an attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against take 3d8 direct physical damage.

@Template[type:emanation|range:vc]

", + "description": "

Spend a Fear to whirl, making an attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against take 3d8 direct physical damage.

", "resource": null, "actions": { "RV1wKufKrMPN6MOo": { @@ -429,7 +427,8 @@ } }, "includeBase": false, - "direct": true + "direct": true, + "groupAttack": "" }, "target": { "type": "any", @@ -458,7 +457,16 @@ }, "name": "Attack", "img": "icons/skills/melee/strike-slashes-orange.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Whirlwind", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, @@ -484,7 +492,7 @@ "name": "Mind Dance", "type": "feature", "system": { - "description": "

Mark a Stress to create a magically dazzling display that grapples the minds of nearby foes. All targets within Close range must make an Instinct Reaction Roll. For each target who failed, you gain a Fear and the @Lookup[@name] learns one of the target’s fears.

@Template[type:emanation|range:c]

", + "description": "

Mark a Stress to create a magically dazzling display that grapples the minds of nearby foes. All targets within Close range must make an Instinct Reaction Roll. For each target who failed, you gain a Fear and the @Lookup[@name] learns one of the target’s fears.

", "resource": null, "actions": { "GNwsDlCabx3fiG4g": { @@ -509,7 +517,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -538,7 +547,16 @@ }, "name": "Roll Save", "img": "icons/magic/light/explosion-glow-spiral-yellow.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Mind Dance", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -564,14 +582,14 @@ "name": "Hallucinatory Breath", "type": "feature", "system": { - "description": "

Countdown (Loop 1d6). When the @Lookup[@name] takes damage for the first time, activate the countdown. When it triggers, the @Lookup[@name] breathes hallucinatory gas on all targets in front of them up to Far range. Targets must make an Instinct Reaction Roll or be tormented by fearful hallucinations. Targets whose fears are known to the @Lookup[@name] have disadvantage on this roll. Targets who fail lose 2 Hope and take 3d8+3 direct magic damage.

@Template[type:inFront|range:f]

", + "description": "

Countdown (Loop 1d6). When the @Lookup[@name] takes damage for the first time, activate the countdown. When it triggers, the @Lookup[@name] breathes hallucinatory gas on all targets in front of them up to Far range. Targets must make an Instinct Reaction Roll or be tormented by fearful hallucinations. Targets whose fears are known to the @Lookup[@name] have disadvantage on this roll. Targets who fail lose 2 Hope and take 3d8+3 direct magic damage.

", "resource": null, "actions": { "YOyKyKGTUEWkMmJe": { "type": "attack", "_id": "YOyKyKGTUEWkMmJe", "systemPath": "actions", - "description": "

The @Lookup[@name] breathes hallucinatory gas on all targets in front of them up to Far range. Targets must make an Instinct Reaction Roll or be tormented by fearful hallucinations. Targets whose fears are known to the @Lookup[@name] have disadvantage on this roll. Targets who fail lose 2 Hope and take 3d8+3 direct magic damage.

@Template[type:inFront|range:f]

", + "description": "", "chatDisplay": true, "actionType": "action", "cost": [], @@ -634,7 +652,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -663,7 +682,16 @@ }, "name": "Roll Save", "img": "icons/magic/air/fog-gas-smoke-purple.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Hallucinatory Breath", + "type": "placed", + "shape": "inFront", + "size": "far", + "effects": [] + } + ] }, "lBhmLc33pcXzJHT3": { "type": "countdown", diff --git a/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json b/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json index dfae0598..5da74eb3 100644 --- a/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json +++ b/src/packs/adversaries/adversary_Arch_Necromancer_WPEOIGfclNJxWb87.json @@ -143,12 +143,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -199,7 +196,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -225,7 +222,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -312,7 +310,7 @@ "name": "Beam Of Decay", "type": "feature", "system": { - "description": "

Mark 2 Stress to cause all targets within Far range to make a Strength Reaction Roll. Targets who fail take 2d20+12 magic damage and you gain a Fear. Targets who succeed take half damage. A target who marks 2 or more HP must also mark 2 Stress and becomes Vulnerable until they roll with Hope.

@Template[type:emanation|range:f]

", + "description": "

Mark 2 Stress to cause all targets within Far range to make a Strength Reaction Roll. Targets who fail take 2d20+12 magic damage and you gain a Fear. Targets who succeed take half damage. A target who marks 2 or more HP must also mark 2 Stress and becomes Vulnerable until they roll with Hope.

", "resource": null, "actions": { "vaXLESD4sRkQ3Ahn": { @@ -364,7 +362,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -398,7 +397,16 @@ }, "name": "Roll Save", "img": "icons/magic/unholy/projectile-missile-green.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Beam Of Decay", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] }, "ME8AMAjgTAChHa3C": { "type": "healing", diff --git a/src/packs/adversaries/adversary_Archer_Squadron_0ts6CGd93lLqGZI5.json b/src/packs/adversaries/adversary_Archer_Squadron_0ts6CGd93lLqGZI5.json index 67e10c53..1e45b90a 100644 --- a/src/packs/adversaries/adversary_Archer_Squadron_0ts6CGd93lLqGZI5.json +++ b/src/packs/adversaries/adversary_Archer_Squadron_0ts6CGd93lLqGZI5.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -246,7 +244,7 @@ "name": "Focused Volley", "type": "feature", "system": { - "description": "

Spend a Fear to target a point within Far range. Make an attack with advantage against all targets within Close range of that point. Targets the @Lookup[@name] succeeds against take 1d10+4 physical damage.

@Template[type:circle|range:c]

", + "description": "

Spend a Fear to target a point within Far range. Make an attack with advantage against all targets within Close range of that point. Targets the @Lookup[@name] succeeds against take 1d10+4 physical damage.

", "resource": null, "actions": { "uG7Hl2DqaT69aNs1": { @@ -296,7 +294,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -325,7 +324,16 @@ }, "name": "Attack", "img": "icons/skills/ranged/arrows-flying-triple-brown.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Focused Volley", + "type": "placed", + "shape": "circle", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -351,7 +359,7 @@ "name": "Supressing Fire", "type": "feature", "system": { - "description": "

Mark a Stress to target a point within Far range. Until the next roll with Fear, a creature who moves within Close range of that point must make an Agility Reaction Roll. On a failure, they take 2d6+3 physical damage. On a success, they take half damage.

@Template[type:circle|range:c]

", + "description": "

Mark a Stress to target a point within Far range. Until the next roll with Fear, a creature who moves within Close range of that point must make an Agility Reaction Roll. On a failure, they take 2d6+3 physical damage. On a success, they take half damage.

", "resource": null, "actions": { "mH6mmJIMM1fwzePt": { @@ -394,7 +402,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -423,7 +432,16 @@ }, "name": "Agility Roll", "img": "icons/skills/ranged/arrows-flying-salvo-blue.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Supressing Fire", + "type": "placed", + "shape": "circle", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Assassin_Poisoner_h5RuhzGL17dW5FBT.json b/src/packs/adversaries/adversary_Assassin_Poisoner_h5RuhzGL17dW5FBT.json index 4b3a872a..c1bce57b 100644 --- a/src/packs/adversaries/adversary_Assassin_Poisoner_h5RuhzGL17dW5FBT.json +++ b/src/packs/adversaries/adversary_Assassin_Poisoner_h5RuhzGL17dW5FBT.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,7 +217,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -399,7 +397,7 @@ "name": "Fumigation", "type": "feature", "system": { - "description": "

Drop a smoke bomb that fills the air within Close range with smoke, Dizzying all targets in this area. Dizzied targets have disadvantage on their next action roll, then clear the condition.

@Template[type:emanation|range:c]

", + "description": "

Drop a smoke bomb that fills the air within Close range with smoke, Dizzying all targets in this area. Dizzied targets have disadvantage on their next action roll, then clear the condition.

", "resource": null, "actions": { "sp7RfJRQJsEUm09m": { @@ -427,7 +425,16 @@ }, "name": "Drop Bomb", "img": "icons/magic/air/fog-gas-smoke-green.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Fumigation", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -450,18 +457,15 @@ "type": "withinRange", "target": "hostile", "range": "melee" - } + }, + "changes": [] }, - "changes": [], "disabled": false, "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null + "value": null, + "units": "seconds", + "expiry": null, + "expired": false }, "description": "

Dizzied targets have disadvantage on their next action roll, then clear the condition.

", "tint": "#ffffff", @@ -471,6 +475,9 @@ "_stats": { "compendiumSource": null }, + "start": null, + "showIcon": 1, + "folder": null, "_key": "!actors.items.effects!h5RuhzGL17dW5FBT.lAmiK8wVxjyHwKlp.yP4ot8VqS56RnxnE" } ], diff --git a/src/packs/adversaries/adversary_Battle_Box_dgH3fW9FTYLaIDvS.json b/src/packs/adversaries/adversary_Battle_Box_dgH3fW9FTYLaIDvS.json index 74ed8dfd..be47829b 100644 --- a/src/packs/adversaries/adversary_Battle_Box_dgH3fW9FTYLaIDvS.json +++ b/src/packs/adversaries/adversary_Battle_Box_dgH3fW9FTYLaIDvS.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,7 +217,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -465,7 +463,7 @@ "name": "Fire Jets", "type": "feature", "system": { - "description": "

The @Lookup[@name] shoots into the air, spinning and releasing jets of flame. Make an attack against all targets within Close range. Targets the @Lookup[@name] succeeds against take 2d8 physical damage.

@Template[type:emanation|range:c]

", + "description": "

The @Lookup[@name] shoots into the air, spinning and releasing jets of flame. Make an attack against all targets within Close range. Targets the @Lookup[@name] succeeds against take 2d8 physical damage.

", "resource": null, "actions": { "hRAKaOdzQXLYBNVV": { @@ -510,7 +508,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -539,7 +538,16 @@ }, "name": "Attack", "img": "icons/magic/fire/explosion-embers-orange.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Fire Jets", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -565,7 +573,7 @@ "name": "Trample", "type": "feature", "system": { - "description": "

The @Lookup[@name] rockets around erratically. Make an attack against all PCs within Close range. Targets the @Lookup[@name] succeeds against take 1d6+5 physical damage and are Vulnerable until their next roll with Hope.

@Template[type:emanation|range:c]

", + "description": "

The @Lookup[@name] rockets around erratically. Make an attack against all PCs within Close range. Targets the @Lookup[@name] succeeds against take 1d6+5 physical damage and are Vulnerable until their next roll with Hope.

", "resource": null, "actions": { "IOgPMu12Xnn33TfG": { @@ -610,7 +618,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -644,7 +653,16 @@ }, "name": "Attack", "img": "icons/skills/movement/arrow-upward-yellow.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Trample", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -720,7 +738,7 @@ "name": "Shocking Gas", "type": "feature", "system": { - "description": "

The @Lookup[@name] sprays out a silver gas sparking with lightning. All targets within Close range must succeed on a Finesse Reaction Roll or mark 3 Stress.

@Template[type:emanation|range:c]

", + "description": "

The @Lookup[@name] sprays out a silver gas sparking with lightning. All targets within Close range must succeed on a Finesse Reaction Roll or mark 3 Stress.

", "resource": null, "actions": { "ky4OMl558J5wCbDp": { @@ -764,7 +782,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -793,7 +812,16 @@ }, "name": "Roll Save", "img": "icons/magic/lightning/bolt-strike-embers-teal.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Shocking Gas", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -819,7 +847,7 @@ "name": "Stunning Clap", "type": "feature", "system": { - "description": "

The @Lookup[@name] leaps and their sides clap, creating a small sonic boom. All targets within Very Close range must succeed on a Strength Reaction Roll or become Vulnerable until the cube is defeated.

@Template[type:emanation|range:vc]

", + "description": "

The @Lookup[@name] leaps and their sides clap, creating a small sonic boom. All targets within Very Close range must succeed on a Strength Reaction Roll or become Vulnerable until the cube is defeated.

", "resource": null, "actions": { "LQtopkrtSlCQ5MAr": { @@ -837,7 +865,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -871,7 +900,16 @@ }, "name": "Roll Save", "img": "icons/magic/sonic/explosion-impact-shock-wave.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Stunning Clap", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, @@ -947,7 +985,7 @@ "name": "Psionic Whine", "type": "feature", "system": { - "description": "

The @Lookup[@name] releases a cluster of mechanical bees whose buzz rattles mortal minds. All targets within Close range must succeed on a Presence Reaction Roll or take 2d4+9 direct magic damage.

@Template[type:emanation|range:c]

", + "description": "

The @Lookup[@name] releases a cluster of mechanical bees whose buzz rattles mortal minds. All targets within Close range must succeed on a Presence Reaction Roll or take 2d4+9 direct magic damage.

", "resource": null, "actions": { "3R3pGOUj4rHaUzPK": { @@ -992,7 +1030,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -1021,7 +1060,16 @@ }, "name": "Bees!", "img": "icons/creatures/invertebrates/wasp-swarm-tan.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Psionic Whine", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -1148,7 +1196,7 @@ "name": "Death Quake", "type": "feature", "system": { - "description": "

When the @Lookup[@name] marks their last HP, the magic powering them ruptures in an explosion of force. All targets within Close range must succeed on an Instinct Reaction Roll or take 2d8+1 magic damage

@Template[type:emanation|range:c]

", + "description": "

When the @Lookup[@name] marks their last HP, the magic powering them ruptures in an explosion of force. All targets within Close range must succeed on an Instinct Reaction Roll or take 2d8+1 magic damage

", "resource": null, "actions": { "oCpv4zi9jtEpo0K1": { @@ -1193,7 +1241,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -1222,7 +1271,16 @@ }, "name": "Roll Save", "img": "icons/magic/sonic/explosion-shock-wave-teal.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Death Quake", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Cave_Ogre_8Zkqk1jU09nKL2fy.json b/src/packs/adversaries/adversary_Cave_Ogre_8Zkqk1jU09nKL2fy.json index cb081441..a1bf6bc9 100644 --- a/src/packs/adversaries/adversary_Cave_Ogre_8Zkqk1jU09nKL2fy.json +++ b/src/packs/adversaries/adversary_Cave_Ogre_8Zkqk1jU09nKL2fy.json @@ -139,12 +139,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -195,7 +192,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -221,7 +218,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -312,7 +310,7 @@ "_id": "zGvaBYJPOOnQVQEn", "img": "icons/magic/earth/projectile-stone-boulder-orange.webp", "system": { - "description": "

Mark a Stress to pick up heavy objects and throw them at all targets in front of the @Lookup[@name] within Far range. Make an attack against these targets. Targets the @Lookup[@name] succeeds against take 1d10+2 physical damage. If they succeed against more than one target, you gain a Fear.

@Template[type:inFront|range:f]

", + "description": "

Mark a Stress to pick up heavy objects and throw them at all targets in front of the @Lookup[@name] within Far range. Make an attack against these targets. Targets the @Lookup[@name] succeeds against take 1d10+2 physical damage. If they succeed against more than one target, you gain a Fear.

", "resource": null, "actions": { "3p1qfHy5uHe4H2hB": { @@ -367,7 +365,8 @@ } }, "includeBase": false, - "direct": true + "direct": true, + "groupAttack": "" }, "target": { "type": "any", @@ -396,7 +395,16 @@ }, "name": "Throw", "img": "icons/magic/earth/projectile-stone-boulder-orange.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Hail of Boulders", + "type": "placed", + "shape": "inFront", + "size": "far", + "effects": [] + } + ] }, "pmeromzI4eQOilbp": { "type": "healing", diff --git a/src/packs/adversaries/adversary_Chaos_Skull_jDmHqGvzg5wjgmxE.json b/src/packs/adversaries/adversary_Chaos_Skull_jDmHqGvzg5wjgmxE.json index a95db1b7..876519cf 100644 --- a/src/packs/adversaries/adversary_Chaos_Skull_jDmHqGvzg5wjgmxE.json +++ b/src/packs/adversaries/adversary_Chaos_Skull_jDmHqGvzg5wjgmxE.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -359,7 +357,7 @@ "name": "Magic Burst", "type": "feature", "system": { - "description": "

Mark a Stress to make an attack against all targets within Close range. Targets the @Lookup[@name] succeeds against take 2d6+4 magic damage.

@Template[type:emanation|range:c]

", + "description": "

Mark a Stress to make an attack against all targets within Close range. Targets the @Lookup[@name] succeeds against take 2d6+4 magic damage.

", "resource": null, "actions": { "iF0PD1t3yovKMTfy": { @@ -411,7 +409,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -440,7 +439,16 @@ }, "name": "Attack", "img": "icons/magic/lightning/bolt-strike-purple.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Magic Burst", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Construct_uOP5oT9QzXPlnf3p.json b/src/packs/adversaries/adversary_Construct_uOP5oT9QzXPlnf3p.json index 067248c9..3bd154ef 100644 --- a/src/packs/adversaries/adversary_Construct_uOP5oT9QzXPlnf3p.json +++ b/src/packs/adversaries/adversary_Construct_uOP5oT9QzXPlnf3p.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -562,7 +560,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -591,7 +590,16 @@ }, "name": "Attack", "img": "icons/magic/sonic/explosion-shock-wave-teal.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Death Quake", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Cult_Adept_0NxCSugvKQ4W8OYZ.json b/src/packs/adversaries/adversary_Cult_Adept_0NxCSugvKQ4W8OYZ.json index cbb48681..27553d32 100644 --- a/src/packs/adversaries/adversary_Cult_Adept_0NxCSugvKQ4W8OYZ.json +++ b/src/packs/adversaries/adversary_Cult_Adept_0NxCSugvKQ4W8OYZ.json @@ -143,12 +143,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -199,7 +196,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -225,7 +222,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -486,7 +484,7 @@ "name": "Shadow Shackles", "type": "feature", "system": { - "description": "

Spend a Fear and choose a point within Far range. All targets within Close range of that point are Restrained in smoky chains until they break free with a successful Strength or Instinct Roll. A target Restrained by this feature must spend a Hope to make an action roll.

@Template[type:circle|range:c]

", + "description": "

Spend a Fear and choose a point within Far range. All targets within Close range of that point are Restrained in smoky chains until they break free with a successful Strength or Instinct Roll. A target Restrained by this feature must spend a Hope to make an action roll.

", "resource": null, "actions": { "g4RDHrY0AEYXjH52": { @@ -521,7 +519,16 @@ }, "name": "Spend Fear", "img": "icons/magic/air/fog-gas-smoke-dense-pink.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Shadow Shackles", + "type": "placed", + "shape": "circle", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Deeproot_Defender_9x2xY9zwc3xzbXo5.json b/src/packs/adversaries/adversary_Deeproot_Defender_9x2xY9zwc3xzbXo5.json index aed2e08a..9ff0a161 100644 --- a/src/packs/adversaries/adversary_Deeproot_Defender_9x2xY9zwc3xzbXo5.json +++ b/src/packs/adversaries/adversary_Deeproot_Defender_9x2xY9zwc3xzbXo5.json @@ -137,12 +137,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -193,7 +190,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -219,7 +216,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -228,7 +226,7 @@ "_id": "0DSCzAFXy0hV4afJ", "img": "icons/magic/earth/barrier-stone-brown-green.webp", "system": { - "description": "

Slam the ground, knocking all targets within Very Close range back to Far range. Each target knocked back this way must mark a Stress.

@Template[type:emanation|range:vc]

", + "description": "

Slam the ground, knocking all targets within Very Close range back to Far range. Each target knocked back this way must mark a Stress.

", "resource": null, "actions": { "55hCZsJQhJNcZ0lX": { @@ -272,7 +270,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -281,7 +280,16 @@ "effects": [], "name": "Stress Damage", "img": "icons/magic/earth/barrier-stone-brown-green.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Ground Slam", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json b/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json index e2f58709..6468c1aa 100644 --- a/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json +++ b/src/packs/adversaries/adversary_Demon_of_Despair_kE4dfhqmIQpNd44e.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,7 +217,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -296,7 +294,7 @@ "name": "Your Struggle is Pointless", "type": "feature", "system": { - "description": "

Spend a Fear to weigh down the spirits of all PCs within Far range. All targets affected replace their Hope Die with a d8 until they roll a success with Hope or their next rest.

@Template[type:emanation|range:f]

", + "description": "

Spend a Fear to weigh down the spirits of all PCs within Far range. All targets affected replace their Hope Die with a d8 until they roll a success with Hope or their next rest.

", "resource": null, "actions": { "n0RYO05pROFU6ov3": { @@ -331,7 +329,16 @@ }, "name": "Spend Fear", "img": "icons/magic/death/skull-flames-white-blue.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Your Struggle is Pointless", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, @@ -411,7 +418,7 @@ "name": "Your Friends Will Fail You", "type": "feature", "system": { - "description": "

When a PC fails with Fear, you can mark a Stress to cause all other PCs within Close range to lose a Hope.

@Template[type:emanation|range:c]

", + "description": "

When a PC fails with Fear, you can mark a Stress to cause all other PCs within Close range to lose a Hope.

", "resource": null, "actions": { "urrp8SCFgqbmSTvm": { @@ -462,7 +469,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -471,7 +479,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/creatures/unholy/demon-fire-horned-mask.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Your Friends Will Fail You", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Demon_of_Hubris_2VN3BftageoTTIzu.json b/src/packs/adversaries/adversary_Demon_of_Hubris_2VN3BftageoTTIzu.json index 9f954437..3a95c233 100644 --- a/src/packs/adversaries/adversary_Demon_of_Hubris_2VN3BftageoTTIzu.json +++ b/src/packs/adversaries/adversary_Demon_of_Hubris_2VN3BftageoTTIzu.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,14 +217,15 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { "name": "Terrifying", "type": "feature", "system": { - "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range must lose a Hope and you gain a Fear.

@Template[type:emanation|range:f]

", + "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range must lose a Hope and you gain a Fear.

", "resource": null, "actions": { "v3XbljQeHEyfuSXz": { @@ -278,7 +276,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -287,7 +286,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/magic/death/skull-energy-light-purple.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Terrifying", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, @@ -533,7 +541,7 @@ "name": "You Pale in Comparison", "type": "feature", "system": { - "description": "

When a PC fails a roll within Close range of the @Lookup[@name], they must mark a Stress.

@Template[type:emanation|range:c]

", + "description": "

When a PC fails a roll within Close range of the @Lookup[@name], they must mark a Stress.

", "resource": null, "actions": { "kuCPWb9cu3pZdAhh": { @@ -577,7 +585,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -586,7 +595,16 @@ "effects": [], "name": "Mark Stress", "img": "icons/magic/control/fear-fright-shadow-monster-red.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "You Pale in Comparison", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Demon_of_Jealousy_SxSOkM4bcVOFyjbo.json b/src/packs/adversaries/adversary_Demon_of_Jealousy_SxSOkM4bcVOFyjbo.json index c083b183..0c743ac2 100644 --- a/src/packs/adversaries/adversary_Demon_of_Jealousy_SxSOkM4bcVOFyjbo.json +++ b/src/packs/adversaries/adversary_Demon_of_Jealousy_SxSOkM4bcVOFyjbo.json @@ -139,12 +139,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -195,7 +192,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -221,7 +218,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -279,7 +277,7 @@ "name": "Rivalry", "type": "feature", "system": { - "description": "

When a creature within Close range takes damage from a different adversary, you can mark a Stress to add a d4 to the damage roll.

@Template[type:emanation|range:c]

", + "description": "

When a creature within Close range takes damage from a different adversary, you can mark a Stress to add a d4 to the damage roll.

", "resource": null, "actions": { "UU3H5aPQejOSoFZw": { @@ -309,7 +307,16 @@ }, "name": "Mark Stress", "img": "icons/magic/perception/eye-ringed-glow-angry-small-teal.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Rivalry", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -335,7 +342,7 @@ "name": "What's Yours Is Mine", "type": "feature", "system": { - "description": "

When a PC takes Severe damage within Very Close range of the @Lookup[@name], you can spend a Fear to cause the target to make a Finesse Reaction Roll. On a failure, the @Lookup[@name] seizes one item or consumable of their choice from the target’s inventory.

@Template[type:emanation|range:vc]

", + "description": "

When a PC takes Severe damage within Very Close range of the @Lookup[@name], you can spend a Fear to cause the target to make a Finesse Reaction Roll. On a failure, the @Lookup[@name] seizes one item or consumable of their choice from the target’s inventory.

", "resource": null, "actions": { "3cGZ2CofM9HUlELH": { @@ -353,7 +360,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -382,7 +390,16 @@ }, "name": "Roll Save", "img": "icons/magic/perception/hand-eye-black.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "What's Yours Is Mine", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json b/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json index 201b17fd..0bc6bf2d 100644 --- a/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json +++ b/src/packs/adversaries/adversary_Demon_of_Wrath_5lphJAgzoqZI3VoG.json @@ -139,12 +139,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -195,7 +192,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -221,7 +218,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -253,7 +251,7 @@ "name": "Battle Lust", "type": "feature", "system": { - "description": "

Spend a Fear to boil the blood of all PCs within Far range. They use a d20 as their Fear Die until the end of the scene.

@Template[type:emanation|range:f]

", + "description": "

Spend a Fear to boil the blood of all PCs within Far range. They use a d20 as their Fear Die until the end of the scene.

", "resource": null, "actions": { "jKvzbQT0vp66DDOH": { @@ -294,7 +292,16 @@ "amount": null }, "name": "Spend Fear", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Battle Lust", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, @@ -374,7 +381,7 @@ "name": "Retalliation", "type": "feature", "system": { - "description": "

When the @Lookup[@name] takes damage from an attack within Close range, you can mark a Stress to make a standard attack against the attacker.

@Template[type:emanation|range:c]

", + "description": "

When the @Lookup[@name] takes damage from an attack within Close range, you can mark a Stress to make a standard attack against the attacker.

", "resource": null, "actions": { "hxrdtBm4dYN7KGZm": { @@ -427,7 +434,8 @@ } }, "includeBase": false, - "direct": true + "direct": true, + "groupAttack": "" }, "target": { "type": "any", @@ -456,7 +464,16 @@ }, "name": "Attack", "img": "icons/skills/melee/blood-slash-foam-red.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Retalliation", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Demonic_Hound_Pack_NoRZ1PqB8N5wcIw0.json b/src/packs/adversaries/adversary_Demonic_Hound_Pack_NoRZ1PqB8N5wcIw0.json index 2043d960..b534562b 100644 --- a/src/packs/adversaries/adversary_Demonic_Hound_Pack_NoRZ1PqB8N5wcIw0.json +++ b/src/packs/adversaries/adversary_Demonic_Hound_Pack_NoRZ1PqB8N5wcIw0.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,7 +217,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -252,7 +250,7 @@ "name": "Dreadhowl", "type": "feature", "system": { - "description": "

Mark a Stress to make all targets within Very Close range lose a Hope. If a target is not able to lose a Hope, they must instead mark 2 Stress.

@Template[type:emanation|range:vc]

", + "description": "

Mark a Stress to make all targets within Very Close range lose a Hope. If a target is not able to lose a Hope, they must instead mark 2 Stress.

", "resource": null, "actions": { "XyLlX9RWSxciZ7oV": { @@ -296,7 +294,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -305,7 +304,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/creatures/unholy/demons-horned-glowing-pink.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Dreadhowl", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Dire_Bat_tBWHW00epmMnkawe.json b/src/packs/adversaries/adversary_Dire_Bat_tBWHW00epmMnkawe.json index 23d5550e..c2064395 100644 --- a/src/packs/adversaries/adversary_Dire_Bat_tBWHW00epmMnkawe.json +++ b/src/packs/adversaries/adversary_Dire_Bat_tBWHW00epmMnkawe.json @@ -137,12 +137,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -193,7 +190,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -219,7 +216,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -295,7 +293,7 @@ "name": "Screech", "type": "feature", "system": { - "description": "

Mark a Stress to send a high-pitch screech out toward all targets in front of the @Lookup[@name] within Far range. Those targets must mark 1d4 Stress.

@Template[type:inFront|range:f]

", + "description": "

Mark a Stress to send a high-pitch screech out toward all targets in front of the @Lookup[@name] within Far range. Those targets must mark 1d4 Stress.

", "resource": null, "actions": { "2ILfoiBoMyBCtBsL": { @@ -338,7 +336,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -347,7 +346,16 @@ "effects": [], "name": "Mark Stress", "img": "icons/magic/sonic/projectile-sound-rings-wave.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Screech", + "type": "placed", + "shape": "inFront", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Dryad_wR7cFKrHvRzbzhBT.json b/src/packs/adversaries/adversary_Dryad_wR7cFKrHvRzbzhBT.json index c69ee84e..62df584a 100644 --- a/src/packs/adversaries/adversary_Dryad_wR7cFKrHvRzbzhBT.json +++ b/src/packs/adversaries/adversary_Dryad_wR7cFKrHvRzbzhBT.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,14 +217,15 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { "name": "Bramble Patch", "type": "feature", "system": { - "description": "

Mark a Stress to target a point within Far range. Create a patch of thorns that covers an area within Close range of that point. All targets within that area take 2d6+2 physical damage when they act. A target must succeed on a Finesse Roll or deal more than 20 damage to the @Lookup[@name] with an attack to leave the area.

@Template[type:circle|range:c]

", + "description": "

Mark a Stress to target a point within Far range. Create a patch of thorns that covers an area within Close range of that point. All targets within that area take 2d6+2 physical damage when they act. A target must succeed on a Finesse Roll or deal more than 20 damage to the @Lookup[@name] with an attack to leave the area.

", "resource": null, "actions": { "iCJdIs57hfh5Cb0u": { @@ -252,7 +250,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -281,7 +280,16 @@ }, "name": "Mark Stress", "img": "icons/magic/nature/root-vines-grow-brown.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Bramble Patch", + "type": "placed", + "shape": "circle", + "size": "close", + "effects": [] + } + ] }, "cpZ5c9d3opSA4BN9": { "type": "damage", @@ -414,7 +422,7 @@ "name": "We Are All One", "type": "feature", "system": { - "description": "

When an ally dies within Close range, you can spend a Fear to clear 2 HP and 2 Stress as the fallen ally’s life force is returned to the forest.

@Template[type:emanation|range:c]

", + "description": "

When an ally dies within Close range, you can spend a Fear to clear 2 HP and 2 Stress as the fallen ally’s life force is returned to the forest.

", "resource": null, "actions": { "SrhuW3mfOuqg1ys6": { @@ -490,7 +498,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "self", @@ -514,7 +523,16 @@ }, "name": "Spend Fear", "img": "icons/magic/unholy/orb-hands-pink.webp", - "range": "self" + "range": "self", + "areas": [ + { + "name": "We Are All One", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json b/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json index 06db1453..975cf6aa 100644 --- a/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json +++ b/src/packs/adversaries/adversary_Fallen_Sorcerer_PELRry1vqjBzSAlr.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,14 +217,15 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { "name": "Conflagration", "type": "feature", "system": { - "description": "

Spend a Fear to unleash an all-consuming firestorm and make an attack against all targets within Close range. Targets the @Lookup[@name] succeeds against take 2d10+6 direct magic damage.

@Template[type:emanation|range:c]

", + "description": "

Spend a Fear to unleash an all-consuming firestorm and make an attack against all targets within Close range. Targets the @Lookup[@name] succeeds against take 2d10+6 direct magic damage.

", "resource": null, "actions": { "v7zZo52Dnj1e1i2G": { @@ -279,7 +277,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -308,7 +307,16 @@ }, "name": "Attack", "img": "icons/magic/fire/projectile-beams-salvo-red.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Conflagration", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -465,14 +473,14 @@ "name": "Shackles of Guilt", "type": "feature", "system": { - "description": "

Countdown (Loop 2d6). When the @Lookup[@name] is in the spotlight for the first time, activate the countdown. When it triggers, all targets within Far range become Vulnerable and must mark a Stress as they relive their greatest regrets. A target can break free from their regret with a successful Presence or Strength Roll. When a PC fails to break free, they lose a Hope.

@Template[type:emanation|range:f]

", + "description": "

Countdown (Loop 2d6). When the @Lookup[@name] is in the spotlight for the first time, activate the countdown. When it triggers, all targets within Far range become Vulnerable and must mark a Stress as they relive their greatest regrets. A target can break free from their regret with a successful Presence or Strength Roll. When a PC fails to break free, they lose a Hope.

", "resource": null, "actions": { "7b0FkpAnWz9a5EWx": { "type": "damage", "_id": "7b0FkpAnWz9a5EWx", "systemPath": "actions", - "description": "

When the countdown triggers, all targets within Far range become Vulnerable and must mark a Stress as they relive their greatest regrets. A target can break free from their regret with a successful Presence or Strength Roll. When a PC fails to break free, they lose a Hope.

@Template[type:emanation|range:f]

", + "description": "

When it triggers, all targets within Far range become Vulnerable and must mark a Stress as they relive their greatest regrets. A target can break free from their regret with a successful Presence or Strength Roll. When a PC fails to break free, they lose a Hope.

", "chatDisplay": true, "actionType": "action", "cost": [], @@ -509,7 +517,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -523,7 +532,16 @@ ], "name": "Mark Stress", "img": "icons/magic/unholy/strike-hand-glow-pink.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Shackles of Guilt", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] }, "11PtfoxbgOXxNlkG": { "type": "countdown", diff --git a/src/packs/adversaries/adversary_Fallen_Warlord__Realm_Breaker_hxZ0sgoFJubh5aj6.json b/src/packs/adversaries/adversary_Fallen_Warlord__Realm_Breaker_hxZ0sgoFJubh5aj6.json index 9fa49107..15663752 100644 --- a/src/packs/adversaries/adversary_Fallen_Warlord__Realm_Breaker_hxZ0sgoFJubh5aj6.json +++ b/src/packs/adversaries/adversary_Fallen_Warlord__Realm_Breaker_hxZ0sgoFJubh5aj6.json @@ -173,12 +173,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -229,7 +226,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -255,7 +252,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -392,7 +390,7 @@ "name": "Tormenting Lash", "type": "feature", "system": { - "description": "

Mark a Stress to make a standard attack against all targets within Very Close range. When a target uses armor to reduce damage from this attack, they must mark 2 Armor Slots.

@Template[type:emanation|range:vc]

", + "description": "

Mark a Stress to make a standard attack against all targets within Very Close range. When a target uses armor to reduce damage from this attack, they must mark 2 Armor Slots.

", "resource": null, "actions": { "zMVhUekP8pcyQGFR": { @@ -444,7 +442,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -473,7 +472,16 @@ }, "name": "Attack", "img": "icons/skills/melee/blood-slash-foam-red.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Tormenting Lash", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, @@ -499,14 +507,14 @@ "name": "All-Consuming Rage", "type": "feature", "system": { - "description": "

Countdown (Decreasing 8). When the @Lookup[@name] is in the spotlight for the first time, activate the countdown. When it triggers, create a torrent of incarnate rage that rends flesh from bone. All targets within Far range must make a Presence Reaction Roll. Targets who fail take 2d6+10 direct magic damage. Targets who succeed take half damage. For each HP marked from this damage, summon a @UUID[Compendium.daggerheart.adversaries.Actor.OsLG2BjaEdTZUJU9]{Fallen Shock Troop} within Very Close range of the target who marked that HP. If the countdown ever decreases its maximum value to 0, the @Lookup[@name] marks their remaining HP and all targets within Far range must mark all remaining HP and make a death move.

@Template[type:emanation|range:f]

", + "description": "

Countdown (Decreasing 8). When the @Lookup[@name] is in the spotlight for the first time, activate the countdown. When it triggers, create a torrent of incarnate rage that rends flesh from bone. All targets within Far range must make a Presence Reaction Roll. Targets who fail take 2d6+10 direct magic damage. Targets who succeed take half damage. For each HP marked from this damage, summon a @UUID[Compendium.daggerheart.adversaries.Actor.OsLG2BjaEdTZUJU9]{Fallen Shock Troop} within Very Close range of the target who marked that HP. If the countdown ever decreases its maximum value to 0, the @Lookup[@name] marks their remaining HP and all targets within Far range must mark all remaining HP and make a death move.

", "resource": null, "actions": { "rgy5wXyXJWh6uWxC": { "type": "attack", "_id": "rgy5wXyXJWh6uWxC", "systemPath": "actions", - "description": "

When it triggers, create a torrent of incarnate rage that rends flesh from bone. All targets within Far range must make a Presence Reaction Roll. Targets who fail take 2d6+10 direct magic damage. Targets who succeed take half damage. For each HP marked from this damage, summon a @UUID[Compendium.daggerheart.adversaries.Actor.OsLG2BjaEdTZUJU9]{Fallen Shock Troop} within Very Close range of the target who marked that HP. If the countdown ever decreases its maximum value to 0, the @Lookup[@name] marks their remaining HP and all targets within Far range must mark all remaining HP and make a death move.

@Template[type:emanation|range:f]

", + "description": "

When it triggers, create a torrent of incarnate rage that rends flesh from bone. All targets within Far range must make a Presence Reaction Roll. Targets who fail take 2d6+10 direct magic damage. Targets who succeed take half damage. For each HP marked from this damage, summon a @UUID[Compendium.daggerheart.adversaries.Actor.OsLG2BjaEdTZUJU9]{Fallen Shock Troop} within Very Close range of the target who marked that HP. If the countdown ever decreases its maximum value to 0, the @Lookup[@name] marks their remaining HP and all targets within Far range must mark all remaining HP and make a death move.

", "chatDisplay": true, "actionType": "action", "cost": [], @@ -544,7 +552,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -573,7 +582,16 @@ }, "name": "Roll Save", "img": "icons/magic/control/fear-fright-monster-grin-red-orange.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "All-Consuming Rage", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] }, "8e3BHmOFLvRwPbTW": { "type": "countdown", @@ -636,7 +654,7 @@ "name": "Doombringer", "type": "feature", "system": { - "description": "

When a target marks HP from an attack by the @Lookup[@name], all PCs within Far range of the target must lose a Hope.

@Template[type:emanation|range:f]

", + "description": "

When a target marks HP from an attack by the @Lookup[@name], all PCs within Far range of the target must lose a Hope.

", "resource": null, "actions": { "WEBPJCbXfBeyHFJ4": { @@ -680,7 +698,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -689,7 +708,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/magic/death/skull-energy-light-purple.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Doombringer", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, 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 5ad77ab0..6cb1c0ce 100644 --- a/src/packs/adversaries/adversary_Fallen_Warlord__Undefeated_Champion_RXkZTwBRi4dJ3JE5.json +++ b/src/packs/adversaries/adversary_Fallen_Warlord__Undefeated_Champion_RXkZTwBRi4dJ3JE5.json @@ -174,12 +174,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -230,7 +227,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -256,7 +253,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -393,7 +391,7 @@ "name": "Shattering Strike", "type": "feature", "system": { - "description": "

Mark a Stress to make a standard attack against all targets within Very Close range. PCs the @Lookup[@name] succeeds against lose a number of Hope equal to the HP they marked from this attack.

@Template[type:emanation|range:vc]

", + "description": "

Mark a Stress to make a standard attack against all targets within Very Close range. PCs the @Lookup[@name] succeeds against lose a number of Hope equal to the HP they marked from this attack.

", "resource": null, "actions": { "t1GhGnEhNYyJ7p2U": { @@ -438,7 +436,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -467,7 +466,16 @@ }, "name": "Attack", "img": "icons/skills/melee/sword-stuck-glowing-pink.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Shattering Strike", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, @@ -496,34 +504,42 @@ "description": "

Spend a Fear to summon a number of @UUID[Compendium.daggerheart.adversaries.Actor.OsLG2BjaEdTZUJU9]{Fallen Shock Troops} equal to twice the number of PCs. The Shock Troops appear at Far range.

", "resource": null, "actions": { - "hGMzqw00JTlYfHYy": { - "type": "effect", - "_id": "hGMzqw00JTlYfHYy", + "SrU7qbh8LcOgfozT": { + "type": "summon", + "_id": "SrU7qbh8LcOgfozT", "systemPath": "actions", + "baseAction": false, "description": "", "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, "actionType": "action", + "triggers": [], "cost": [ { "scalable": false, "key": "fear", "value": 1, - "step": null + "itemId": null, + "step": null, + "consumeOnSuccess": false } ], "uses": { "value": null, "max": "", - "recovery": null - }, - "effects": [], - "target": { - "type": "self", - "amount": null + "recovery": null, + "consumeOnSuccess": false }, + "summon": [ + { + "actorUUID": "Compendium.daggerheart.adversaries.Actor.OsLG2BjaEdTZUJU9", + "count": "@partySize*2" + } + ], "name": "Spend Fear", - "img": "icons/magic/death/undead-skeleton-worn-blue.webp", - "range": "" + "range": "far" } }, "originItemType": null, @@ -565,19 +581,25 @@ "max": "", "recovery": null }, - "effects": [ - { - "_id": "eZp1PSCHZzdb47oM", - "onSave": false - } - ], + "effects": [], "target": { "type": "any", "amount": null }, "name": "Circle", "img": "icons/magic/unholy/barrier-fire-pink.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Circle of Defilement", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [ + "KlTKlZXjdXQ9v6qB" + ] + } + ] }, "4x13WyksHU0u0j20": { "type": "countdown", @@ -625,42 +647,58 @@ "img": "icons/magic/unholy/barrier-fire-pink.webp", "effects": [ { - "name": "Circle of Defilement", + "name": "Circle Of Defilement", + "disabled": false, "img": "icons/magic/unholy/barrier-fire-pink.webp", - "origin": "Compendium.daggerheart.adversaries.Actor.RXkZTwBRi4dJ3JE5.Item.55P7ZijSbQeVHCw4", + "description": "

You are Vulnerable until you leave the circle.

", "transfer": false, - "_id": "eZp1PSCHZzdb47oM", - "type": "base", + "statuses": [ + "vulnerable" + ], "system": { "rangeDependence": { "enabled": false, "type": "withinRange", "target": "hostile", "range": "melee" - } + }, + "changes": [], + "duration": { + "description": "", + "type": "" + }, + "stacking": null, + "targetDispositions": [ + 1, + 0 + ] }, - "changes": [], - "disabled": false, - "duration": { - "startTime": null, + "_id": "KlTKlZXjdXQ9v6qB", + "type": "base", + "start": { + "time": 0, "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null + "combatant": null, + "initiative": null, + "round": null, + "turn": null }, - "description": "

Vulnerable until you leave the circle. The circle can be removed by dealing Severe damage to the Undefeated Champion.

", + "duration": { + "value": null, + "units": "seconds", + "expiry": null, + "expired": false + }, + "origin": null, "tint": "#ffffff", - "statuses": [ - "vulnerable" - ], + "showIcon": 1, + "folder": null, "sort": 0, "flags": {}, "_stats": { "compendiumSource": null }, - "_key": "!actors.items.effects!RXkZTwBRi4dJ3JE5.55P7ZijSbQeVHCw4.eZp1PSCHZzdb47oM" + "_key": "!actors.items.effects!RXkZTwBRi4dJ3JE5.55P7ZijSbQeVHCw4.KlTKlZXjdXQ9v6qB" } ], "folder": null, @@ -775,7 +813,7 @@ "name": "Doombringer", "type": "feature", "system": { - "description": "

When a target marks HP from an attack by the @Lookup[@name], all PCs within Far range of the target lose a Hope.

@Template[type:emanation|range:f]

", + "description": "

When a target marks HP from an attack by the @Lookup[@name], all PCs within Far range of the target lose a Hope.

", "resource": null, "actions": { "liwKSCTmQqZasAf6": { @@ -819,7 +857,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -828,7 +867,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/magic/death/skull-energy-light-purple.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Doombringer", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Giant_Brawler_YnObCleGjPT7yqEc.json b/src/packs/adversaries/adversary_Giant_Brawler_YnObCleGjPT7yqEc.json index 8948c8b6..acb9c219 100644 --- a/src/packs/adversaries/adversary_Giant_Brawler_YnObCleGjPT7yqEc.json +++ b/src/packs/adversaries/adversary_Giant_Brawler_YnObCleGjPT7yqEc.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,14 +217,15 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { "name": "Battering Ram", "type": "feature", "system": { - "description": "

Mark a Stress to have the @Lookup[@name] charge at an inanimate object within Close range they could feasibly smash (such as a wall, cart, or market stand) and destroy it. All targets within Very Close range of the object must succeed on an Agility Reaction Roll or take 2d4+3 physical damage from the shrapnel.

@Template[type:circle|range:vc]

", + "description": "

Mark a Stress to have the @Lookup[@name] charge at an inanimate object within Close range they could feasibly smash (such as a wall, cart, or market stand) and destroy it. All targets within Very Close range of the object must succeed on an Agility Reaction Roll or take 2d4+3 physical damage from the shrapnel.

", "resource": null, "actions": { "zns57MqnZ6M1d4r0": { @@ -308,7 +306,16 @@ }, "name": "Roll Save", "img": "icons/skills/melee/shield-damaged-broken-orange.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Battering Ram", + "type": "placed", + "shape": "circle", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Glass_Snake_8KWVLWXFhlY2kYx0.json b/src/packs/adversaries/adversary_Glass_Snake_8KWVLWXFhlY2kYx0.json index 5876f55c..f290875d 100644 --- a/src/packs/adversaries/adversary_Glass_Snake_8KWVLWXFhlY2kYx0.json +++ b/src/packs/adversaries/adversary_Glass_Snake_8KWVLWXFhlY2kYx0.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -352,7 +350,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -381,7 +380,16 @@ }, "name": "Attack", "img": "icons/skills/melee/blood-slash-foam-red.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Spinning Serpent", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, @@ -408,7 +416,7 @@ "_id": "LR5XHauNtWcl18CY", "img": "icons/magic/acid/projectile-needles-salvo-green.webp", "system": { - "description": "

Spend a Fear to introduce a d6 Spitter Die. When the @Lookup[@name] is in the spotlight, roll this die. On a result of 5 or higher, all targets in front of the @Lookup[@name] within Far range must succeed on an Agility Reaction Roll or take 1d4 physical damage. The @Lookup[@name] can take the spotlight a second time this GM turn.

@Template[type:inFront|range:f]

", + "description": "

Spend a Fear to introduce a d6 Spitter Die. When the @Lookup[@name] is in the spotlight, roll this die. On a result of 5 or higher, all targets in front of the @Lookup[@name] within Far range must succeed on an Agility Reaction Roll or take 1d4 physical damage. The @Lookup[@name] can take the spotlight a second time this GM turn.

", "resource": null, "actions": { "yx5fjMLLwSnvSbqs": { @@ -449,7 +457,7 @@ "type": "attack", "_id": "Ds6KlQKZCOhh5OMT", "systemPath": "actions", - "description": "

All targets in front of the @Lookup[@name] within Far range must succeed on an Agility Reaction Roll or take 1d4 physical damage.

@Template[type:inFront|range:f]

", + "description": "

All targets in front of the @Lookup[@name] within Far range must succeed on an Agility Reaction Roll or take 1d4 physical damage.

", "chatDisplay": true, "actionType": "action", "cost": [], @@ -487,7 +495,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -516,7 +525,16 @@ }, "name": "Spit Attack", "img": "icons/magic/acid/projectile-needles-salvo-green.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Spitter", + "type": "placed", + "shape": "inFront", + "size": "far", + "effects": [] + } + ] }, "xccwknU2xHUwQSdn": { "type": "attack", @@ -584,18 +602,15 @@ "type": "withinRange", "target": "hostile", "range": "melee" - } + }, + "changes": [] }, - "changes": [], "disabled": false, "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null + "value": null, + "units": "seconds", + "expiry": null, + "expired": false }, "description": "

You have a d6 Spitter Die. When the Snake is in the spotlight, roll this die. On a result of 5 or higher, all targets in front of the Snake within Far range must succeed on an Agility Reaction Roll or take 1d4 physical damage. The Snake can take the spotlight a second time this GM turn.

", "tint": "#ffffff", @@ -605,6 +620,9 @@ "_stats": { "compendiumSource": null }, + "start": null, + "showIcon": 1, + "folder": null, "_key": "!actors.items.effects!8KWVLWXFhlY2kYx0.LR5XHauNtWcl18CY.Mchd23xNQ4nSWw9X" } ], diff --git a/src/packs/adversaries/adversary_Greater_Earth_Elemental_dsfB3YhoL5SudvS2.json b/src/packs/adversaries/adversary_Greater_Earth_Elemental_dsfB3YhoL5SudvS2.json index 077373b2..e59d2683 100644 --- a/src/packs/adversaries/adversary_Greater_Earth_Elemental_dsfB3YhoL5SudvS2.json +++ b/src/packs/adversaries/adversary_Greater_Earth_Elemental_dsfB3YhoL5SudvS2.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -398,7 +396,7 @@ "name": "Rockslide", "type": "feature", "system": { - "description": "

Mark a Stress to create a rockslide that buries the land in front of @Lookup[@name] within Close range with rockfall. All targets in this area must make an Agility Reaction Roll (19). Targets who fail take 2d12+5 physical damage and become Vulnerable until their next roll with Hope. Targets who succeed take half damage.

@Template[type:inFront|range:c]

", + "description": "

Mark a Stress to create a rockslide that buries the land in front of @Lookup[@name] within Close range with rockfall. All targets in this area must make an Agility Reaction Roll (19). Targets who fail take 2d12+5 physical damage and become Vulnerable until their next roll with Hope. Targets who succeed take half damage.

", "resource": null, "actions": { "eLGIC3kVjLo8FEvy": { @@ -450,7 +448,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -484,7 +483,16 @@ }, "name": "Roll Save", "img": "icons/magic/earth/barrier-stone-brown-green.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Rockslide", + "type": "placed", + "shape": "inFront", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Greater_Water_Elemental_xIICT6tEdnA7dKDV.json b/src/packs/adversaries/adversary_Greater_Water_Elemental_xIICT6tEdnA7dKDV.json index b44bb9cc..db73a536 100644 --- a/src/packs/adversaries/adversary_Greater_Water_Elemental_xIICT6tEdnA7dKDV.json +++ b/src/packs/adversaries/adversary_Greater_Water_Elemental_xIICT6tEdnA7dKDV.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -377,7 +375,7 @@ "name": "Drowning Embrace", "type": "feature", "system": { - "description": "

Spend a Fear to make an attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against become Restrained and Vulnerable as they begin drowning. A target can break free, ending both conditions, with a successful Strength or Instinct Roll.

@Template[type:emanation|range:vc]

", + "description": "

Spend a Fear to make an attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against become Restrained and Vulnerable as they begin drowning. A target can break free, ending both conditions, with a successful Strength or Instinct Roll.

", "resource": null, "actions": { "ooYbiLrYjoWXIfe9": { @@ -402,7 +400,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -436,7 +435,16 @@ }, "name": "Attack", "img": "icons/magic/water/vortex-water-whirlpool-blue.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Drowning Embrace", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Head_Guard_mK3A5FTx6k8iPU3F.json b/src/packs/adversaries/adversary_Head_Guard_mK3A5FTx6k8iPU3F.json index f0c050a9..9a6cc509 100644 --- a/src/packs/adversaries/adversary_Head_Guard_mK3A5FTx6k8iPU3F.json +++ b/src/packs/adversaries/adversary_Head_Guard_mK3A5FTx6k8iPU3F.json @@ -143,12 +143,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -199,7 +196,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -225,7 +222,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -234,7 +232,7 @@ "_id": "SsgN2qSYpQLR43Cz", "img": "icons/skills/movement/arrows-up-trio-red.webp", "system": { - "description": "

Spend 2 Fear to spotlight the @Lookup[@name] and up to 2d4 allies within Far range.

@Template[type:emanation|range:f]

", + "description": "

Spend 2 Fear to spotlight the @Lookup[@name] and up to 2d4 allies within Far range.

", "resource": null, "actions": { "lI0lnRb3xrUjqIYX": { @@ -259,7 +257,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -288,7 +287,16 @@ }, "name": "Rally", "img": "icons/skills/movement/arrows-up-trio-red.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Rally Guards", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, @@ -315,7 +323,7 @@ "_id": "YeJ7eJVCKsRxG8mk", "img": "icons/skills/ranged/target-bullseye-arrow-blue.webp", "system": { - "description": "

Countdown (5). When the @Lookup[@name] is in the spotlight for the first time, activate the countdown. It ticks down when a PC makes an attack roll. When it triggers, all Archer Guards within Far range make a standard attack with advantage against the nearest target within their range. If any attacks succeed on the same target, combine their damage.

@Template[type:emanation|range:f]

", + "description": "

Countdown (5). When the @Lookup[@name] is in the spotlight for the first time, activate the countdown. It ticks down when a PC makes an attack roll. When it triggers, all Archer Guards within Far range make a standard attack with advantage against the nearest target within their range. If any attacks succeed on the same target, combine their damage.

", "resource": null, "actions": { "xyhaCmPGiVMsTViH": { @@ -353,7 +361,16 @@ ], "name": "Start Countdown", "img": "icons/skills/ranged/target-bullseye-arrow-blue.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "On My Signal", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Head_Vampire_i2UNbRvgyoSs07M6.json b/src/packs/adversaries/adversary_Head_Vampire_i2UNbRvgyoSs07M6.json index 322e4658..b17c85bc 100644 --- a/src/packs/adversaries/adversary_Head_Vampire_i2UNbRvgyoSs07M6.json +++ b/src/packs/adversaries/adversary_Head_Vampire_i2UNbRvgyoSs07M6.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,14 +217,15 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { "name": "Terrifying", "type": "feature", "system": { - "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range lose a Hope and you gain a Fear.

@Template[type:emanation|range:f]

", + "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range lose a Hope and you gain a Fear.

", "resource": null, "actions": { "Rf2ZL3EjCzudonRb": { @@ -271,7 +269,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -280,7 +279,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/magic/death/skull-energy-light-purple.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Terrifying", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, @@ -525,7 +533,7 @@ "name": "Lifesuck", "type": "feature", "system": { - "description": "

When the @Lookup[@name] is spotlighted, roll a d8. On a result of 6 or higher, all targets within Very Close range must mark a HP.

@Template[type:emanation|range:vc]

", + "description": "

When the @Lookup[@name] is spotlighted, roll a d8. On a result of 6 or higher, all targets within Very Close range must mark a HP.

", "resource": null, "actions": { "DA8qT2omBcG4oryX": { @@ -569,7 +577,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -598,7 +607,16 @@ }, "name": "Roll d8", "img": "icons/magic/unholy/strike-beam-blood-small-red-purple.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Lifesuck", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Hydra_MI126iMOOobQ1Obn.json b/src/packs/adversaries/adversary_Hydra_MI126iMOOobQ1Obn.json index 7e71af98..9c53487a 100644 --- a/src/packs/adversaries/adversary_Hydra_MI126iMOOobQ1Obn.json +++ b/src/packs/adversaries/adversary_Hydra_MI126iMOOobQ1Obn.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -377,7 +375,7 @@ "name": "Terrifying Chorus", "type": "feature", "system": { - "description": "

All PCs within Far range lose 2 Hope.

@Template[type:emanation|range:f]

", + "description": "

All PCs within Far range lose 2 Hope.

", "resource": null, "actions": { "nJxpFR4Ul0e2RrL4": { @@ -421,7 +419,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -430,7 +429,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/magic/death/skull-energy-light-white.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Terrifying Chorus", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Jagged_Knife_Lieutenant_aTljstqteGoLpCBq.json b/src/packs/adversaries/adversary_Jagged_Knife_Lieutenant_aTljstqteGoLpCBq.json index 8820f30c..771c6692 100644 --- a/src/packs/adversaries/adversary_Jagged_Knife_Lieutenant_aTljstqteGoLpCBq.json +++ b/src/packs/adversaries/adversary_Jagged_Knife_Lieutenant_aTljstqteGoLpCBq.json @@ -137,12 +137,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -193,7 +190,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -219,7 +216,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -258,7 +256,16 @@ }, "name": "Mark Stress", "img": "icons/skills/movement/arrows-up-trio-red.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Tactician", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json b/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json index 562b42b8..24683a37 100644 --- a/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json +++ b/src/packs/adversaries/adversary_Juvenile_Flickerfly_MYXmTx2FHcIjdfYZ.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -400,7 +398,7 @@ "name": "Mind Dance", "type": "feature", "system": { - "description": "

Mark a Stress to create a magically dazzling display that grapples the minds of nearby foes. All targets within Close range must make an Instinct Reaction Roll. For each target who failed, you gain a Fear and the @Lookup[@name] learns one of the target’s fears.

@Template[type:emanation|range:c]

", + "description": "

Mark a Stress to create a magically dazzling display that grapples the minds of nearby foes. All targets within Close range must make an Instinct Reaction Roll. For each target who failed, you gain a Fear and the @Lookup[@name] learns one of the target’s fears.

", "resource": null, "actions": { "0wL3ieMrXEb2gcxe": { @@ -418,7 +416,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -447,7 +446,16 @@ }, "name": "Roll Save", "img": "icons/magic/light/explosion-glow-spiral-yellow.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Mind Dance", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -473,7 +481,7 @@ "name": "Hallucinatory Breath", "type": "feature", "system": { - "description": "

Countdown (Loop 1d6). When the @Lookup[@name] takes damage for the first time, activate the countdown. When it triggers, the @Lookup[@name] breathes hallucinatory gas on all targets in front of them up to Far range. Targets must succeed on an Instinct Reaction Roll or be tormented by fearful hallucinations. Targets whose fears are known to the @Lookup[@name] have disadvantage on this roll. Targets who fail must mark a Stress and lose a Hope.

@Template[type:inFront|range:f]

", + "description": "

Countdown (Loop 1d6). When the @Lookup[@name] takes damage for the first time, activate the countdown. When it triggers, the @Lookup[@name] breathes hallucinatory gas on all targets in front of them up to Far range. Targets must succeed on an Instinct Reaction Roll or be tormented by fearful hallucinations. Targets whose fears are known to the @Lookup[@name] have disadvantage on this roll. Targets who fail must mark a Stress and lose a Hope.

", "resource": null, "actions": { "USEkCakSzYcZbBwY": { @@ -542,7 +550,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -571,7 +580,16 @@ }, "name": "Roll Save", "img": "icons/magic/air/fog-gas-smoke-purple.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Hallucinatory Breath", + "type": "placed", + "shape": "inFront", + "size": "far", + "effects": [] + } + ] }, "n8ZuLjwTf2FJ7V6n": { "type": "countdown", diff --git a/src/packs/adversaries/adversary_Kraken_4nqv3ZwJGjnmic8j.json b/src/packs/adversaries/adversary_Kraken_4nqv3ZwJGjnmic8j.json index 4494e0e8..4bcdc15d 100644 --- a/src/packs/adversaries/adversary_Kraken_4nqv3ZwJGjnmic8j.json +++ b/src/packs/adversaries/adversary_Kraken_4nqv3ZwJGjnmic8j.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,7 +217,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -439,7 +437,7 @@ "name": "Boiling Blast", "type": "feature", "system": { - "description": "

Spend a Fear to spew a line of boiling water at any number of targets in a line up to Far range. All targets must succeed on an Agility Reaction Roll or take 4d6+9 physical damage. If a target marks an Armor Slot to reduce the damage, they must also mark a Stress.

@Template[type:ray|range:f]

", + "description": "

Spend a Fear to spew a line of boiling water at any number of targets in a line up to Far range. All targets must succeed on an Agility Reaction Roll or take 4d6+9 physical damage. If a target marks an Armor Slot to reduce the damage, they must also mark a Stress.

", "resource": null, "actions": { "pHZUiZRSj4FuG0uK": { @@ -484,7 +482,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -513,7 +512,16 @@ }, "name": "Attack", "img": "icons/magic/water/projectile-icecicle-glowing.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Boiling Blast", + "type": "placed", + "shape": "line", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Masked_Thief_niBpVU7yeo5ccskE.json b/src/packs/adversaries/adversary_Masked_Thief_niBpVU7yeo5ccskE.json index 25740e52..77d48be3 100644 --- a/src/packs/adversaries/adversary_Masked_Thief_niBpVU7yeo5ccskE.json +++ b/src/packs/adversaries/adversary_Masked_Thief_niBpVU7yeo5ccskE.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,7 +217,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -325,7 +323,7 @@ "name": "Escape Plan", "type": "feature", "system": { - "description": "

Mark a Stress to reveal a snare trap set anywhere on the battlefield by the @Lookup[@name]. All targets within Very Close range of the trap must succeed on an Agility Reaction Roll (13) or be pulled off their feet and suspended upside down. A target is Restrained and Vulnerable until they break free, ending both conditions, with a successful Finesse or Strength Roll (13).

@Template[type:rect|range:c]

", + "description": "

Mark a Stress to reveal a snare trap set anywhere on the battlefield by the @Lookup[@name]. All targets within Very Close range of the trap must succeed on an Agility Reaction Roll (13) or be pulled off their feet and suspended upside down. A target is Restrained and Vulnerable until they break free, ending both conditions, with a successful Finesse or Strength Roll (13).

", "resource": null, "actions": { "sq0q1l2Go4GduR3B": { @@ -377,7 +375,16 @@ }, "name": "Roll Save", "img": "icons/environment/traps/trap-jaw-tan.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Escape Plan", + "type": "placed", + "shape": "circle", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Minor_Chaos_Elemental_sRn4bqerfARvhgSV.json b/src/packs/adversaries/adversary_Minor_Chaos_Elemental_sRn4bqerfARvhgSV.json index 21564421..9ddfb4f3 100644 --- a/src/packs/adversaries/adversary_Minor_Chaos_Elemental_sRn4bqerfARvhgSV.json +++ b/src/packs/adversaries/adversary_Minor_Chaos_Elemental_sRn4bqerfARvhgSV.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -293,7 +291,7 @@ "_id": "oAxhAawgcK7DAdpa", "img": "icons/magic/sonic/explosion-shock-sound-wave.webp", "system": { - "description": "

Mark a HP to force all targets within Close range to mark a Stress and become Vulnerable until their next rest or they clear a HP.

@Template[type:emanation|range:c]

", + "description": "

Mark a HP to force all targets within Close range to mark a Stress and become Vulnerable until their next rest or they clear a HP.

", "resource": null, "actions": { "g4CVwjDeJgTJ2oCw": { @@ -344,7 +342,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -358,7 +357,16 @@ ], "name": "Mark HP", "img": "icons/magic/sonic/explosion-shock-sound-wave.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Sickening Flux", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -434,7 +442,7 @@ "_id": "updQuIK8sybf4YmW", "img": "icons/magic/light/explosion-glow-spiral-teal.webp", "system": { - "description": "

Spend a Fear to transform the area within Very Close range into a different biome. All targets within this area take 2d6+3 direct magic damage.

@Template[type:emanation|range:vc]

", + "description": "

Spend a Fear to transform the area within Very Close range into a different biome. All targets within this area take 2d6+3 direct magic damage.

", "resource": null, "actions": { "QzuQIAtSrgz9Zd5V": { @@ -486,7 +494,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -495,7 +504,16 @@ "effects": [], "name": "Spend Fear", "img": "icons/magic/light/explosion-glow-spiral-teal.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Remake Reality", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Minor_Demon_3tqCjDwJAQ7JKqMb.json b/src/packs/adversaries/adversary_Minor_Demon_3tqCjDwJAQ7JKqMb.json index 8f5f51f3..626b1597 100644 --- a/src/packs/adversaries/adversary_Minor_Demon_3tqCjDwJAQ7JKqMb.json +++ b/src/packs/adversaries/adversary_Minor_Demon_3tqCjDwJAQ7JKqMb.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -282,7 +280,7 @@ "_id": "kD9kO92V7t3IqZu8", "img": "icons/magic/unholy/strike-hand-glow-pink.webp", "system": { - "description": "

When a PC rolls a failure with Fear while within Close range of the @Lookup[@name], they lose a Hope.

@Template[type:emanation|range:c]

", + "description": "

When a PC rolls a failure with Fear while within Close range of the @Lookup[@name], they lose a Hope.

", "resource": null, "actions": { "XQ7QebA0iGvMti4A": { @@ -326,7 +324,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -335,7 +334,16 @@ "effects": [], "name": "Hope Damage", "img": "icons/magic/unholy/strike-hand-glow-pink.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "All Must fall", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -361,7 +369,7 @@ "_id": "lA7vcvS7oGT9NTSy", "img": "icons/magic/fire/projectile-beams-salvo-red.webp", "system": { - "description": "

Spend a Fear to rain down hellfire within Far range. All targets within the area must make an Agility Reaction Roll. Targets who fail take 1d20+3 magic damage. Targets who succeed take half damage.

@Template[type:emanation|range:f]

", + "description": "

Spend a Fear to rain down hellfire within Far range. All targets within the area must make an Agility Reaction Roll. Targets who fail take 1d20+3 magic damage. Targets who succeed take half damage.

", "resource": null, "actions": { "nOzLQ0NJzeB3vKiV": { @@ -413,7 +421,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -442,7 +451,16 @@ }, "name": "Spend Fear", "img": "icons/magic/fire/projectile-beams-salvo-red.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Hellfire", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Minor_Fire_Elemental_DscWkNVoHak6P4hh.json b/src/packs/adversaries/adversary_Minor_Fire_Elemental_DscWkNVoHak6P4hh.json index 0cc9703c..859c207c 100644 --- a/src/packs/adversaries/adversary_Minor_Fire_Elemental_DscWkNVoHak6P4hh.json +++ b/src/packs/adversaries/adversary_Minor_Fire_Elemental_DscWkNVoHak6P4hh.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -273,7 +271,7 @@ "_id": "7AXE86WNd68OySkD", "img": "icons/magic/fire/explosion-flame-lightning-strike.webp", "system": { - "description": "

Mark a Stress to choose a point within Far range. The ground within Very Close range of that point immediately bursts into flames. All creatures within this area must make an Agility Reaction Roll. Targets who fail take 2d8 magic damage from the flames. Targets who succeed take half damage.

@Template[type:circle|range:vc]

", + "description": "

Mark a Stress to choose a point within Far range. The ground within Very Close range of that point immediately bursts into flames. All creatures within this area must make an Agility Reaction Roll. Targets who fail take 2d8 magic damage from the flames. Targets who succeed take half damage.

", "resource": null, "actions": { "x1VCkfcSYiPyg8fk": { @@ -354,7 +352,16 @@ }, "name": "Attack", "img": "icons/magic/fire/explosion-flame-lightning-strike.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Scorched Earth", + "type": "placed", + "shape": "circle", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, @@ -381,14 +388,14 @@ "_id": "ESnu3I89BmUdBZEk", "img": "icons/magic/fire/explosion-fireball-large-red-orange.webp", "system": { - "description": "

Spend a Fear to erupt in a fi ery explosion. Make an attack against all targets within Close range. Targets the Elemental succeeds against take 1d8 magic damage and are knocked back to Far range.

@Template[type:emanation|range:c]

", + "description": "

Spend a Fear to erupt in a fi ery explosion. Make an attack against all targets within Close range. Targets the Elemental succeeds against take 1d8 magic damage and are knocked back to Far range.

", "resource": null, "actions": { "JQgqyW8H7fugR7F0": { "type": "attack", "_id": "JQgqyW8H7fugR7F0", "systemPath": "actions", - "description": "

Spend a Fear to erupt in a fi ery explosion. Make an attack against all targets within Close range. Targets the Elemental succeeds against take 1d8 magic damage and are knocked back to Far range.

@Template[type:emanation|range:c]

", + "description": "", "chatDisplay": true, "actionType": "action", "cost": [ @@ -433,7 +440,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -462,7 +470,16 @@ }, "name": "Attack", "img": "icons/magic/fire/explosion-fireball-large-red-orange.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Explosion", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -492,9 +509,11 @@ "description": "

Three times per scene, when the @Lookup[@name] moves onto objects that are highly flammable, consume them to clear a HP or a Stress.

", "resource": { "type": "simple", - "value": 0, + "value": 3, "max": "3", - "icon": "fa-solid fa-fire" + "icon": "fa-solid fa-fire", + "progression": "decreasing", + "recovery": "scene" }, "actions": { "CTWSVVisdgJgF7pd": { @@ -504,7 +523,16 @@ "description": "", "chatDisplay": true, "actionType": "action", - "cost": [], + "cost": [ + { + "scalable": false, + "key": "resource", + "value": 1, + "itemId": "3u6wvKPJAS2v5nWV", + "step": null, + "consumeOnSuccess": false + } + ], "uses": { "value": null, "max": "", @@ -538,7 +566,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "self", @@ -571,7 +600,16 @@ "description": "", "chatDisplay": true, "actionType": "action", - "cost": [], + "cost": [ + { + "scalable": false, + "key": "resource", + "value": 1, + "itemId": "3u6wvKPJAS2v5nWV", + "step": null, + "consumeOnSuccess": false + } + ], "uses": { "value": null, "max": "", @@ -605,7 +643,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "self", diff --git a/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json b/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json index 2eaa9619..33677263 100644 --- a/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json +++ b/src/packs/adversaries/adversary_Mortal_Hunter_mVV7a7KQAORoPMgZ.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,14 +217,15 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { "name": "Terrifying", "type": "feature", "system": { - "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range lose a Hope and you gain a Fear.

@Template[type:emanation|range:f]

", + "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range lose a Hope and you gain a Fear.

", "resource": null, "actions": { "9T1g3FH38cnCRG8k": { @@ -271,7 +269,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -280,7 +279,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/magic/death/skull-energy-light-purple.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Terrifying", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, @@ -574,7 +582,7 @@ "name": "Rampage", "type": "feature", "system": { - "description": "

Countdown (Loop 1d6). When the @Lookup[@name] is in the spotlight for the first time, activate the countdown. When it triggers, move the @Lookup[@name] in a straight line to a point within Far range and make an attack against all targets in their path. Targets the @Lookup[@name] succeeds against take 2d8+2 physical damage.

@Template[type:ray|range:f]

", + "description": "

Countdown (Loop 1d6). When the @Lookup[@name] is in the spotlight for the first time, activate the countdown. When it triggers, move the @Lookup[@name] in a straight line to a point within Far range and make an attack against all targets in their path. Targets the @Lookup[@name] succeeds against take 2d8+2 physical damage.

", "resource": null, "actions": { "VjiFxuzfAaq5N1jy": { @@ -619,7 +627,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -648,7 +657,16 @@ }, "name": "Attack", "img": "icons/magic/movement/trail-streak-zigzag-yellow.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Rampage", + "type": "placed", + "shape": "line", + "size": "far", + "effects": [] + } + ] }, "BhA3vxCuMs4UbbQU": { "type": "countdown", diff --git a/src/packs/adversaries/adversary_Oracle_of_Doom_befIqd5IYKg6eUz2.json b/src/packs/adversaries/adversary_Oracle_of_Doom_befIqd5IYKg6eUz2.json index 343cfdc1..a9b865ae 100644 --- a/src/packs/adversaries/adversary_Oracle_of_Doom_befIqd5IYKg6eUz2.json +++ b/src/packs/adversaries/adversary_Oracle_of_Doom_befIqd5IYKg6eUz2.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,14 +217,15 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { "name": "Terrifying", "type": "feature", "system": { - "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range lose a Hope and you gain a Fear.

@Template[type:emanation|range:f]

", + "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range lose a Hope and you gain a Fear.

", "resource": null, "actions": { "VjdSO1lAdTIAlofM": { @@ -271,7 +269,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -280,7 +279,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/magic/death/skull-energy-light-purple.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Terrifying", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Outer_Realms_Abomination_A0SeeDzwjvqOsyof.json b/src/packs/adversaries/adversary_Outer_Realms_Abomination_A0SeeDzwjvqOsyof.json index 0f73354e..3e5bacf3 100644 --- a/src/packs/adversaries/adversary_Outer_Realms_Abomination_A0SeeDzwjvqOsyof.json +++ b/src/packs/adversaries/adversary_Outer_Realms_Abomination_A0SeeDzwjvqOsyof.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -367,7 +365,7 @@ "name": "Reality Quake", "type": "feature", "system": { - "description": "

Spend a Fear to rattle the edges of reality within Far range of the @Lookup[@name]. All targets within that area must succeed on a Knowledge Reaction Roll or become Unstuck from reality until the end of the scene. When an Unstuck target spends Hope or marks Armor Slots, HP, or Stress, they must double the amount spent or marked.

@Template[type:emanation|range:f]

", + "description": "

Spend a Fear to rattle the edges of reality within Far range of the @Lookup[@name]. All targets within that area must succeed on a Knowledge Reaction Roll or become Unstuck from reality until the end of the scene. When an Unstuck target spends Hope or marks Armor Slots, HP, or Stress, they must double the amount spent or marked.

", "resource": null, "actions": { "7apNSLz8m7sxyLhU": { @@ -385,7 +383,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -419,7 +418,16 @@ }, "name": "Roll Save", "img": "icons/magic/sonic/explosion-shock-sound-wave.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Reality Quake", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Outer_Realms_Corrupter_ms6nuOl3NFkhPj1k.json b/src/packs/adversaries/adversary_Outer_Realms_Corrupter_ms6nuOl3NFkhPj1k.json index 6c78dced..9edf3f04 100644 --- a/src/packs/adversaries/adversary_Outer_Realms_Corrupter_ms6nuOl3NFkhPj1k.json +++ b/src/packs/adversaries/adversary_Outer_Realms_Corrupter_ms6nuOl3NFkhPj1k.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -299,7 +297,7 @@ "name": "Disgorge Realiy Flotsam", "type": "feature", "system": { - "description": "

Mark a Stress to spew partially digested portions of consumed realities at all targets within Close range. Targets must succeed on a Knowledge Reaction Roll or mark 2 Stress.

@Template[type:emanation|range:c]

", + "description": "

Mark a Stress to spew partially digested portions of consumed realities at all targets within Close range. Targets must succeed on a Knowledge Reaction Roll or mark 2 Stress.

", "resource": null, "actions": { "6vX6VHpXX7OiGSWH": { @@ -343,7 +341,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -372,7 +371,16 @@ }, "name": "Roll Save", "img": "icons/magic/unholy/barrier-shield-glowing-pink.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Disgorge Realiy Flotsam", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Patchwork_Zombie_Hulk_EQTOAOUrkIvS2z88.json b/src/packs/adversaries/adversary_Patchwork_Zombie_Hulk_EQTOAOUrkIvS2z88.json index 999f89b9..8e82dcf7 100644 --- a/src/packs/adversaries/adversary_Patchwork_Zombie_Hulk_EQTOAOUrkIvS2z88.json +++ b/src/packs/adversaries/adversary_Patchwork_Zombie_Hulk_EQTOAOUrkIvS2z88.json @@ -143,12 +143,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -199,7 +196,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -225,7 +222,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -317,9 +315,46 @@ "_id": "0fn7rVLwBnyCyvTA", "img": "icons/skills/melee/strike-slashes-orange.webp", "system": { - "description": "

When the @Lookup[@name] makes a standard attack, they can attack all targets within Very Close range.

@Template[type:emanation|range:vc]

", + "description": "

When the @Lookup[@name] makes a standard attack, they can attack all targets within Very Close range.

", "resource": null, - "actions": {}, + "actions": { + "ngl1xlJT4IOh3bkJ": { + "type": "effect", + "_id": "ngl1xlJT4IOh3bkJ", + "systemPath": "actions", + "baseAction": false, + "description": "", + "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, + "actionType": "action", + "triggers": [], + "areas": [ + { + "name": "Flailing Limbs", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ], + "cost": [], + "uses": { + "value": null, + "max": "", + "recovery": null, + "consumeOnSuccess": false + }, + "effects": [], + "target": { + "type": "any", + "amount": null + }, + "name": "", + "range": "" + } + }, "originItemType": null, "subType": null, "originId": null @@ -463,7 +498,7 @@ "_id": "uTtQwNg46NAjgzuD", "img": "icons/magic/death/skeleton-skull-soul-blue.webp", "system": { - "description": "

Mark a Stress to cause all PCs within Far range to make a Presence Reaction Roll (13). Targets who fail lose a Hope and you gain a Fear for each. Targets who succeed must mark a Stress.

@Template[type:emanation|range:f]

", + "description": "

Mark a Stress to cause all PCs within Far range to make a Presence Reaction Roll (13). Targets who fail lose a Hope and you gain a Fear for each. Targets who succeed must mark a Stress.

", "resource": null, "actions": { "2NYC0D7wkBNrUAKl": { @@ -514,7 +549,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -543,7 +579,16 @@ }, "name": "Mark Stress", "img": "icons/magic/death/skeleton-skull-soul-blue.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Tormented Screams", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Perfected_Zombie_CP6iRfHdyFWniTHY.json b/src/packs/adversaries/adversary_Perfected_Zombie_CP6iRfHdyFWniTHY.json index a6ce78d5..06a18345 100644 --- a/src/packs/adversaries/adversary_Perfected_Zombie_CP6iRfHdyFWniTHY.json +++ b/src/packs/adversaries/adversary_Perfected_Zombie_CP6iRfHdyFWniTHY.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,14 +211,15 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { "name": "Terrifying", "type": "feature", "system": { - "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range lose a Hope and you gain a Fear.

@Template[type:emanation|range:f]

", + "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range lose a Hope and you gain a Fear.

", "resource": null, "actions": { "dquYnt5qiHZfnyD9": { @@ -265,7 +263,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -274,7 +273,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/magic/death/skull-energy-light-purple.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Terrifying", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, @@ -324,7 +332,7 @@ "name": "Perfect Strike", "type": "feature", "system": { - "description": "

Mark a Stress to make a standard attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against are Vulnerable until their next rest.

@Template[type:emanation|range:vc]

", + "description": "

Mark a Stress to make a standard attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against are Vulnerable until their next rest.

", "resource": null, "actions": { "un9btM1mN53JHIgV": { @@ -376,7 +384,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -410,7 +419,16 @@ }, "name": "Attack", "img": "icons/skills/melee/strike-axe-energy-pink.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Perfect Strike", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Shark_YmVAkdNsyuXWTtYp.json b/src/packs/adversaries/adversary_Shark_YmVAkdNsyuXWTtYp.json index f9bad7ea..0a6f27b0 100644 --- a/src/packs/adversaries/adversary_Shark_YmVAkdNsyuXWTtYp.json +++ b/src/packs/adversaries/adversary_Shark_YmVAkdNsyuXWTtYp.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,14 +211,15 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { "name": "Terrifying", "type": "feature", "system": { - "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range lose a Hope and you gain a Fear.

@Template[type:emanation|range:f]

", + "description": "

When the @Lookup[@name] makes a successful attack, all PCs within Far range lose a Hope and you gain a Fear.

", "resource": null, "actions": { "NoEb6qR3ktIu9kRJ": { @@ -265,7 +263,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -274,7 +273,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/magic/death/skull-energy-light-purple.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Terrifying", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Siren_BK4jwyXSRx7IOQiO.json b/src/packs/adversaries/adversary_Siren_BK4jwyXSRx7IOQiO.json index 38f77982..39f6a5b9 100644 --- a/src/packs/adversaries/adversary_Siren_BK4jwyXSRx7IOQiO.json +++ b/src/packs/adversaries/adversary_Siren_BK4jwyXSRx7IOQiO.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,7 +217,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -326,7 +324,7 @@ "name": "Enchanting Song", "type": "feature", "system": { - "description": "

Spend a Fear to sing a song that affects all targets within Close range. Targets must succeed on an Instinct Reaction Roll or become Entranced until they mark 2 Stress. Other @Lookup[@name]s within Close range of the target can mark a Stress to each add a +1 bonus to the Difficulty of the reaction roll. While Entranced, a target can’t act and is Vulnerable.

@Template[type:emanation|range:c]

", + "description": "

Spend a Fear to sing a song that affects all targets within Close range. Targets must succeed on an Instinct Reaction Roll or become Entranced until they mark 2 Stress. Other @Lookup[@name]s within Close range of the target can mark a Stress to each add a +1 bonus to the Difficulty of the reaction roll. While Entranced, a target can’t act and is Vulnerable.

", "resource": null, "actions": { "FY8K8Nsg0TKAWok8": { @@ -351,7 +349,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -385,7 +384,16 @@ }, "name": "Roll Save", "img": "icons/magic/control/hypnosis-mesmerism-eye.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Enchanting Song", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Skeleton_Knight_Q9LaVTyXF9NF12C7.json b/src/packs/adversaries/adversary_Skeleton_Knight_Q9LaVTyXF9NF12C7.json index 8b2042f3..e6982135 100644 --- a/src/packs/adversaries/adversary_Skeleton_Knight_Q9LaVTyXF9NF12C7.json +++ b/src/packs/adversaries/adversary_Skeleton_Knight_Q9LaVTyXF9NF12C7.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -302,7 +300,7 @@ "_id": "WdVLwy9RNkVlZnCL", "img": "icons/skills/melee/strike-sword-steel-yellow.webp", "system": { - "description": "

Mark a Stress to make an attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against take 1d8+2 physical damage and must mark a Stress.

@Template[type:emanation|range:vc]

", + "description": "

Mark a Stress to make an attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against take 1d8+2 physical damage and must mark a Stress.

", "resource": null, "actions": { "vMv4monku9LOSxUZ": { @@ -379,7 +377,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -408,7 +407,16 @@ }, "name": "Attack", "img": "icons/skills/melee/strike-sword-steel-yellow.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Cut to the Bone", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Spellblade_ldbWEL7uZs84vyrR.json b/src/packs/adversaries/adversary_Spellblade_ldbWEL7uZs84vyrR.json index 90c7d68f..5d72dfc7 100644 --- a/src/packs/adversaries/adversary_Spellblade_ldbWEL7uZs84vyrR.json +++ b/src/packs/adversaries/adversary_Spellblade_ldbWEL7uZs84vyrR.json @@ -139,12 +139,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -195,7 +192,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -221,7 +218,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -256,7 +254,7 @@ "_id": "a76dNCrcoZOH1RRT", "img": "icons/magic/sonic/projectile-shock-wave-blue.webp", "system": { - "description": "

Mark a Stress and target a group within Far range. All targets must succeed on an Agility Reaction Roll or take 1d8+2 magic damage. You gain a Fear for each target who marked HP from this attack.

@Template[type:emanation|range:f]

", + "description": "

Mark a Stress and target a group within Far range. All targets must succeed on an Agility Reaction Roll or take 1d8+2 magic damage. You gain a Fear for each target who marked HP from this attack.

", "resource": null, "actions": { "K4VnxigKTiu7hhZx": { @@ -308,7 +306,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -337,7 +336,16 @@ }, "name": "Attack", "img": "icons/magic/sonic/projectile-shock-wave-blue.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Supressing Blast", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, @@ -394,7 +402,16 @@ }, "name": "Spend Fear", "img": "icons/skills/movement/arrows-up-trio-red.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Move as a Unit", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Stag_Knight_KGVwnLq85ywP9xvB.json b/src/packs/adversaries/adversary_Stag_Knight_KGVwnLq85ywP9xvB.json index e7738a46..14e81a8c 100644 --- a/src/packs/adversaries/adversary_Stag_Knight_KGVwnLq85ywP9xvB.json +++ b/src/packs/adversaries/adversary_Stag_Knight_KGVwnLq85ywP9xvB.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,7 +217,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -306,7 +304,7 @@ "name": "Blade of the Forest", "type": "feature", "system": { - "description": "

Spend a Fear to make an attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against take physical damage equal to [[/r 3d4]] + the target’s Major threshold.

@Template[type:emanation|range:vc]

", + "description": "

Spend a Fear to make an attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against take physical damage equal to [[/r 3d4]] + the target’s Major threshold.

", "resource": null, "actions": { "xPSVwVVOC5gc2KTi": { @@ -331,7 +329,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -360,7 +359,16 @@ }, "name": "Attack", "img": "icons/skills/melee/strike-blade-hooked-green-purple.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Blade of the Forest", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json b/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json index c50c426d..52869085 100644 --- a/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json +++ b/src/packs/adversaries/adversary_Stonewraith_3aAS2Qm3R6cgaYfE.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,7 +217,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -411,7 +409,7 @@ "name": "Avalanche Roar", "type": "feature", "system": { - "description": "

Spend a Fear to roar while within a cave and cause a cave-in. All targets within Close range must succeed on an Agility Reaction Roll (14) or take 2d10 physical damage. The rubble can be cleared with a Progress Countdown (8).

@Template[type:emanation|range:c]

", + "description": "

Spend a Fear to roar while within a cave and cause a cave-in. All targets within Close range must succeed on an Agility Reaction Roll (14) or take 2d10 physical damage. The rubble can be cleared with a Progress Countdown (8).

", "resource": null, "actions": { "4UGEEuK9XY8leCBV": { @@ -463,7 +461,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -492,7 +491,16 @@ }, "name": "Roll Save", "img": "icons/magic/sonic/projectile-sound-rings-wave.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Avalanche Roar", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] }, "UurIzyyMRAJc2DUX": { "type": "countdown", diff --git a/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json b/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json index d4fa0340..ba3f5c33 100644 --- a/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json +++ b/src/packs/adversaries/adversary_Vault_Guardian_Sentinel_FVgYb28fhxlVcGwA.json @@ -349,7 +349,7 @@ "name": "Mana Bolt", "type": "feature", "system": { - "description": "

Spend a Fear to lob explosive magic at a point within Far range. All targets within Very Close range of that point must make an Agility Reaction Roll. Targets who fail take 2d8+20 magic damage and are knocked back to Close range. Targets who succeed take half damage and aren’t knocked back.

@Template[type:circle|range:vc]

", + "description": "

Spend a Fear to lob explosive magic at a point within Far range. All targets within Very Close range of that point must make an Agility Reaction Roll. Targets who fail take 2d8+20 magic damage and are knocked back to Close range. Targets who succeed take half damage and aren’t knocked back.

", "resource": null, "actions": { "mI9i9iwrM48NjzeE": { @@ -430,7 +430,16 @@ }, "name": "Roll Save", "img": "icons/magic/sonic/projectile-shock-wave-blue.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Mana Bolt", + "type": "placed", + "shape": "circle", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Vault_Guardian_Turret_c5hGdvY5UnSjlHws.json b/src/packs/adversaries/adversary_Vault_Guardian_Turret_c5hGdvY5UnSjlHws.json index d723df80..018d5b58 100644 --- a/src/packs/adversaries/adversary_Vault_Guardian_Turret_c5hGdvY5UnSjlHws.json +++ b/src/packs/adversaries/adversary_Vault_Guardian_Turret_c5hGdvY5UnSjlHws.json @@ -132,12 +132,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -188,7 +185,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -214,7 +211,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -412,7 +410,7 @@ "name": "Detonation", "type": "feature", "system": { - "description": "

When the @Lookup[@name] is destroyed, they explode. All targets within Close range must make an Agility Reaction Roll. Targets who fail take 3d20 physical damage. Targets who succeed take half damage.

@Template[type:emanation|range:c]

", + "description": "

When the @Lookup[@name] is destroyed, they explode. All targets within Close range must make an Agility Reaction Roll. Targets who fail take 3d20 physical damage. Targets who succeed take half damage.

", "resource": null, "actions": { "i1PZ9ddYdOOs2xSb": { @@ -457,7 +455,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -486,7 +485,16 @@ }, "name": "Roll Save", "img": "icons/magic/sonic/explosion-shock-wave-teal.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Detonation", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": 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 f6a8bc84..e360f0c8 100644 --- a/src/packs/adversaries/adversary_Volcanic_Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json +++ b/src/packs/adversaries/adversary_Volcanic_Dragon__Ashen_Tyrant_pMuXGCSOQaxpi5tb.json @@ -163,12 +163,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -219,7 +216,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -245,7 +242,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -478,7 +476,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -487,7 +486,16 @@ "effects": [], "name": "Lose Hope", "img": "icons/magic/fire/flame-burning-skull-orange.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Ashes to Ashes", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -512,7 +520,7 @@ "name": "Desperate Rampage", "type": "feature", "system": { - "description": "

Mark a Stress to make an attack against all targets within Close range. Targets the @Lookup[@name] succeeds against take 2d20+2 physical damage, are knocked back to Close range of where they were, and must mark a Stress.

@Template[type:emanation|range:c]

", + "description": "

Mark a Stress to make an attack against all targets within Close range. Targets the @Lookup[@name] succeeds against take 2d20+2 physical damage, are knocked back to Close range of where they were, and must mark a Stress.

", "resource": null, "actions": { "3glUQAcsLBcCumnS": { @@ -582,7 +590,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -611,7 +620,16 @@ }, "name": "Attack", "img": "icons/creatures/abilities/tail-swipe-green.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Desperate Rampage", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -637,7 +655,7 @@ "name": "Ashen Cloud", "type": "feature", "system": { - "description": "

Spend a Fear to smash the ground and kick up ash within Far range. While within the ash cloud, a target has disadvantage on action rolls. The ash cloud clears the next time an adversary is spotlighted.

@Template[type:emanation|range:f]

", + "description": "

Spend a Fear to smash the ground and kick up ash within Far range. While within the ash cloud, a target has disadvantage on action rolls. The ash cloud clears the next time an adversary is spotlighted.

", "resource": null, "actions": { "UrD4A68IBJgyfvvt": { @@ -667,7 +685,16 @@ }, "name": "Spend Fear", "img": "icons/magic/air/fog-gas-smoke-brown.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Ashen Cloud", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, @@ -693,14 +720,14 @@ "name": "Apocalyptic Thrasing", "type": "feature", "system": { - "description": "

Countdown (1d12). Spend a Fear to activate. It ticks down when a PC rolls with Fear. When it triggers, the @Lookup[@name] thrashes about, causing environmental damage (such as an earthquake, avalanche, or collapsing walls). All targets within Far range must make a Strength Reaction Roll. Targets who fail take 2d10+10 physical damage and are Restrained by the rubble until they break free with a successful Strength Roll. Targets who succeed take half damage. If the @Lookup[@name] is defeated while this countdown is active, trigger the countdown immediately as the destruction caused by their death throes.

@Template[type:emanation|range:f]

", + "description": "

Countdown (1d12). Spend a Fear to activate. It ticks down when a PC rolls with Fear. When it triggers, the @Lookup[@name] thrashes about, causing environmental damage (such as an earthquake, avalanche, or collapsing walls). All targets within Far range must make a Strength Reaction Roll. Targets who fail take 2d10+10 physical damage and are Restrained by the rubble until they break free with a successful Strength Roll. Targets who succeed take half damage. If the @Lookup[@name] is defeated while this countdown is active, trigger the countdown immediately as the destruction caused by their death throes.

", "resource": null, "actions": { "OznXxmwiPwzuFPQZ": { "type": "attack", "_id": "OznXxmwiPwzuFPQZ", "systemPath": "actions", - "description": "

When the countdown triggers, the @Lookup[@name] thrashes about, causing environmental damage (such as an earthquake, avalanche, or collapsing walls). All targets within Far range must make a Strength Reaction Roll. Targets who fail take 2d10+10 physical damage and are Restrained by the rubble until they break free with a successful Strength Roll. Targets who succeed take half damage. If the @Lookup[@name] is defeated while this countdown is active, trigger the countdown immediately as the destruction caused by their death throes.

@Template[type:emanation|range:f]

", + "description": "

When the countdown triggers, the @Lookup[@name] thrashes about, causing environmental damage (such as an earthquake, avalanche, or collapsing walls). All targets within Far range must make a Strength Reaction Roll. Targets who fail take 2d10+10 physical damage and are Restrained by the rubble until they break free with a successful Strength Roll. Targets who succeed take half damage. If the @Lookup[@name] is defeated while this countdown is active, trigger the countdown immediately as the destruction caused by their death throes.

", "chatDisplay": true, "actionType": "action", "cost": [], @@ -738,7 +765,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -772,7 +800,16 @@ }, "name": "Roll Save", "img": "icons/creatures/abilities/mouth-teeth-fire-orange.webp", - "range": "" + "range": "", + "areas": [ + { + "name": "Apocalyptic Thrasing", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] }, "rZ7IwBnDzw7VmBT6": { "type": "countdown", 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 25c8b637..d4babd71 100644 --- a/src/packs/adversaries/adversary_Volcanic_Dragon__Molten_Scourge_eArAPuB38CNR0ZIM.json +++ b/src/packs/adversaries/adversary_Volcanic_Dragon__Molten_Scourge_eArAPuB38CNR0ZIM.json @@ -163,12 +163,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -219,7 +216,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -245,7 +242,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -442,7 +440,7 @@ "name": "Eruption", "type": "feature", "system": { - "description": "

Spend a Fear to erupt lava from beneath the @Lookup[@name]’s scales, filling the area within Very Close range with molten lava. All targets in that area must succeed on an Agility Reaction Roll or take 4d6+6 physical damage and be knocked back to Close range. This area remains lava. When a creature other than the @Lookup[@name] enters that area or acts while inside of it, they must mark 6 HP.

@Template[type:emanation|range:vc]

", + "description": "

Spend a Fear to erupt lava from beneath the @Lookup[@name]’s scales, filling the area within Very Close range with molten lava. All targets in that area must succeed on an Agility Reaction Roll or take 4d6+6 physical damage and be knocked back to Close range. This area remains lava. When a creature other than the @Lookup[@name] enters that area or acts while inside of it, they must mark 6 HP.

", "resource": null, "actions": { "OpwKa8tQQoaEIZiS": { @@ -487,7 +485,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -516,7 +515,16 @@ }, "name": "Roll Save", "img": "icons/magic/fire/blast-jet-stream-embers-red.webp", - "range": "veryClose" + "range": "veryClose", + "areas": [ + { + "name": "Eruption", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, @@ -542,7 +550,7 @@ "name": "Volcanic Breath", "type": "feature", "system": { - "description": "

When the @Lookup[@name] takes Major damage, roll a d10. On a result of 8 or higher, the @Lookup[@name] breathes a flow of lava in front of them within Far range. All targets in that area must make an Agility Reaction Roll. Targets who fail take 2d10+4 physical damage, mark 1d4 Stress, and are Vulnerable until they clear a Stress. Targets who succeed take half damage and must mark a Stress.

@Template[type:inFront|range:f]

", + "description": "

When the @Lookup[@name] takes Major damage, roll a d10. On a result of 8 or higher, the @Lookup[@name] breathes a flow of lava in front of them within Far range. All targets in that area must make an Agility Reaction Roll. Targets who fail take 2d10+4 physical damage, mark 1d4 Stress, and are Vulnerable until they clear a Stress. Targets who succeed take half damage and must mark a Stress.

", "resource": null, "actions": { "OhrssSQhmciZt1Rm": { @@ -602,7 +610,7 @@ "type": "attack", "_id": "LBNvfABGWcrygpQM", "systemPath": "actions", - "description": "

The @Lookup[@name] breathes a flow of lava in front of them within Far range. All targets in that area must make an Agility Reaction Roll. Targets who fail take 2d10+4 physical damage, mark 1d4 Stress, and are Vulnerable until they clear a Stress. Targets who succeed take half damage and must mark a Stress.

@Template[type:inFront|range:f]

", + "description": "

The @Lookup[@name]Β breathes a flow of lava in front of them within Far range. All targets in that area must make an Agility Reaction Roll. Targets who fail take 2d10+4 physical damage, mark 1d4 Stress, and are Vulnerable until they clear a Stress. Targets who succeed take half damage and must mark a Stress.

", "chatDisplay": true, "actionType": "action", "cost": [], @@ -664,7 +672,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -698,7 +707,16 @@ }, "name": "Roll Save", "img": "icons/magic/fire/blast-jet-stream-embers-orange.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Volcanic Breath", + "type": "placed", + "shape": "inFront", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, 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 227efccc..82daed6a 100644 --- a/src/packs/adversaries/adversary_Volcanic_Dragon__Obsidian_Predator_ladm7wykhZczYzrQ.json +++ b/src/packs/adversaries/adversary_Volcanic_Dragon__Obsidian_Predator_ladm7wykhZczYzrQ.json @@ -163,12 +163,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -219,7 +216,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -245,7 +242,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -448,7 +446,7 @@ "name": "Avalanche Tail", "type": "feature", "system": { - "description": "

Mark a Stress to make an attack against all targets within Close range. Targets the @Lookup[@name] succeeds against take 4d6+4 physical damage and are knocked.

@Template[type:emanation|range:c]

", + "description": "

Mark a Stress to make an attack against all targets within Close range. Targets the @Lookup[@name] succeeds against take 4d6+4 physical damage and are knocked.

", "resource": null, "actions": { "23y0BoufIgNq62j9": { @@ -491,7 +489,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -525,7 +524,16 @@ }, "name": "Attack", "img": "icons/creatures/abilities/tail-swipe-green.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Avalanche Tail", + "type": "placed", + "shape": "emanation", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -548,18 +556,15 @@ "type": "withinRange", "target": "hostile", "range": "melee" - } + }, + "changes": [] }, - "changes": [], "disabled": false, "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null + "value": null, + "units": "seconds", + "expiry": null, + "expired": false }, "description": "

Vulnerable until your next roll with Hope.

", "tint": "#ffffff", @@ -571,6 +576,9 @@ "_stats": { "compendiumSource": null }, + "start": null, + "showIcon": 1, + "folder": null, "_key": "!actors.items.effects!ladm7wykhZczYzrQ.8bMOItTuL7PfAYcJ.qtIaAZDW8QsjILgb" } ], @@ -590,7 +598,7 @@ "name": "Dive-Bomb", "type": "feature", "system": { - "description": "

If the @Lookup[@name] is flying, mark a Stress to choose a point within Far range. Move to that point and make an attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against take 2d10+6 physical damage and must mark a Stress and lose a Hope.

@Template[type:emanation|range:vc]

", + "description": "

If the @Lookup[@name] is flying, mark a Stress to choose a point within Far range. Move to that point and make an attack against all targets within Very Close range. Targets the @Lookup[@name] succeeds against take 2d10+6 physical damage and must mark a Stress and lose a Hope.

", "resource": null, "actions": { "OpAT9nxlbgvnhdBg": { @@ -685,7 +693,8 @@ "type": [] } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -714,7 +723,16 @@ }, "name": "Attack", "img": "icons/creatures/reptiles/dragon-winged-blue.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Dive-Bomb", + "type": "placed", + "shape": "emanation", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_War_Wizard_noDdT0tsN6FXSmC8.json b/src/packs/adversaries/adversary_War_Wizard_noDdT0tsN6FXSmC8.json index 55be8e1a..0ba663ab 100644 --- a/src/packs/adversaries/adversary_War_Wizard_noDdT0tsN6FXSmC8.json +++ b/src/packs/adversaries/adversary_War_Wizard_noDdT0tsN6FXSmC8.json @@ -143,12 +143,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -199,7 +196,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -225,7 +222,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -343,7 +341,7 @@ "name": "Eruption", "type": "feature", "system": { - "description": "

Spend a Fear and choose a point within Far range. A Very Close area around that point erupts into impassable terrain. All targets within that area must make an Agility Reaction Roll (14). Targets who fail take 2d10 physical damage and are thrown out of the area. Targets who succeed take half damage and aren’t moved.

@Template[type:circle|range:vc]

", + "description": "

Spend a Fear and choose a point within Far range. A Very Close area around that point erupts into impassable terrain. All targets within that area must make an Agility Reaction Roll (14). Targets who fail take 2d10 physical damage and are thrown out of the area. Targets who succeed take half damage and aren’t moved.

", "resource": null, "actions": { "vnMq4NuQO6GYxWhM": { @@ -424,7 +422,16 @@ }, "name": "Roll Save", "img": "icons/magic/earth/barrier-stone-explosion-red.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Eruption", + "type": "placed", + "shape": "circle", + "size": "veryClose", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/adversaries/adversary_Young_Ice_Dragon_UGPiPLJsPvMTSKEF.json b/src/packs/adversaries/adversary_Young_Ice_Dragon_UGPiPLJsPvMTSKEF.json index 09e76fa8..6c55ba15 100644 --- a/src/packs/adversaries/adversary_Young_Ice_Dragon_UGPiPLJsPvMTSKEF.json +++ b/src/packs/adversaries/adversary_Young_Ice_Dragon_UGPiPLJsPvMTSKEF.json @@ -138,12 +138,9 @@ "src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg", "anchorX": 0.5, "anchorY": 0.5, - "offsetX": 0, - "offsetY": 0, "fit": "contain", "scaleX": 1, "scaleY": 1, - "rotation": 0, "tint": "#ffffff", "alphaThreshold": 0.75 }, @@ -194,7 +191,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -220,7 +217,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -388,7 +386,7 @@ "name": "Blizzard Breath", "type": "feature", "system": { - "description": "

Spend 2 Fear to release an icy whorl in front of the @Lookup[@name] within Close range. All targets in this area must make an Agility Reaction Roll. Targets who fail take 4d6+5 magic damage and are Restrained by ice until they break free with a successful Strength Roll. Targets who succeed must mark 2 Stress or take half damage.

@Template[type:inFront|range:c]

", + "description": "

Spend 2 Fear to release an icy whorl in front of the @Lookup[@name] within Close range. All targets in this area must make an Agility Reaction Roll. Targets who fail take 4d6+5 magic damage and are Restrained by ice until they break free with a successful Strength Roll. Targets who succeed must mark 2 Stress or take half damage.

", "resource": null, "actions": { "CBecTlgyUBFxgoi5": { @@ -440,7 +438,8 @@ } } }, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -474,7 +473,16 @@ }, "name": "Roll Save", "img": "icons/magic/water/projectiles-ice-faceted-shard-salvo-blue.webp", - "range": "close" + "range": "close", + "areas": [ + { + "name": "Blizzard Breath", + "type": "placed", + "shape": "inFront", + "size": "close", + "effects": [] + } + ] } }, "originItemType": null, @@ -497,18 +505,15 @@ "type": "withinRange", "target": "hostile", "range": "melee" - } + }, + "changes": [] }, - "changes": [], "disabled": false, "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null + "value": null, + "units": "seconds", + "expiry": null, + "expired": false }, "description": "

Restrained by ice until you break free with a successful Strength Roll.

", "tint": "#ffffff", @@ -520,6 +525,9 @@ "_stats": { "compendiumSource": null }, + "start": null, + "showIcon": 1, + "folder": null, "_key": "!actors.items.effects!UGPiPLJsPvMTSKEF.QV2ytK4b1VWF71OS.g9bUvmw3jet6T99e" } ], @@ -539,7 +547,7 @@ "name": "Avalanche", "type": "feature", "system": { - "description": "

Spend a Fear to have the @Lookup[@name] unleash a huge downfall of snow and ice, covering all other creatures within Far range. All targets within this area must succeed on an Instinct Reaction Roll or be buried in snow and rocks, becoming Vulnerable until they dig themselves out from the debris. For each PC that fails the reaction roll, you gain a Fear.

@Template[type:emanation|range:f]

", + "description": "

Spend a Fear to have the @Lookup[@name] unleash a huge downfall of snow and ice, covering all other creatures within Far range. All targets within this area must succeed on an Instinct Reaction Roll or be buried in snow and rocks, becoming Vulnerable until they dig themselves out from the debris. For each PC that fails the reaction roll, you gain a Fear.

", "resource": null, "actions": { "G9LjoXShkCcgx8EC": { @@ -564,7 +572,8 @@ }, "damage": { "parts": {}, - "includeBase": false + "includeBase": false, + "groupAttack": "" }, "target": { "type": "any", @@ -598,7 +607,16 @@ }, "name": "Attack", "img": "icons/magic/water/barrier-ice-wall-snow.webp", - "range": "far" + "range": "far", + "areas": [ + { + "name": "Avalanche", + "type": "placed", + "shape": "emanation", + "size": "far", + "effects": [] + } + ] } }, "originItemType": null, diff --git a/src/packs/ancestries/feature_Retract_UFR67BUOhNGLFyg9.json b/src/packs/ancestries/feature_Retract_UFR67BUOhNGLFyg9.json index b17cd7da..eb9696b2 100644 --- a/src/packs/ancestries/feature_Retract_UFR67BUOhNGLFyg9.json +++ b/src/packs/ancestries/feature_Retract_UFR67BUOhNGLFyg9.json @@ -68,31 +68,33 @@ "type": "withinRange", "target": "hostile", "range": "melee" + }, + "changes": [ + { + "key": "system.resistance.physical.resistance", + "type": "override", + "value": 1, + "priority": null, + "phase": "initial" + }, + { + "key": "system.disadvantageSources", + "type": "add", + "value": "Action rolls", + "priority": null, + "phase": "initial" + } + ], + "duration": { + "type": "" } }, - "changes": [ - { - "key": "system.resistance.physical.resistance", - "mode": 5, - "value": "1", - "priority": null - }, - { - "key": "system.disadvantageSources", - "mode": 2, - "value": "Retract", - "priority": null - } - ], "disabled": true, "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null + "value": null, + "units": "seconds", + "expiry": null, + "expired": false }, "description": "

While in your shell, you have resistance to physical damage, you have disadvantage on action rolls, and you can’t move.

", "tint": "#ffffff", @@ -102,6 +104,16 @@ "_stats": { "compendiumSource": null }, + "start": { + "time": 0, + "combat": null, + "combatant": null, + "initiative": null, + "round": null, + "turn": null + }, + "showIcon": 1, + "folder": null, "_key": "!items.effects!UFR67BUOhNGLFyg9.3V4FPoyjJUnFP9WS" } ], diff --git a/src/packs/communities/feature_Low_Light_Living_aMla3xQuCHEwORGD.json b/src/packs/communities/feature_Low_Light_Living_aMla3xQuCHEwORGD.json index f1ed3ace..c95d9132 100644 --- a/src/packs/communities/feature_Low_Light_Living_aMla3xQuCHEwORGD.json +++ b/src/packs/communities/feature_Low_Light_Living_aMla3xQuCHEwORGD.json @@ -29,39 +29,28 @@ "type": "withinRange", "target": "hostile", "range": "melee" + }, + "changes": [ + { + "key": "system.advantageSources", + "type": "add", + "value": "Rolls to hide, investigate, or perceive details in low light", + "priority": null, + "phase": "initial" + } + ], + "duration": { + "type": "" } }, - "changes": [ - { - "key": "system.advantageSources", - "mode": 2, - "value": "In an area with low light or heavy shadow: hide, investigate, or perceive", - "priority": null - }, - { - "key": "system.advantageSources", - "mode": 2, - "value": "", - "priority": null - }, - { - "key": "", - "mode": 2, - "value": "", - "priority": null - } - ], "disabled": false, "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null + "value": null, + "units": "seconds", + "expiry": null, + "expired": false }, - "description": "", + "description": "

When you’re in an area with low light or heavy shadow, you have advantage on rolls to hide, investigate, or perceive details within that area.

", "origin": null, "tint": "#ffffff", "transfer": true, @@ -71,6 +60,16 @@ "_stats": { "compendiumSource": null }, + "start": { + "time": 0, + "combat": null, + "combatant": null, + "initiative": null, + "round": null, + "turn": null + }, + "showIcon": 1, + "folder": null, "_key": "!items.effects!aMla3xQuCHEwORGD.pCp32u7UwqxCI4WW" } ], diff --git a/src/packs/domains/domainCard_Battle_Cry_Ef1JsUG50LIoKx2F.json b/src/packs/domains/domainCard_Battle_Cry_Ef1JsUG50LIoKx2F.json index c9ae6071..1fde286d 100644 --- a/src/packs/domains/domainCard_Battle_Cry_Ef1JsUG50LIoKx2F.json +++ b/src/packs/domains/domainCard_Battle_Cry_Ef1JsUG50LIoKx2F.json @@ -132,27 +132,29 @@ "type": "withinRange", "target": "hostile", "range": "melee" + }, + "changes": [ + { + "key": "system.advantageSources", + "type": "add", + "value": "On Attacks", + "priority": null, + "phase": "initial" + } + ], + "duration": { + "type": "temporary", + "description": "

Until you or an ally rolls a failure with Fear.

" } }, - "changes": [ - { - "key": "system.advantageSources", - "mode": 2, - "value": "1", - "priority": null - } - ], "disabled": false, "duration": { - "startTime": null, - "combat": null, - "seconds": null, - "rounds": null, - "turns": null, - "startRound": null, - "startTurn": null + "value": null, + "units": "seconds", + "expiry": null, + "expired": false }, - "description": "", + "description": "

You gain advantage on attack rolls until you or an ally rolls a failure with Fear.

", "tint": "#ffffff", "statuses": [], "sort": 0, @@ -160,6 +162,16 @@ "_stats": { "compendiumSource": null }, + "start": { + "time": 0, + "combat": null, + "combatant": null, + "initiative": null, + "round": null, + "turn": null + }, + "showIcon": 1, + "folder": null, "_key": "!items.effects!Ef1JsUG50LIoKx2F.s7ma4TNgAvt0ZgEW" } ], diff --git a/src/packs/environments/environment_Abandoned_Grove_pGEdzdLkqYtBhxnG.json b/src/packs/environments/environment_Abandoned_Grove_pGEdzdLkqYtBhxnG.json index 75fc932f..0cab16a2 100644 --- a/src/packs/environments/environment_Abandoned_Grove_pGEdzdLkqYtBhxnG.json +++ b/src/packs/environments/environment_Abandoned_Grove_pGEdzdLkqYtBhxnG.json @@ -52,12 +52,9 @@ "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 }, @@ -108,7 +105,7 @@ "saturation": 0, "contrast": 0 }, - "detectionModes": [], + "detectionModes": {}, "occludable": { "radius": 0 }, @@ -134,7 +131,8 @@ "flags": {}, "randomImg": false, "appendNumber": false, - "prependAdjective": false + "prependAdjective": false, + "depth": 1 }, "items": [ { @@ -323,7 +321,42 @@ "system": { "description": "

A @UUID[Compendium.daggerheart.adversaries.Actor.8yUj2Mzvnifhxegm]{Young Dryad}, two @UUID[Compendium.daggerheart.adversaries.Actor.VtFBt9XBE0WrGGxP]{Sylvan Soldiers}, and a number of @UUID[Compendium.daggerheart.adversaries.Actor.G62k4oSkhkoXEs2D]{Minor Treants} equal to the number of PCs appear to confront the party for their intrusion.

What are the grove guardians concealing? What threat to the forest could the PCs confront to appease the Dryad?

", "resource": null, - "actions": {}, + "actions": { + "TPm6rpKA4mbili82": { + "type": "summon", + "_id": "TPm6rpKA4mbili82", + "systemPath": "actions", + "baseAction": false, + "description": "", + "chatDisplay": true, + "originItem": { + "type": "itemCollection" + }, + "actionType": "action", + "triggers": [], + "cost": [], + "uses": { + "value": null, + "max": null, + "recovery": null, + "consumeOnSuccess": false + }, + "summon": [ + { + "actorUUID": "Compendium.daggerheart.adversaries.Actor.8yUj2Mzvnifhxegm", + "count": "1" + }, + { + "actorUUID": "Compendium.daggerheart.adversaries.Actor.VtFBt9XBE0WrGGxP", + "count": "2" + }, + { + "actorUUID": "Compendium.daggerheart.adversaries.Actor.G62k4oSkhkoXEs2D", + "count": "@partySize" + } + ] + } + }, "originItemType": null, "originId": null, "featureForm": "action" diff --git a/styles/less/dialog/character-creation/selections-container.less b/styles/less/dialog/character-creation/selections-container.less index f9569fca..2bbac484 100644 --- a/styles/less/dialog/character-creation/selections-container.less +++ b/styles/less/dialog/character-creation/selections-container.less @@ -175,6 +175,11 @@ opacity: 0.2; } + &.no-horizontal-padding { + padding-left: 0; + padding-right: 0; + } + legend { margin-left: auto; margin-right: auto; @@ -250,6 +255,11 @@ height: 65px; background: url(../assets/svg/trait-shield.svg) no-repeat; background-size: 100%; + padding-top: 3px; + display: flex; + flex-direction: column; + align-items: center; + row-gap: 3px; div { filter: drop-shadow(0 0 3px black); @@ -278,6 +288,15 @@ flex-direction: column; gap: 5px; + &.separated { + border-bottom: 2px solid; + padding-bottom: 8px; + } + + .form-group { + padding: 0 0.75rem; + } + .experience-inner-container { position: relative; display: flex; diff --git a/styles/less/dialog/group-roll-dialog/initialization.less b/styles/less/dialog/group-roll-dialog/initialization.less index 96990339..b2e7e021 100644 --- a/styles/less/dialog/group-roll-dialog/initialization.less +++ b/styles/less/dialog/group-roll-dialog/initialization.less @@ -34,6 +34,7 @@ margin-top: 4px; color: light-dark(@dark, @beige); background-image: url('../assets/parchments/dh-parchment-dark.png'); + text-align: center; } img { diff --git a/styles/less/dialog/group-roll-dialog/sheet.less b/styles/less/dialog/group-roll-dialog/sheet.less index 823f6cbf..70afc1fe 100644 --- a/styles/less/dialog/group-roll-dialog/sheet.less +++ b/styles/less/dialog/group-roll-dialog/sheet.less @@ -26,9 +26,8 @@ .member-info { display: flex; - align-items: center; + align-items: start; width: 100%; - height: 64px; img { height: 64px; diff --git a/styles/less/dialog/tag-team-dialog/initialization.less b/styles/less/dialog/tag-team-dialog/initialization.less index 0d16aa3b..8557d231 100644 --- a/styles/less/dialog/tag-team-dialog/initialization.less +++ b/styles/less/dialog/tag-team-dialog/initialization.less @@ -1,3 +1,11 @@ +.theme-light .daggerheart.dialog.dh-style.views.tag-team-dialog { + .initialization-container .members-container .member-container { + .member-name { + background-image: url('../assets/parchments/dh-parchment-light.png'); + } + } +} + .daggerheart.dialog.dh-style.views.tag-team-dialog { .initialization-container { h2 { @@ -26,6 +34,7 @@ margin-top: 4px; color: light-dark(@dark, @beige); background-image: url('../assets/parchments/dh-parchment-dark.png'); + text-align: center; } img { diff --git a/styles/less/global/inventory-item.less b/styles/less/global/inventory-item.less index 4bd4d0bb..a2b9ebd8 100644 --- a/styles/less/global/inventory-item.less +++ b/styles/less/global/inventory-item.less @@ -24,6 +24,15 @@ width: 100%; list-style-type: none; + &.bordered { + border: 1px solid; + border-radius: 6px; + + .inventory-item-header .img-portait img.item-img { + border-radius: 6px 0 0 6px; + } + } + &:not(.single-img) { .img-portait:has(.roll-img):hover { .roll-img { diff --git a/styles/less/global/prose-mirror.less b/styles/less/global/prose-mirror.less index 3523dc89..8a663e28 100644 --- a/styles/less/global/prose-mirror.less +++ b/styles/less/global/prose-mirror.less @@ -25,7 +25,7 @@ } h4 { font-size: var(--font-size-16); - color: @beige; + color: light-dark(@dark, @beige); font-weight: 600; } diff --git a/styles/less/sheets-settings/character-settings/sheet.less b/styles/less/sheets-settings/character-settings/sheet.less index f7f16df4..eab29436 100644 --- a/styles/less/sheets-settings/character-settings/sheet.less +++ b/styles/less/sheets-settings/character-settings/sheet.less @@ -27,10 +27,11 @@ height: 65px; background: url(../assets/svg/trait-shield.svg) no-repeat; background-size: 100%; - padding-top: 4px; + padding-top: 3px; display: flex; flex-direction: column; align-items: center; + row-gap: 3px; span { font-size: var(--font-size-10); diff --git a/styles/less/sheets/actions/actions.less b/styles/less/sheets/actions/actions.less index 5a18d622..485f8e91 100644 --- a/styles/less/sheets/actions/actions.less +++ b/styles/less/sheets/actions/actions.less @@ -147,4 +147,10 @@ padding-bottom: 7px; } } + + .sub-section-header { + display: flex; + align-items: center; + gap: 4px; + } } diff --git a/styles/less/sheets/actors/actor-sheet-shared.less b/styles/less/sheets/actors/actor-sheet-shared.less index 23db088a..bd82ef83 100644 --- a/styles/less/sheets/actors/actor-sheet-shared.less +++ b/styles/less/sheets/actors/actor-sheet-shared.less @@ -37,6 +37,59 @@ color: light-dark(@chat-blue-bg, @beige-50); } + .tab.inventory { + .search-section { + display: flex; + gap: 10px; + align-items: center; + } + .search-bar { + position: relative; + color: light-dark(@dark-blue-50, @beige-50); + width: 100%; + padding-top: 5px; + + input { + border-radius: 50px; + background: light-dark(@dark-blue-10, @golden-10); + border: none; + outline: 2px solid transparent; + transition: all 0.3s ease; + padding: 0 20px; + + &:hover { + outline: 2px solid light-dark(@dark, @golden); + } + + &::-webkit-search-cancel-button { + -webkit-appearance: none; + display: none; + } + } + + .icon { + align-content: center; + height: 32px; + position: absolute; + right: 20px; + font-size: 16px; + z-index: 1; + color: light-dark(@dark-blue-50, @beige-50); + } + } + + .gold-section { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + gap: 10px; + padding: 10px 10px 0; + + .input { + color: light-dark(@dark, @beige); + } + } + } + &.limited { &.character, &.adversary, diff --git a/styles/less/sheets/actors/character/inventory.less b/styles/less/sheets/actors/character/inventory.less index b555aa3d..12f63753 100644 --- a/styles/less/sheets/actors/character/inventory.less +++ b/styles/less/sheets/actors/character/inventory.less @@ -3,47 +3,6 @@ .application.sheet.daggerheart.actor.dh-style.character { .tab.inventory { - .search-section { - display: flex; - gap: 10px; - align-items: center; - - .search-bar { - position: relative; - color: light-dark(@dark-blue-50, @beige-50); - width: 100%; - padding-top: 5px; - - input { - border-radius: 50px; - background: light-dark(@dark-blue-10, @golden-10); - border: none; - outline: 2px solid transparent; - transition: all 0.3s ease; - padding: 0 20px; - - &:hover { - outline: 2px solid light-dark(@dark, @golden); - } - - &::-webkit-search-cancel-button { - -webkit-appearance: none; - display: none; - } - } - - .icon { - align-content: center; - height: 32px; - position: absolute; - right: 20px; - font-size: var(--font-size-16); - z-index: 1; - color: light-dark(@dark-blue-50, @beige-50); - } - } - } - .items-section { display: flex; flex-direction: column; @@ -55,16 +14,5 @@ scrollbar-width: thin; scrollbar-color: light-dark(@dark-blue, @golden) transparent; } - - .currency-section { - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr; - gap: 10px; - padding: 10px 10px 0; - - .input { - color: light-dark(@dark, @beige); - } - } } } diff --git a/styles/less/sheets/actors/character/sheet.less b/styles/less/sheets/actors/character/sheet.less index ee6580fd..68792c99 100644 --- a/styles/less/sheets/actors/character/sheet.less +++ b/styles/less/sheets/actors/character/sheet.less @@ -11,21 +11,6 @@ padding-bottom: 0; overflow-x: auto; - &.viewMode { - button:not(.btn-toggle-view), - input:not(.search), - .controls, - .character-sidebar-sheet, - .img-portait, - .name-row, - .hope-section, - .downtime-section, - .character-traits, - .card-list { - pointer-events: none; - } - } - .character-sidebar-sheet { grid-row: 1 / span 2; grid-column: 1; diff --git a/styles/less/sheets/actors/character/sidebar.less b/styles/less/sheets/actors/character/sidebar.less index e7027163..b159a8e8 100644 --- a/styles/less/sheets/actors/character/sidebar.less +++ b/styles/less/sheets/actors/character/sidebar.less @@ -316,9 +316,9 @@ border-radius: 3px; background: light-dark(@dark-blue, @golden); clip-path: none; - cursor: pointer; display: flex; align-items: center; + justify-content: center; gap: 4px; border: 1px solid transparent; transition: all 0.3s ease; diff --git a/styles/less/sheets/actors/party/inventory.less b/styles/less/sheets/actors/party/inventory.less index 2dcc97d8..ac59e1de 100644 --- a/styles/less/sheets/actors/party/inventory.less +++ b/styles/less/sheets/actors/party/inventory.less @@ -3,51 +3,6 @@ .application.sheet.daggerheart.actor.dh-style.party { .tab.inventory { - .search-section { - display: flex; - gap: 10px; - align-items: center; - - .search-bar { - position: relative; - color: light-dark(@dark-blue-50, @beige-50); - width: 100%; - padding-top: 5px; - - input { - border-radius: 50px; - background: light-dark(@dark-blue-10, @golden-10); - border: none; - outline: 2px solid transparent; - transition: all 0.3s ease; - padding: 0 20px; - - &:hover { - outline: 2px solid light-dark(@dark, @golden); - } - - &:placeholder { - color: light-dark(@dark-blue-50, @beige-50); - } - - &::-webkit-search-cancel-button { - -webkit-appearance: none; - display: none; - } - } - - .icon { - align-content: center; - height: 32px; - position: absolute; - right: 20px; - font-size: 16px; - z-index: 1; - color: light-dark(@dark-blue-50, @beige-50); - } - } - } - .items-section { display: flex; flex-direction: column; @@ -59,16 +14,5 @@ scrollbar-width: thin; scrollbar-color: light-dark(@dark-blue, @golden) transparent; } - - .currency-section { - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr; - gap: 10px; - padding: 10px 10px 0; - - .input { - color: light-dark(@dark, @beige); - } - } } } diff --git a/styles/less/sheets/actors/party/party-members.less b/styles/less/sheets/actors/party/party-members.less index 155fcc36..2e2f4cf8 100644 --- a/styles/less/sheets/actors/party/party-members.less +++ b/styles/less/sheets/actors/party/party-members.less @@ -35,8 +35,8 @@ body.game:is(.performance-low, .noblur) { .actor-img-frame { grid-area: img; - width: 7.5rem; - height: 7.5rem; + width: 7.375rem; + height: 7.375rem; position: relative; .actor-img { @@ -71,6 +71,7 @@ body.game:is(.performance-low, .noblur) { 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; @@ -87,7 +88,7 @@ body.game:is(.performance-low, .noblur) { display: flex; gap: 4px; - background-color: light-dark(transparent, @dark-blue); + background-color: light-dark(var(--color-light-1), @dark-blue); color: light-dark(@dark-blue, @golden); padding: 4px 6px; border: 1px solid light-dark(@dark-blue, @golden); @@ -125,7 +126,7 @@ body.game:is(.performance-low, .noblur) { width: 100%; z-index: 1; font-size: var(--font-size-20); - color: light-dark(@beige, @golden); + color: light-dark(@dark-blue, @golden); font-weight: bold; } diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index db6dceb9..4d627e39 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -624,9 +624,14 @@ display: flex; gap: 5px; margin-top: 8px; + button { height: 32px; flex: 1; + + &.end-button { + flex: 0; + } } } @@ -698,6 +703,11 @@ } } + .action-roll-buttons { + width: 100%; + padding: 0 8px; + } + .description { padding: 8px; diff --git a/styles/less/ui/combat-sidebar/encounter-controls.less b/styles/less/ui/combat-sidebar/encounter-controls.less index 16a8e11a..66f265e0 100644 --- a/styles/less/ui/combat-sidebar/encounter-controls.less +++ b/styles/less/ui/combat-sidebar/encounter-controls.less @@ -10,6 +10,7 @@ .encounter-battlepoints { display: flex; cursor: help; + color: light-dark(@dark, @beige); } .inner-controls { diff --git a/system.json b/system.json index 450c33b2..babdde26 100644 --- a/system.json +++ b/system.json @@ -2,12 +2,15 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.1.1", + "version": "2.1.2", "compatibility": { "minimum": "14.359", "verified": "14.360", "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.1.2/system.zip", "authors": [ { "name": "WBHarry" @@ -295,8 +298,5 @@ }, "background": "systems/daggerheart/assets/logos/FoundrybornBackgroundLogo.png", "primaryTokenAttribute": "resources.hitPoints", - "secondaryTokenAttribute": "resources.stress", - "url": "https://github.com/Foundryborne/daggerheart", - "manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/main/system.json", - "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.1.1/system.zip" + "secondaryTokenAttribute": "resources.stress" } diff --git a/templates/actionTypes/areas.hbs b/templates/actionTypes/areas.hbs new file mode 100644 index 00000000..2e010c72 --- /dev/null +++ b/templates/actionTypes/areas.hbs @@ -0,0 +1,46 @@ +
+ + {{localize "DAGGERHEART.ACTIONS.Config.area.sectionTitle"}} + + + + {{#each source as |area index|}} + {{#unless @first}}{{/unless}} +
+ {{formField ../fields.name value=area.name name=(concat "areas." index ".name") localize=true}} + +
+
+ {{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}} +
+ +
+ {{localize "DAGGERHEART.GENERAL.Effect.plural"}} + +
+
+ {{#each area.effects as |effectId index|}} + + +
+
+ {{#with (@root.getEffectDetails effectId) as | details |}} +
+ +
+
+
{{name}}
+
+ {{/with}} +
+ +
+
+
+ {{/each}} +
+ {{/each}} + +
\ No newline at end of file diff --git a/templates/actionTypes/damage.hbs b/templates/actionTypes/damage.hbs index 192c5be5..454d0413 100644 --- a/templates/actionTypes/damage.hbs +++ b/templates/actionTypes/damage.hbs @@ -21,7 +21,7 @@ {{!-- 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|}} + {{#each source.parts as |dmg key|}}
@@ -31,40 +31,44 @@ {{/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"}} + {{#unless (and @root.source.damage.includeBase (eq key 'hitPoints'))}} + {{#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)}}
- - {{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"}} +
+ {{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}} +
-
- {{/if}} - + {{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}} + + {{else}} + {{localize "DAGGERHEART.ACTIONS.Config.itemDamageIsUsed"}} + {{/unless}}
{{/each}} diff --git a/templates/actionTypes/range-target.hbs b/templates/actionTypes/range-target.hbs index 114c76a6..ec595df4 100644 --- a/templates/actionTypes/range-target.hbs +++ b/templates/actionTypes/range-target.hbs @@ -1,12 +1,14 @@
{{localize "DAGGERHEART.GENERAL.range"}}{{#if fields.target}} & {{localize "DAGGERHEART.GENERAL.Target.single"}}{{/if}} - {{formField fields.range value=source.range label=(localize "DAGGERHEART.GENERAL.range") name=(concat path "range") localize=true}} {{#if fields.target}} -
- {{#if (and source.target.type (not (eq source.target.type 'self')))}} - {{ formField fields.target.amount value=source.target.amount label=(localize "DAGGERHEART.GENERAL.amount") name=(concat path "target.amount") localize=true}} - {{/if}} - {{ formField fields.target.type value=source.target.type label=(localize "DAGGERHEART.GENERAL.Target.single") name=(concat path "target.type") localize=true }} -
+
+ {{formField fields.range value=source.range label=(localize "DAGGERHEART.GENERAL.range") name=(concat path "range") localize=true}} + {{#if (and source.target.type (not (eq source.target.type 'self')))}} + {{ formField fields.target.amount value=source.target.amount label=(localize "DAGGERHEART.GENERAL.amount") name=(concat path "target.amount") localize=true}} + {{/if}} + {{ formField fields.target.type value=source.target.type label=(localize "DAGGERHEART.GENERAL.Target.single") name=(concat path "target.type") localize=true }} +
+ {{else}} + {{formField fields.range value=source.range label=(localize "DAGGERHEART.GENERAL.range") name=(concat path "range") localize=true}} {{/if}}
\ No newline at end of file diff --git a/templates/actionTypes/roll.hbs b/templates/actionTypes/roll.hbs index 9784fc08..41f88ba2 100644 --- a/templates/actionTypes/roll.hbs +++ b/templates/actionTypes/roll.hbs @@ -1,7 +1,7 @@
- Roll - {{#if @root.hasBaseDamage}}{{formInput fields.useDefault name="roll.useDefault" value=source.useDefault dataset=(object tooltip="Use default Item values" tooltipDirection="UP")}}{{/if}} + {{localize "DAGGERHEART.GENERAL.roll"}} + {{#if @root.hasBaseDamage}}{{formInput fields.useDefault name="roll.useDefault" value=source.useDefault dataset=(object tooltip=(localize "DAGGERHEART.ACTIONS.Config.useDefaultItemValues") tooltipDirection="UP")}}{{/if}} {{formField fields.type label="DAGGERHEART.GENERAL.type" name="roll.type" value=source.type localize=true choices=@root.getRollTypeOptions localize=true}} diff --git a/templates/characterCreation/footer.hbs b/templates/characterCreation/footer.hbs index 95b86cfb..51eef110 100644 --- a/templates/characterCreation/footer.hbs +++ b/templates/characterCreation/footer.hbs @@ -1,8 +1,8 @@ \ No newline at end of file diff --git a/templates/characterCreation/tabs/experience.hbs b/templates/characterCreation/tabs/experience.hbs index 3eb92834..66363084 100644 --- a/templates/characterCreation/tabs/experience.hbs +++ b/templates/characterCreation/tabs/experience.hbs @@ -4,17 +4,25 @@ data-group='{{tabs.experience.group}}' >
-
+
{{localize "DAGGERHEART.APPLICATIONS.CharacterCreation.initialExperiences"}} {{experience.nrSelected}}/{{experience.nrTotal}}
{{#each experience.values as |experience id|}} -
-
- - {{numberFormat this.value sign=true}} +
+
+ +
+ + {{numberFormat this.value sign=true}} +
- +
+ +
+ +
+
{{/each}}
diff --git a/templates/dialogs/characterReset.hbs b/templates/dialogs/characterReset.hbs index 298826e5..0bd54f7c 100644 --- a/templates/dialogs/characterReset.hbs +++ b/templates/dialogs/characterReset.hbs @@ -28,6 +28,6 @@
- +
\ No newline at end of file diff --git a/templates/dialogs/compendiumBrowserSettingsDialog/footer.hbs b/templates/dialogs/compendiumBrowserSettingsDialog/footer.hbs index 9dc61cbe..d9bb378e 100644 --- a/templates/dialogs/compendiumBrowserSettingsDialog/footer.hbs +++ b/templates/dialogs/compendiumBrowserSettingsDialog/footer.hbs @@ -1,3 +1,3 @@ \ No newline at end of file diff --git a/templates/dialogs/deathMove.hbs b/templates/dialogs/deathMove.hbs index 341659df..97900022 100644 --- a/templates/dialogs/deathMove.hbs +++ b/templates/dialogs/deathMove.hbs @@ -17,7 +17,7 @@
{{/if}} {{/unless}} diff --git a/templates/dialogs/downtime/downtime.hbs b/templates/dialogs/downtime/downtime.hbs index 9744ffea..edaa81c1 100644 --- a/templates/dialogs/downtime/downtime.hbs +++ b/templates/dialogs/downtime/downtime.hbs @@ -28,7 +28,7 @@ \ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/footer.hbs b/templates/dialogs/groupRollDialog/footer.hbs index cb041247..e401966b 100644 --- a/templates/dialogs/groupRollDialog/footer.hbs +++ b/templates/dialogs/groupRollDialog/footer.hbs @@ -1,6 +1,6 @@
- +
\ No newline at end of file diff --git a/templates/dialogs/image-select/footer.hbs b/templates/dialogs/image-select/footer.hbs index cd7d3d1a..58a60cc4 100644 --- a/templates/dialogs/image-select/footer.hbs +++ b/templates/dialogs/image-select/footer.hbs @@ -1,4 +1,4 @@ \ No newline at end of file diff --git a/templates/dialogs/item-transfer.hbs b/templates/dialogs/item-transfer.hbs index 0e7df3dc..63972ed8 100644 --- a/templates/dialogs/item-transfer.hbs +++ b/templates/dialogs/item-transfer.hbs @@ -14,7 +14,7 @@
- +
diff --git a/templates/dialogs/multiclassChoice.hbs b/templates/dialogs/multiclassChoice.hbs index 3c89ff1a..55365939 100644 --- a/templates/dialogs/multiclassChoice.hbs +++ b/templates/dialogs/multiclassChoice.hbs @@ -16,7 +16,7 @@ diff --git a/templates/levelup/tabs/footer.hbs b/templates/levelup/tabs/footer.hbs index 2ee7a316..d487e657 100644 --- a/templates/levelup/tabs/footer.hbs +++ b/templates/levelup/tabs/footer.hbs @@ -20,7 +20,7 @@ {{/if}} {{#unless levelupAuto}} {{/unless}} diff --git a/templates/settings/automation-settings/footer.hbs b/templates/settings/automation-settings/footer.hbs index 54939c17..14ff5bb5 100644 --- a/templates/settings/automation-settings/footer.hbs +++ b/templates/settings/automation-settings/footer.hbs @@ -1,10 +1,10 @@ \ No newline at end of file diff --git a/templates/settings/downtime-config/actions.hbs b/templates/settings/downtime-config/actions.hbs index d197f983..feb05302 100644 --- a/templates/settings/downtime-config/actions.hbs +++ b/templates/settings/downtime-config/actions.hbs @@ -8,7 +8,7 @@
{{#each move.actions as |action|}} - {{> "systems/daggerheart/templates/settings/components/settings-item-line.hbs" id=action.id }} + {{> "systems/daggerheart/templates/settings/components/settings-item-line.hbs" id=action.id type="action" }} {{/each}}
diff --git a/templates/settings/downtime-config/footer.hbs b/templates/settings/downtime-config/footer.hbs index 5e5f31dd..199aea15 100644 --- a/templates/settings/downtime-config/footer.hbs +++ b/templates/settings/downtime-config/footer.hbs @@ -1,4 +1,4 @@ \ No newline at end of file diff --git a/templates/settings/homebrew-settings/footer.hbs b/templates/settings/homebrew-settings/footer.hbs index 954572de..fc84fde7 100644 --- a/templates/settings/homebrew-settings/footer.hbs +++ b/templates/settings/homebrew-settings/footer.hbs @@ -1,10 +1,10 @@ \ No newline at end of file diff --git a/templates/settings/metagaming-settings/footer.hbs b/templates/settings/metagaming-settings/footer.hbs index 54939c17..14ff5bb5 100644 --- a/templates/settings/metagaming-settings/footer.hbs +++ b/templates/settings/metagaming-settings/footer.hbs @@ -1,10 +1,10 @@ \ No newline at end of file diff --git a/templates/settings/variant-rules.hbs b/templates/settings/variant-rules.hbs index df7accb3..cdaef024 100644 --- a/templates/settings/variant-rules.hbs +++ b/templates/settings/variant-rules.hbs @@ -32,11 +32,11 @@ diff --git a/templates/sheets-settings/action-settings/configuration.hbs b/templates/sheets-settings/action-settings/configuration.hbs index 5bd29e39..8df528c9 100644 --- a/templates/sheets-settings/action-settings/configuration.hbs +++ b/templates/sheets-settings/action-settings/configuration.hbs @@ -6,4 +6,5 @@ {{> 'systems/daggerheart/templates/actionTypes/uses.hbs' fields=fields.uses.fields source=source.uses}} {{> 'systems/daggerheart/templates/actionTypes/cost.hbs' fields=fields.cost.element.fields source=source.cost costOptions=costOptions}} {{> 'systems/daggerheart/templates/actionTypes/range-target.hbs' fields=(object range=fields.range target=fields.target.fields) source=(object target=source.target range=source.range)}} + {{> 'systems/daggerheart/templates/actionTypes/areas.hbs' fields=fields.areas.element.fields source=source.areas}} \ No newline at end of file diff --git a/templates/sheets/activeEffect/details.hbs b/templates/sheets/activeEffect/details.hbs index f7e465bd..dc19b3dc 100644 --- a/templates/sheets/activeEffect/details.hbs +++ b/templates/sheets/activeEffect/details.hbs @@ -2,6 +2,7 @@ {{formGroup fields.tint value=source.tint rootId=rootId placeholder="#ffffff"}} {{formGroup fields.description value=source.description rootId=rootId}} {{formGroup fields.disabled value=source.disabled rootId=rootId}} + {{formGroup systemFields.targetDispositions value=source.system.targetDispositions name=(concat "system.targetDispositions") localize=true}} {{#if isActorEffect}}
diff --git a/templates/sheets/activeEffect/settings.hbs b/templates/sheets/activeEffect/settings.hbs index 9307ff65..09b78856 100644 --- a/templates/sheets/activeEffect/settings.hbs +++ b/templates/sheets/activeEffect/settings.hbs @@ -26,11 +26,11 @@ {{formGroup systemFields.duration.fields.type value=source.system.duration.type localize=true }} -
-
- {{formInput systemFields.duration.fields.description value=source.system.duration.description localize=true }} -
+
+
+ {{formInput systemFields.duration.fields.description value=source.system.duration.description localize=true }}
+
{{formGroup fields.start.fields.time value=source.start.time localize=true }} diff --git a/templates/sheets/actors/adversary/effects.hbs b/templates/sheets/actors/adversary/effects.hbs index cefb6e57..087e8b30 100644 --- a/templates/sheets/actors/adversary/effects.hbs +++ b/templates/sheets/actors/adversary/effects.hbs @@ -6,7 +6,7 @@ type='effect' isGlassy=true collection=effects.actives - canCreate=true + canCreate=@root.editable hideResources=true }} @@ -15,7 +15,7 @@ type='effect' isGlassy=true collection=effects.inactives - canCreate=true + canCreate=@root.editable hideResources=true }}
diff --git a/templates/sheets/actors/adversary/features.hbs b/templates/sheets/actors/adversary/features.hbs index a24342fc..d320b0d8 100644 --- a/templates/sheets/actors/adversary/features.hbs +++ b/templates/sheets/actors/adversary/features.hbs @@ -6,8 +6,8 @@ type='feature' collection=@root.features hideContextMenu=true - canCreate=true - showActions=true + canCreate=@root.editable + showActions=@root.editable }}
\ No newline at end of file diff --git a/templates/sheets/actors/character/effects.hbs b/templates/sheets/actors/character/effects.hbs index 3355d575..a2e5a420 100644 --- a/templates/sheets/actors/character/effects.hbs +++ b/templates/sheets/actors/character/effects.hbs @@ -7,7 +7,7 @@ type='effect' isGlassy=true collection=effects.actives - canCreate=true + canCreate=@root.editable hideResources=true }} @@ -16,7 +16,7 @@ type='effect' isGlassy=true collection=effects.inactives - canCreate=true + canCreate=@root.editable hideResources=true disabled=true }} diff --git a/templates/sheets/actors/character/features.hbs b/templates/sheets/actors/character/features.hbs index 3e942468..70544683 100644 --- a/templates/sheets/actors/character/features.hbs +++ b/templates/sheets/actors/character/features.hbs @@ -8,8 +8,8 @@ type='feature' actorType='character' collection=category.values - canCreate=true - showActions=true + canCreate=@root.editable + showActions=@root.editable }} {{else if category.values}} {{> 'daggerheart.inventory-items' @@ -18,7 +18,7 @@ actorType='character' collection=category.values canCreate=false - showActions=true + showActions=@root.editable }} {{/if}} diff --git a/templates/sheets/actors/character/header.hbs b/templates/sheets/actors/character/header.hbs index 4ceba54d..a75b2c2f 100644 --- a/templates/sheets/actors/character/header.hbs +++ b/templates/sheets/actors/character/header.hbs @@ -4,22 +4,24 @@

{{source.name}}

- {{#if document.system.needsCharacterSetup}} - - {{else if document.system.levelData.canLevelUp}} - + {{#if @root.editable}} + {{#if document.system.needsCharacterSetup}} + + {{else if document.system.levelData.canLevelUp}} + + {{/if}} {{/if}} {{#unless document.system.needsCharacterSetup}} {{localize 'DAGGERHEART.GENERAL.level'}} @@ -110,12 +112,14 @@ {{/if}} - - + {{#if @root.editable}} + + + {{/if}}

diff --git a/templates/sheets/actors/character/inventory.hbs b/templates/sheets/actors/character/inventory.hbs index a05fed35..c3ddb0ad 100644 --- a/templates/sheets/actors/character/inventory.hbs +++ b/templates/sheets/actors/character/inventory.hbs @@ -5,7 +5,7 @@
- + @@ -13,18 +13,7 @@ {{#if this.inventory.hasCurrency}} -
- {{#each this.inventory.currencies as |currency key|}} - {{#if currency.enabled}} -
- - {{localize currency.label}} - - -
- {{/if}} - {{/each}} -
+ {{> "systems/daggerheart/templates/sheets/global/partials/gold.hbs" currencies=inventory.currencies}} {{/if}}
@@ -33,7 +22,7 @@ type='weapon' collection=@root.inventory.weapons isGlassy=true - canCreate=true + canCreate=@root.editable hideResources=true }} {{> 'daggerheart.inventory-items' @@ -41,7 +30,7 @@ type='armor' collection=@root.inventory.armor isGlassy=true - canCreate=true + canCreate=@root.editable hideResources=true }} {{> 'daggerheart.inventory-items' @@ -49,15 +38,17 @@ type='consumable' collection=@root.inventory.consumables isGlassy=true - canCreate=true + canCreate=@root.editable + isQuantifiable=true }} {{> 'daggerheart.inventory-items' title='TYPES.Item.loot' type='loot' collection=@root.inventory.loot isGlassy=true - canCreate=true - showActions=true + canCreate=@root.editable + showActions=@root.editable + isQuantifiable=true }}
\ No newline at end of file diff --git a/templates/sheets/actors/character/loadout.hbs b/templates/sheets/actors/character/loadout.hbs index 0319d56f..9ba3fb04 100644 --- a/templates/sheets/actors/character/loadout.hbs +++ b/templates/sheets/actors/character/loadout.hbs @@ -5,7 +5,7 @@
- +
@@ -27,7 +27,7 @@ isGlassy=true cardView=cardView collection=document.system.domainCards.loadout - canCreate=true + canCreate=@root.editable }} {{> 'daggerheart.inventory-items' title='DAGGERHEART.GENERAL.Tabs.vault' @@ -35,7 +35,7 @@ isGlassy=true cardView=cardView collection=document.system.domainCards.vault - canCreate=true + canCreate=@root.editable inVault=true }} diff --git a/templates/sheets/actors/character/sidebar.hbs b/templates/sheets/actors/character/sidebar.hbs index d3be4983..0142ac1d 100644 --- a/templates/sheets/actors/character/sidebar.hbs +++ b/templates/sheets/actors/character/sidebar.hbs @@ -45,11 +45,11 @@ {{/times}} - + {{localize "DAGGERHEART.GENERAL.armorSlots"}}
{{document.system.armorScore.value}} / {{document.system.armorScore.max}} - + {{#if @root.editable}}{{/if}}
@@ -64,9 +64,9 @@ value='{{document.system.armorScore.value}}' max='{{document.system.armorScore.max}}' > - +

{{localize "DAGGERHEART.GENERAL.armorSlots"}}

- + {{#if @root.editable}}{{/if}}
{{/if}} diff --git a/templates/sheets/actors/companion/effects.hbs b/templates/sheets/actors/companion/effects.hbs index cefb6e57..087e8b30 100644 --- a/templates/sheets/actors/companion/effects.hbs +++ b/templates/sheets/actors/companion/effects.hbs @@ -6,7 +6,7 @@ type='effect' isGlassy=true collection=effects.actives - canCreate=true + canCreate=@root.editable hideResources=true }} @@ -15,7 +15,7 @@ type='effect' isGlassy=true collection=effects.inactives - canCreate=true + canCreate=@root.editable hideResources=true }} diff --git a/templates/sheets/actors/environment/features.hbs b/templates/sheets/actors/environment/features.hbs index 3ad36023..3fd512da 100644 --- a/templates/sheets/actors/environment/features.hbs +++ b/templates/sheets/actors/environment/features.hbs @@ -9,8 +9,8 @@ type='feature' collection=@root.features hideContextMenu=true - canCreate=true - showActions=true + canCreate=@root.editable + showActions=@root.editable }} \ No newline at end of file diff --git a/templates/sheets/actors/party/inventory.hbs b/templates/sheets/actors/party/inventory.hbs index 92371b8d..cf056608 100644 --- a/templates/sheets/actors/party/inventory.hbs +++ b/templates/sheets/actors/party/inventory.hbs @@ -5,7 +5,7 @@
- + @@ -16,18 +16,7 @@ {{#if inventory.hasCurrency}} -
- {{#each this.inventory.currencies as |currency key|}} - {{#if currency.enabled}} -
- - {{localize currency.label}} - - -
- {{/if}} - {{/each}} -
+ {{> "systems/daggerheart/templates/sheets/global/partials/gold.hbs" currencies=inventory.currencies}} {{/if}}
@@ -37,9 +26,10 @@ actorType='party' collection=@root.inventory.weapons isGlassy=true - canCreate=true + canCreate=@root.editable hideResources=true hideContextMenu=true + isQuantifiable=true }} {{> 'daggerheart.inventory-items' title='TYPES.Item.armor' @@ -47,9 +37,10 @@ actorType='party' collection=@root.inventory.armor isGlassy=true - canCreate=true + canCreate=@root.editable hideResources=true hideContextMenu=true + isQuantifiable=true }} {{> 'daggerheart.inventory-items' title='TYPES.Item.consumable' @@ -57,8 +48,9 @@ actorType='party' collection=@root.inventory.consumables isGlassy=true - canCreate=true + canCreate=@root.editable hideContextMenu=true + isQuantifiable=true }} {{> 'daggerheart.inventory-items' title='TYPES.Item.loot' @@ -66,8 +58,9 @@ actorType='party' collection=@root.inventory.loot isGlassy=true - canCreate=true + canCreate=@root.editable hideContextMenu=true + isQuantifiable=true }}
\ No newline at end of file diff --git a/templates/sheets/actors/party/party-members.hbs b/templates/sheets/actors/party/party-members.hbs index bc0c6672..aa41aeaa 100644 --- a/templates/sheets/actors/party/party-members.hbs +++ b/templates/sheets/actors/party/party-members.hbs @@ -7,11 +7,11 @@
{{/if}} - {{!-- {{#if action.cost.value}}
{{action.cost.value}} {{action.cost.type}}
{{/if}} --}} {{/each}}
\ No newline at end of file diff --git a/templates/ui/chat/action.hbs b/templates/ui/chat/action.hbs index 2854795c..51840363 100644 --- a/templates/ui/chat/action.hbs +++ b/templates/ui/chat/action.hbs @@ -26,4 +26,9 @@ {{/if}} + {{#if action.areas.length}} +
+ +
+ {{/if}} \ No newline at end of file diff --git a/templates/ui/chat/parts/button-part.hbs b/templates/ui/chat/parts/button-part.hbs index 21317939..6bc5f372 100644 --- a/templates/ui/chat/parts/button-part.hbs +++ b/templates/ui/chat/parts/button-part.hbs @@ -1,4 +1,5 @@
+ {{#if areas.length}}{{/if}} {{#if hasDamage}} {{#unless (empty damage)}} diff --git a/templates/ui/chat/parts/target-part.hbs b/templates/ui/chat/parts/target-part.hbs index 9a545926..88d337ac 100644 --- a/templates/ui/chat/parts/target-part.hbs +++ b/templates/ui/chat/parts/target-part.hbs @@ -24,7 +24,7 @@
{{/if}} - {{#if (and hasSave currentTargets.length)}}
Reaction Roll All Targets
{{/if}} + {{#if (and hasSave currentTargets.length)}}
{{localize "DAGGERHEART.UI.Chat.saveRoll.reactionRollAllTargets"}}
{{/if}} {{#each currentTargets}}
diff --git a/templates/ui/itemBrowser/itemBrowser.hbs b/templates/ui/itemBrowser/itemBrowser.hbs index 137693fc..d4946c1f 100644 --- a/templates/ui/itemBrowser/itemBrowser.hbs +++ b/templates/ui/itemBrowser/itemBrowser.hbs @@ -1,14 +1,14 @@
{{#if menu.path.length }}
@@ -17,7 +17,7 @@
- +
diff --git a/templates/ui/sidebar/actor-document-partial.hbs b/templates/ui/sidebar/actor-document-partial.hbs index ec261f85..2a9f47fa 100644 --- a/templates/ui/sidebar/actor-document-partial.hbs +++ b/templates/ui/sidebar/actor-document-partial.hbs @@ -14,6 +14,10 @@ {{else}} {{localize "DAGGERHEART.UI.Sidebar.actorDirectory.companionNoPartner"}} {{/if}} + {{else if (eq type "party")}} + {{#if system.active}} + {{localize "DAGGERHEART.UI.Sidebar.actorDirectory.partyIsActive"}} + {{/if}} {{/if}} diff --git a/templates/ui/tooltip/action.hbs b/templates/ui/tooltip/action.hbs index 29d44dde..959188f3 100644 --- a/templates/ui/tooltip/action.hbs +++ b/templates/ui/tooltip/action.hbs @@ -16,7 +16,7 @@ {{#if (gt item.cost.length 0)}} {{#each item.cost as | cost |}}
- {{localize "Type"}} {{#with (lookup @root.config.GENERAL.abilityCosts cost.type) as | type |}}{{localize type.label}}{{/with}} + {{localize "DAGGERHEART.GENERAL.type"}} {{#with (lookup @root.config.GENERAL.abilityCosts cost.type) as | type |}}{{localize type.label}}{{/with}}
{{localize "DAGGERHEART.GENERAL.value"}} {{cost.value}} diff --git a/templates/ui/tooltip/adversary.hbs b/templates/ui/tooltip/adversary.hbs index bba7e696..f96fe2a0 100644 --- a/templates/ui/tooltip/adversary.hbs +++ b/templates/ui/tooltip/adversary.hbs @@ -11,7 +11,7 @@ {{/with}}
- + {{#with (lookup adversaryTypes item.system.type) as | type |}}
{{localize type.label}}
{{/with}} diff --git a/templates/ui/tooltip/battlepoints.hbs b/templates/ui/tooltip/battlepoints.hbs index d793fe8c..f2f42f53 100644 --- a/templates/ui/tooltip/battlepoints.hbs +++ b/templates/ui/tooltip/battlepoints.hbs @@ -1,15 +1,15 @@
-

{{localize "Adversaries"}} ({{currentBP}}/{{maxBP}})

+

{{localize "DAGGERHEART.GENERAL.Adversary.plural"}} ({{currentBP}}/{{maxBP}})

{{#each categories as |category key|}} {{#each category as |grouping index|}}
{{#if grouping.nr}} - + {{else}} - + {{/if}}
{{/each}} @@ -17,7 +17,7 @@
-

{{localize "Modifiers"}}

+

{{localize "DAGGERHEART.GENERAL.Modifier.plural"}}

{{#each toggles as |toggle|}}
@@ -26,7 +26,7 @@ {{else}} {{/if}} - +
{{/each}}
diff --git a/templates/ui/tooltip/weapon.hbs b/templates/ui/tooltip/weapon.hbs index a672c883..4adb9c46 100644 --- a/templates/ui/tooltip/weapon.hbs +++ b/templates/ui/tooltip/weapon.hbs @@ -3,7 +3,7 @@

{{item.name}}

- {{#if item.system.secondary}}{{localize "DAGGERHEART.ITEMS.Weapon.secondaryWeapon"}}{{else}}{{localize "DAGGERHEART.ITEMS.Weapon.primaryWeapon"}}{{/if}} + {{#if item.system.secondary}}{{localize "DAGGERHEART.ITEMS.Weapon.secondaryWeapon.full"}}{{else}}{{localize "DAGGERHEART.ITEMS.Weapon.primaryWeapon.full"}}{{/if}}
{{#with (lookup config.GENERAL.burden item.system.burden) as | burden |}} diff --git a/tools/pullYMLtoLDB.mjs b/tools/pullYMLtoLDB.mjs index 2326d94a..52b7db94 100644 --- a/tools/pullYMLtoLDB.mjs +++ b/tools/pullYMLtoLDB.mjs @@ -1,12 +1,12 @@ import { compilePack } from '@foundryvtt/foundryvtt-cli'; import readline from 'node:readline/promises'; import { promises as fs } from 'fs'; -import systemJSON from "../system.json" with { type: "json" }; +import systemJSON from '../system.json' with { type: 'json' }; const MODULE_ID = process.cwd(); const answer = await (async () => { - if (process.argv.includes("--build")) return "overwrite"; + if (process.argv.includes('--build')) return 'overwrite'; const rl = readline.createInterface({ input: process.stdin, @@ -42,8 +42,8 @@ async function pullToLDB() { function transformEntry(entry) { const stats = { coreVersion: systemJSON.compatibility.minimum, - systemId: "daggerheart", - systemVersion: systemJSON.version, + systemId: 'daggerheart', + systemVersion: systemJSON.version }; entry._stats = { ...stats }; diff --git a/tools/pushLDBtoYML.mjs b/tools/pushLDBtoYML.mjs index a113caec..99f84fd7 100644 --- a/tools/pushLDBtoYML.mjs +++ b/tools/pushLDBtoYML.mjs @@ -23,7 +23,7 @@ for (const pack of packs) { await extractPack(`${MODULE_ID}/${pack}`, `${MODULE_ID}/src/${pack}`, { yaml, transformName, - transformEntry, + transformEntry }); } /** @@ -45,12 +45,12 @@ function transformEntry(entry) { delete entry._stats; for (const effect of entry.effects ?? []) { - effect._stats = prune(effect._stats) + effect._stats = prune(effect._stats); } for (const item of entry.items ?? []) { item._stats = prune(item._stats); for (const effect of item.effects ?? []) { - effect._stats = prune(effect._stats) + effect._stats = prune(effect._stats); } } }