{ "folder": "SwEjiVLbnXT2x9Lz", "name": "Strange Patterns", "type": "feature", "_id": "6YsfFjmCGuFYVhT4", "img": "icons/magic/symbols/rune-sigil-black-pink.webp", "system": { "description": "

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

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

", "resource": { "type": "diceValue", "value": 1, "max": "1", "icon": "fa-solid fa-hashtag", "dieFaces": "d12" }, "actions": { "RkqPzF1bdWzPPMml": { "type": "healing", "_id": "RkqPzF1bdWzPPMml", "systemPath": "actions", "description": "

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

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

", "chatDisplay": true, "actionType": "action", "cost": [], "uses": { "value": null, "max": "", "recovery": null, "consumeOnSuccess": false }, "damage": { "parts": [ { "value": { "custom": { "enabled": true, "formula": "1" }, "multiplier": "prof", "flatMultiplier": 1, "dice": "d6", "bonus": null }, "applyTo": "stress", "base": false, "resultBased": false, "valueAlt": { "multiplier": "prof", "flatMultiplier": 1, "dice": "d6", "bonus": null, "custom": { "enabled": false } }, "type": [] } ], "includeBase": false }, "target": { "type": "any", "amount": null }, "effects": [], "roll": { "type": null, "trait": null, "difficulty": null, "bonus": null, "advState": "neutral", "diceRolling": { "multiplier": "prof", "flatMultiplier": 1, "dice": "d6", "compare": null, "treshold": null }, "useDefault": false }, "name": "Clear Stress", "img": "icons/magic/symbols/rune-sigil-black-pink.webp", "range": "", "triggers": [ { "trigger": "dualityRoll", "triggeringActorType": "self", "command": "/* Ignore if it's a TagTeam roll */\nconst tagTeam = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.TagTeamRoll);\nif (tagTeam.members[actor.id]) return;\n\n/* Check if there's a Strange Pattern match */\nconst dice = [roll.dFear.total, roll.dHope.total];\nconst resource = this.parent.resource?.diceStates ? Object.values(this.parent.resource.diceStates).map(x => x.value)[0] : null;\nconst nrMatches = dice.filter(x => x === resource).length;\n\nif (!nrMatches) return;\n\n/* Create a dialog to choose Hope or Stress - or to cancel*/\nconst content = `\n
${game.i18n.format('DAGGERHEART.CONFIG.Triggers.triggerTexts.strangePatternsContentTitle', { nr: nrMatches })}
\n
${game.i18n.format('DAGGERHEART.CONFIG.Triggers.triggerTexts.strangePatternsContentSubTitle', { nr: nrMatches })}
\n
${game.i18n.localize('DAGGERHEART.CONFIG.Triggers.triggerTexts.strangePatternsActionExplanation')}
\n
\n \n \n
\n
`;\n\nconst result = await foundry.applications.api.DialogV2.input({\n classes: ['dh-style', 'two-big-buttons'],\n window: { title: this.item.name },\n content: content,\n render: (_, dialog) => {\n const hopeButton = dialog.element.querySelector('#hopeButton');\n const stressButton = dialog.element.querySelector('#stressButton');\ndialog.element.querySelector('button[type=\"submit\"]').disabled = true;\n \n const updateFunc = (event, selector, adding, clamp) => {\n const button = event.target.closest(`#${selector}Button`);\n const parent = event.target.closest('.flexrow');\n const hope = Number.parseInt(parent.querySelector('#hopeButton label').innerHTML);\n const stress = Number.parseInt(parent.querySelector('#stressButton label').innerHTML);\n const currentTotal = (Number.isNumeric(hope) ? hope : 0) + (Number.isNumeric(stress) ? stress : 0);\n if (adding && currentTotal === nrMatches) return;\n \n const current = Number.parseInt(button.querySelector('label').innerHTML);\n if (!adding && current === 0) return;\n \n const value = Number.isNumeric(current) ? adding ? current+1 : current-1 : 1;\n if (!dialog.data) dialog.data = {};\n dialog.data[selector] = clamp(value);\n button.querySelector('label').innerHTML = dialog.data[selector];\n\n event.target.closest('.dialog-form').querySelector('button[type=\"submit\"]').disabled = !adding || currentTotal < (nrMatches-1);\n \n };\n hopeButton.addEventListener('click', event => updateFunc(event, 'hope', true, x => Math.min(x, nrMatches)));\n hopeButton.addEventListener('contextmenu', event => updateFunc(event, 'hope', false, x => Math.max(x, 0)));\n stressButton.addEventListener('click', event => updateFunc(event, 'stress', true, x => Math.min(x, nrMatches)));\n stressButton.addEventListener('contextmenu', event => updateFunc(event, 'stress', false, x => Math.max(x, 0)));\n },\n ok: { callback: (_event, _result, dialog) => {\n const hope = dialog.data.hope ?? 0;\n const stress = dialog.data.stress ?? 0;\n if (!hope && !stress) return;\n\n /* Return resource update according to choices */\n const hopeUpdate = hope ? { key: 'hope', value: hope, total: -hope, enabled: true } : null;\n const stressUpdate = stress ? { key: 'stress', value: -stress, total: stress, enabled: true } : null;\n return { updates: [hopeUpdate, stressUpdate].filter(x => x) };\n }}\n});\n\nreturn result;" } ] } }, "originItemType": null, "originId": null, "attribution": { "source": "Daggerheart SRD", "page": 25, "artist": "" } }, "effects": [], "sort": 0, "ownership": { "default": 0, "MQSznptE5yLT7kj8": 3 }, "flags": {}, "_key": "!items!6YsfFjmCGuFYVhT4" }