mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
Merge f47cbb41e8 into 0b343c9f52
This commit is contained in:
commit
6c67e22e48
46 changed files with 933 additions and 338 deletions
|
|
@ -2,6 +2,7 @@ import { SYSTEM } from './module/config/system.mjs';
|
||||||
import * as applications from './module/applications/_module.mjs';
|
import * as applications from './module/applications/_module.mjs';
|
||||||
import * as data from './module/data/_module.mjs';
|
import * as data from './module/data/_module.mjs';
|
||||||
import * as models from './module/data/_module.mjs';
|
import * as models from './module/data/_module.mjs';
|
||||||
|
import * as canvas from './module/canvas/_module.mjs';
|
||||||
import * as documents from './module/documents/_module.mjs';
|
import * as documents from './module/documents/_module.mjs';
|
||||||
import * as dice from './module/dice/_module.mjs';
|
import * as dice from './module/dice/_module.mjs';
|
||||||
import * as fields from './module/data/fields/_module.mjs';
|
import * as fields from './module/data/fields/_module.mjs';
|
||||||
|
|
@ -19,6 +20,7 @@ import {
|
||||||
import { placeables } from './module/canvas/_module.mjs';
|
import { placeables } from './module/canvas/_module.mjs';
|
||||||
import './node_modules/@yaireo/tagify/dist/tagify.css';
|
import './node_modules/@yaireo/tagify/dist/tagify.css';
|
||||||
import TemplateManager from './module/documents/templateManager.mjs';
|
import TemplateManager from './module/documents/templateManager.mjs';
|
||||||
|
import TokenManager from './module/documents/tokenManager.mjs';
|
||||||
|
|
||||||
CONFIG.DH = SYSTEM;
|
CONFIG.DH = SYSTEM;
|
||||||
CONFIG.TextEditor.enrichers.push(...enricherConfig);
|
CONFIG.TextEditor.enrichers.push(...enricherConfig);
|
||||||
|
|
@ -51,6 +53,8 @@ CONFIG.ChatMessage.template = 'systems/daggerheart/templates/ui/chat/chat-messag
|
||||||
|
|
||||||
CONFIG.Canvas.rulerClass = placeables.DhRuler;
|
CONFIG.Canvas.rulerClass = placeables.DhRuler;
|
||||||
CONFIG.Canvas.layers.templates.layerClass = placeables.DhTemplateLayer;
|
CONFIG.Canvas.layers.templates.layerClass = placeables.DhTemplateLayer;
|
||||||
|
CONFIG.Canvas.layers.tokens.layerClass = canvas.DhTokenLayer;
|
||||||
|
|
||||||
CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate;
|
CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate;
|
||||||
|
|
||||||
CONFIG.Scene.documentClass = documents.DhScene;
|
CONFIG.Scene.documentClass = documents.DhScene;
|
||||||
|
|
@ -73,6 +77,7 @@ CONFIG.ui.countdowns = applications.ui.DhCountdowns;
|
||||||
CONFIG.ux.ContextMenu = applications.ux.DHContextMenu;
|
CONFIG.ux.ContextMenu = applications.ux.DHContextMenu;
|
||||||
CONFIG.ux.TooltipManager = documents.DhTooltipManager;
|
CONFIG.ux.TooltipManager = documents.DhTooltipManager;
|
||||||
CONFIG.ux.TemplateManager = new TemplateManager();
|
CONFIG.ux.TemplateManager = new TemplateManager();
|
||||||
|
CONFIG.ux.TokenManager = new TokenManager();
|
||||||
|
|
||||||
Hooks.once('init', () => {
|
Hooks.once('init', () => {
|
||||||
game.system.api = {
|
game.system.api = {
|
||||||
|
|
|
||||||
16
lang/en.json
16
lang/en.json
|
|
@ -69,7 +69,11 @@
|
||||||
},
|
},
|
||||||
"summon": {
|
"summon": {
|
||||||
"name": "Summon",
|
"name": "Summon",
|
||||||
"tooltip": "Create tokens in the scene."
|
"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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Config": {
|
"Config": {
|
||||||
|
|
@ -120,6 +124,9 @@
|
||||||
},
|
},
|
||||||
"cost": {
|
"cost": {
|
||||||
"stepTooltip": "+{step} per step"
|
"stepTooltip": "+{step} per step"
|
||||||
|
},
|
||||||
|
"summon": {
|
||||||
|
"dropSummonsHere": "Drop Summons Here"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -2179,6 +2186,10 @@
|
||||||
"stress": "Stress",
|
"stress": "Stress",
|
||||||
"subclasses": "Subclasses",
|
"subclasses": "Subclasses",
|
||||||
"success": "Success",
|
"success": "Success",
|
||||||
|
"summon": {
|
||||||
|
"single": "Summon",
|
||||||
|
"plural": "Summons"
|
||||||
|
},
|
||||||
"take": "Take",
|
"take": "Take",
|
||||||
"Target": {
|
"Target": {
|
||||||
"single": "Target",
|
"single": "Target",
|
||||||
|
|
@ -2828,7 +2839,8 @@
|
||||||
"deleteItem": "Delete Item",
|
"deleteItem": "Delete Item",
|
||||||
"immune": "Immune",
|
"immune": "Immune",
|
||||||
"middleClick": "[Middle Click] Keep tooltip view",
|
"middleClick": "[Middle Click] Keep tooltip view",
|
||||||
"tokenSize": "The token size used on the canvas"
|
"tokenSize": "The token size used on the canvas",
|
||||||
|
"previewTokenHelp": "Left-click to place, right-click to cancel"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,27 +93,29 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
||||||
}
|
}
|
||||||
|
|
||||||
getRefreshables() {
|
getRefreshables() {
|
||||||
const actionItems = this.actor.items.filter(x => this.actor.system.isItemAvailable(x)).reduce((acc, x) => {
|
const actionItems = this.actor.items
|
||||||
if (x.system.actions) {
|
.filter(x => this.actor.system.isItemAvailable(x))
|
||||||
const recoverable = x.system.actions.reduce((acc, action) => {
|
.reduce((acc, x) => {
|
||||||
if (refreshIsAllowed([this.shortrest ? 'shortRest' : 'longRest'], action.uses.recovery)) {
|
if (x.system.actions) {
|
||||||
acc.push({
|
const recoverable = x.system.actions.reduce((acc, action) => {
|
||||||
title: x.name,
|
if (refreshIsAllowed([this.shortrest ? 'shortRest' : 'longRest'], action.uses.recovery)) {
|
||||||
name: action.name,
|
acc.push({
|
||||||
uuid: action.uuid
|
title: x.name,
|
||||||
});
|
name: action.name,
|
||||||
|
uuid: action.uuid
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (recoverable) {
|
||||||
|
acc.push(...recoverable);
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (recoverable) {
|
|
||||||
acc.push(...recoverable);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
const resourceItems = this.actor.items.reduce((acc, x) => {
|
const resourceItems = this.actor.items.reduce((acc, x) => {
|
||||||
if (
|
if (
|
||||||
x.system.resource &&
|
x.system.resource &&
|
||||||
|
|
@ -189,7 +191,8 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const characters = game.actors.filter(x => x.type === 'character')
|
const characters = game.actors
|
||||||
|
.filter(x => x.type === 'character')
|
||||||
.filter(x => x.testUserPermission(game.user, 'LIMITED'))
|
.filter(x => x.testUserPermission(game.user, 'LIMITED'))
|
||||||
.filter(x => x.uuid !== this.actor.uuid);
|
.filter(x => x.uuid !== this.actor.uuid);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
|
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
tag: 'form',
|
tag: 'form',
|
||||||
classes: ['daggerheart', 'dh-style', 'dialog', 'max-800'],
|
classes: ['daggerheart', 'dh-style', 'dialog', 'action-config', 'max-800'],
|
||||||
window: {
|
window: {
|
||||||
icon: 'fa-solid fa-wrench',
|
icon: 'fa-solid fa-wrench',
|
||||||
resizable: false
|
resizable: false
|
||||||
|
|
@ -29,13 +29,15 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
removeElement: this.removeElement,
|
removeElement: this.removeElement,
|
||||||
editEffect: this.editEffect,
|
editEffect: this.editEffect,
|
||||||
addDamage: this.addDamage,
|
addDamage: this.addDamage,
|
||||||
removeDamage: this.removeDamage
|
removeDamage: this.removeDamage,
|
||||||
|
editDoc: this.editDoc
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
handler: this.updateForm,
|
handler: this.updateForm,
|
||||||
submitOnChange: true,
|
submitOnChange: true,
|
||||||
closeOnSubmit: false
|
closeOnSubmit: false
|
||||||
}
|
},
|
||||||
|
dragDrop: [{ dragSelector: null, dropSelector: '#summon-drop-zone', handlers: ['_onDrop'] }]
|
||||||
};
|
};
|
||||||
|
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
|
|
@ -85,7 +87,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static CLEAN_ARRAYS = ['damage.parts', 'cost', 'effects'];
|
static CLEAN_ARRAYS = ['damage.parts', 'cost', 'effects', 'summon'];
|
||||||
|
|
||||||
_getTabs(tabs) {
|
_getTabs(tabs) {
|
||||||
for (const v of Object.values(tabs)) {
|
for (const v of Object.values(tabs)) {
|
||||||
|
|
@ -96,9 +98,24 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
return tabs;
|
return tabs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_attachPartListeners(partId, htmlElement, options) {
|
||||||
|
super._attachPartListeners(partId, htmlElement, options);
|
||||||
|
|
||||||
|
htmlElement.querySelectorAll('.summon-count-wrapper input').forEach(element => {
|
||||||
|
element.addEventListener('change', this.updateSummonCount.bind(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async _prepareContext(_options) {
|
async _prepareContext(_options) {
|
||||||
const context = await super._prepareContext(_options, 'action');
|
const context = await super._prepareContext(_options, 'action');
|
||||||
context.source = this.action.toObject(true);
|
context.source = this.action.toObject(true);
|
||||||
|
|
||||||
|
context.summons = [];
|
||||||
|
for (const summon of context.source.summon ?? []) {
|
||||||
|
const actor = await foundry.utils.fromUuid(summon.actorUUID);
|
||||||
|
context.summons.push({ actor, count: summon.count });
|
||||||
|
}
|
||||||
|
|
||||||
context.openSection = this.openSection;
|
context.openSection = this.openSection;
|
||||||
context.tabs = this._getTabs(this.constructor.TABS);
|
context.tabs = this._getTabs(this.constructor.TABS);
|
||||||
context.config = CONFIG.DH;
|
context.config = CONFIG.DH;
|
||||||
|
|
@ -181,8 +198,9 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static async updateForm(event, _, formData) {
|
static async updateForm(event, _, formData) {
|
||||||
const submitData = this._prepareSubmitData(event, formData),
|
const submitData = this._prepareSubmitData(event, formData);
|
||||||
data = foundry.utils.mergeObject(this.action.toObject(), submitData);
|
|
||||||
|
const data = foundry.utils.mergeObject(this.action.toObject(), submitData);
|
||||||
this.action = await this.action.update(data);
|
this.action = await this.action.update(data);
|
||||||
|
|
||||||
this.sheetUpdate?.(this.action);
|
this.sheetUpdate?.(this.action);
|
||||||
|
|
@ -201,12 +219,26 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
static removeElement(event, button) {
|
static removeElement(event, button) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const data = this.action.toObject(),
|
const data = this.action.toObject(),
|
||||||
key = event.target.closest('[data-key]').dataset.key,
|
key = event.target.closest('[data-key]').dataset.key;
|
||||||
index = button.dataset.index;
|
|
||||||
|
// Prefer explicit index, otherwise find by uuid
|
||||||
|
let index = button?.dataset.index;
|
||||||
|
if (index === undefined || index === null || index === '') {
|
||||||
|
const uuid = button?.dataset.uuid ?? button?.dataset.itemUuid;
|
||||||
|
index = data[key].findIndex(e => (e?.actorUUID ?? e?.uuid) === uuid);
|
||||||
|
if (index === -1) return;
|
||||||
|
} else index = Number(index);
|
||||||
|
|
||||||
data[key].splice(index, 1);
|
data[key].splice(index, 1);
|
||||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async editDoc(_event, target) {
|
||||||
|
const element = target.closest('[data-item-uuid]');
|
||||||
|
const doc = (await foundry.utils.fromUuid(element.dataset.itemUuid)) ?? null;
|
||||||
|
if (doc) return doc.sheet.render({ force: true });
|
||||||
|
}
|
||||||
|
|
||||||
static addDamage(_event) {
|
static addDamage(_event) {
|
||||||
if (!this.action.damage.parts) return;
|
if (!this.action.damage.parts) return;
|
||||||
const data = this.action.toObject(),
|
const data = this.action.toObject(),
|
||||||
|
|
@ -224,6 +256,15 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSummonCount(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
const wrapper = event.target.closest('.summon-count-wrapper');
|
||||||
|
const index = wrapper.dataset.index;
|
||||||
|
const data = this.action.toObject();
|
||||||
|
data.summon[index].count = event.target.value;
|
||||||
|
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||||
|
}
|
||||||
|
|
||||||
/** Specific implementation in extending classes **/
|
/** Specific implementation in extending classes **/
|
||||||
static async addEffect(_event) {}
|
static async addEffect(_event) {}
|
||||||
static removeEffect(_event, _button) {}
|
static removeEffect(_event, _button) {}
|
||||||
|
|
@ -233,4 +274,29 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
this.tabGroups.primary = 'base';
|
this.tabGroups.primary = 'base';
|
||||||
await super.close(options);
|
await super.close(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _onDrop(event) {
|
||||||
|
const data = foundry.applications.ux.TextEditor.getDragEventData(event);
|
||||||
|
const item = await foundry.utils.fromUuid(data.uuid);
|
||||||
|
if (!(item instanceof game.system.api.documents.DhpActor)) {
|
||||||
|
ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.summon.invalidDrop'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionData = this.action.toObject();
|
||||||
|
let countvalue = 1;
|
||||||
|
for (const entry of actionData.summon) {
|
||||||
|
if (entry.actorUUID === data.uuid) {
|
||||||
|
entry.count += 1;
|
||||||
|
countvalue = entry.count;
|
||||||
|
await this.constructor.updateForm.bind(this)(null, null, {
|
||||||
|
object: foundry.utils.flattenObject(actionData)
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actionData.summon.push({ actorUUID: data.uuid, count: countvalue });
|
||||||
|
await this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(actionData) });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
||||||
dragSelector: '[data-item-id][draggable="true"], [data-item-id] [draggable="true"]',
|
dragSelector: '[data-item-id][draggable="true"], [data-item-id] [draggable="true"]',
|
||||||
dropSelector: null
|
dropSelector: null
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
|
|
@ -185,7 +185,6 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
||||||
super._onDragStart(event);
|
super._onDragStart(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Application Clicks Actions */
|
/* Application Clicks Actions */
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
advanceResourceDie: CharacterSheet.#advanceResourceDie,
|
advanceResourceDie: CharacterSheet.#advanceResourceDie,
|
||||||
cancelBeastform: CharacterSheet.#cancelBeastform,
|
cancelBeastform: CharacterSheet.#cancelBeastform,
|
||||||
useDowntime: this.useDowntime,
|
useDowntime: this.useDowntime,
|
||||||
viewParty: CharacterSheet.#viewParty,
|
viewParty: CharacterSheet.#viewParty
|
||||||
},
|
},
|
||||||
window: {
|
window: {
|
||||||
resizable: true,
|
resizable: true,
|
||||||
|
|
@ -338,15 +338,20 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
}
|
}
|
||||||
const type = 'effect';
|
const type = 'effect';
|
||||||
const cls = game.system.api.models.actions.actionsTypes[type];
|
const cls = game.system.api.models.actions.actionsTypes[type];
|
||||||
const action = new cls({
|
const action = new cls(
|
||||||
...cls.getSourceConfig(doc.system),
|
{
|
||||||
type: type,
|
...cls.getSourceConfig(doc.system),
|
||||||
chatDisplay: false,
|
type: type,
|
||||||
cost: [{
|
chatDisplay: false,
|
||||||
key: 'stress',
|
cost: [
|
||||||
value: doc.system.recallCost
|
{
|
||||||
}]
|
key: 'stress',
|
||||||
}, { parent: doc.system });
|
value: doc.system.recallCost
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ parent: doc.system }
|
||||||
|
);
|
||||||
const config = await action.use(event);
|
const config = await action.use(event);
|
||||||
if (config) {
|
if (config) {
|
||||||
return doc.update({ 'system.inVault': false });
|
return doc.update({ 'system.inVault': false });
|
||||||
|
|
@ -900,32 +905,32 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const buttons = parties.map((p) => {
|
const buttons = parties.map(p => {
|
||||||
const button = document.createElement("button");
|
const button = document.createElement('button');
|
||||||
button.type = "button";
|
button.type = 'button';
|
||||||
button.classList.add("plain");
|
button.classList.add('plain');
|
||||||
const img = document.createElement("img");
|
const img = document.createElement('img');
|
||||||
img.src = p.img;
|
img.src = p.img;
|
||||||
button.append(img);
|
button.append(img);
|
||||||
const name = document.createElement("span");
|
const name = document.createElement('span');
|
||||||
name.textContent = p.name;
|
name.textContent = p.name;
|
||||||
button.append(name);
|
button.append(name);
|
||||||
button.addEventListener("click", () => {
|
button.addEventListener('click', () => {
|
||||||
p.sheet?.render({ force: true });
|
p.sheet?.render({ force: true });
|
||||||
game.tooltip.dismissLockedTooltips();
|
game.tooltip.dismissLockedTooltips();
|
||||||
});
|
});
|
||||||
return button;
|
return button;
|
||||||
});
|
});
|
||||||
|
|
||||||
const html = document.createElement("div");
|
const html = document.createElement('div');
|
||||||
html.classList.add("party-list");
|
html.classList.add('party-list');
|
||||||
html.append(...buttons);
|
html.append(...buttons);
|
||||||
|
|
||||||
game.tooltip.dismissLockedTooltips();
|
game.tooltip.dismissLockedTooltips();
|
||||||
game.tooltip.activate(target, {
|
game.tooltip.activate(target, {
|
||||||
html,
|
html,
|
||||||
locked: true,
|
locked: true
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
||||||
async actionUseButton(event, message) {
|
async actionUseButton(event, message) {
|
||||||
const { moveIndex, actionIndex, movePath } = event.currentTarget.dataset;
|
const { moveIndex, actionIndex, movePath } = event.currentTarget.dataset;
|
||||||
const targetUuid = event.currentTarget.closest('.action-use-button-parent').querySelector('select')?.value;
|
const targetUuid = event.currentTarget.closest('.action-use-button-parent').querySelector('select')?.value;
|
||||||
const parent = await foundry.utils.fromUuid(targetUuid || message.system.actor)
|
const parent = await foundry.utils.fromUuid(targetUuid || message.system.actor);
|
||||||
|
|
||||||
const actionType = message.system.moves[moveIndex].actions[actionIndex];
|
const actionType = message.system.moves[moveIndex].actions[actionIndex];
|
||||||
const cls = game.system.api.models.actions.actionsTypes[actionType.type];
|
const cls = game.system.api.models.actions.actionsTypes[actionType.type];
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export * as placeables from './placeables/_module.mjs';
|
export * as placeables from './placeables/_module.mjs';
|
||||||
|
export { default as DhTokenLayer } from './tokens.mjs';
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,12 @@
|
||||||
export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
|
/** @inheritdoc */
|
||||||
|
async _draw(options) {
|
||||||
|
await super._draw(options);
|
||||||
|
|
||||||
|
if (this.document.flags.daggerheart?.createPlacement)
|
||||||
|
this.previewHelp ||= this.addChild(this.#drawPreviewHelp());
|
||||||
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
async _drawEffects() {
|
async _drawEffects() {
|
||||||
this.effects.renderable = false;
|
this.effects.renderable = false;
|
||||||
|
|
@ -34,7 +42,7 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
this.renderFlags.set({ refreshEffects: true });
|
this.renderFlags.set({ refreshEffects: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the distance from this token to another token object.
|
* Returns the distance from this token to another token object.
|
||||||
* This value is corrected to handle alternate token sizes and other grid types
|
* This value is corrected to handle alternate token sizes and other grid types
|
||||||
* according to the diagonal rules.
|
* according to the diagonal rules.
|
||||||
|
|
@ -47,11 +55,11 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
const destinationPoint = target.center;
|
const destinationPoint = target.center;
|
||||||
|
|
||||||
// Compute for gridless. This version returns circular edge to edge + grid distance,
|
// Compute for gridless. This version returns circular edge to edge + grid distance,
|
||||||
// so that tokens that are touching return 5.
|
// so that tokens that are touching return 5.
|
||||||
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
if (canvas.grid.type === CONST.GRID_TYPES.GRIDLESS) {
|
||||||
const boundsCorrection = canvas.grid.distance / canvas.grid.size;
|
const boundsCorrection = canvas.grid.distance / canvas.grid.size;
|
||||||
const originRadius = this.bounds.width * boundsCorrection / 2;
|
const originRadius = (this.bounds.width * boundsCorrection) / 2;
|
||||||
const targetRadius = target.bounds.width * boundsCorrection / 2;
|
const targetRadius = (target.bounds.width * boundsCorrection) / 2;
|
||||||
const distance = canvas.grid.measurePath([originPoint, destinationPoint]).distance;
|
const distance = canvas.grid.measurePath([originPoint, destinationPoint]).distance;
|
||||||
return distance - originRadius - targetRadius + canvas.grid.distance;
|
return distance - originRadius - targetRadius + canvas.grid.distance;
|
||||||
}
|
}
|
||||||
|
|
@ -61,11 +69,11 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
const targetEdge = this.#getEdgeBoundary(target.bounds, originPoint, destinationPoint);
|
const targetEdge = this.#getEdgeBoundary(target.bounds, originPoint, destinationPoint);
|
||||||
const adjustedOriginPoint = canvas.grid.getTopLeftPoint({
|
const adjustedOriginPoint = canvas.grid.getTopLeftPoint({
|
||||||
x: originEdge.x + Math.sign(originPoint.x - originEdge.x),
|
x: originEdge.x + Math.sign(originPoint.x - originEdge.x),
|
||||||
y: originEdge.y + Math.sign(originPoint.y - originEdge.y)
|
y: originEdge.y + Math.sign(originPoint.y - originEdge.y)
|
||||||
});
|
});
|
||||||
const adjustDestinationPoint = canvas.grid.getTopLeftPoint({
|
const adjustDestinationPoint = canvas.grid.getTopLeftPoint({
|
||||||
x: targetEdge.x + Math.sign(destinationPoint.x - targetEdge.x),
|
x: targetEdge.x + Math.sign(destinationPoint.x - targetEdge.x),
|
||||||
y: targetEdge.y + Math.sign(destinationPoint.y - targetEdge.y)
|
y: targetEdge.y + Math.sign(destinationPoint.y - targetEdge.y)
|
||||||
});
|
});
|
||||||
return canvas.grid.measurePath([adjustedOriginPoint, adjustDestinationPoint]).distance;
|
return canvas.grid.measurePath([adjustedOriginPoint, adjustDestinationPoint]).distance;
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +102,7 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
|
|
||||||
/** Tests if the token is at least adjacent with another, with some leeway for diagonals */
|
/** Tests if the token is at least adjacent with another, with some leeway for diagonals */
|
||||||
isAdjacentWith(token) {
|
isAdjacentWith(token) {
|
||||||
return this.distanceTo(token) <= (canvas.grid.distance * 1.5);
|
return this.distanceTo(token) <= canvas.grid.distance * 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
|
|
@ -132,4 +140,25 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
bar.position.set(0, posY);
|
bar.position.set(0, posY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a helptext for previews as a text object
|
||||||
|
* @returns {PreciseText} The Text object for the preview helper
|
||||||
|
*/
|
||||||
|
#drawPreviewHelp() {
|
||||||
|
const { uiScale } = canvas.dimensions;
|
||||||
|
|
||||||
|
const textStyle = CONFIG.canvasTextStyle.clone();
|
||||||
|
textStyle.fontSize = 18;
|
||||||
|
textStyle.wordWrapWidth = this.w * 2.5;
|
||||||
|
textStyle.fontStyle = 'italic';
|
||||||
|
|
||||||
|
const helpText = new PreciseText(
|
||||||
|
`(${game.i18n.localize('DAGGERHEART.UI.Tooltip.previewTokenHelp')})`,
|
||||||
|
textStyle
|
||||||
|
);
|
||||||
|
helpText.anchor.set(helpText.width / 900, 1);
|
||||||
|
helpText.scale.set(uiScale, uiScale);
|
||||||
|
return helpText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
module/canvas/tokens.mjs
Normal file
16
module/canvas/tokens.mjs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -164,7 +164,6 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
*/
|
*/
|
||||||
getRollData(data = {}) {
|
getRollData(data = {}) {
|
||||||
const actorData = this.actor ? this.actor.getRollData(false) : {};
|
const actorData = this.actor ? this.actor.getRollData(false) : {};
|
||||||
|
|
||||||
actorData.result = data.roll?.total ?? 1;
|
actorData.result = data.roll?.total ?? 1;
|
||||||
actorData.scale = data.costs?.length // Right now only return the first scalable cost.
|
actorData.scale = data.costs?.length // Right now only return the first scalable cost.
|
||||||
? (data.costs.find(c => c.scalable)?.total ?? 1)
|
? (data.costs.find(c => c.scalable)?.total ?? 1)
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,5 @@
|
||||||
import DHBaseAction from './baseAction.mjs';
|
import DHBaseAction from './baseAction.mjs';
|
||||||
|
|
||||||
export default class DHSummonAction extends DHBaseAction {
|
export default class DHSummonAction extends DHBaseAction {
|
||||||
static defineSchema() {
|
static extraSchemas = [...super.extraSchemas, 'summon'];
|
||||||
const fields = foundry.data.fields;
|
|
||||||
return {
|
|
||||||
...super.defineSchema(),
|
|
||||||
documentUUID: new fields.DocumentUUIDField({ type: 'Actor' })
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async trigger(event, ...args) {
|
|
||||||
if (!this.canSummon || !canvas.scene) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
get canSummon() {
|
|
||||||
return game.user.can('TOKEN_CREATE');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,4 @@ export { default as BeastformField } from './beastformField.mjs';
|
||||||
export { default as DamageField } from './damageField.mjs';
|
export { default as DamageField } from './damageField.mjs';
|
||||||
export { default as RollField } from './rollField.mjs';
|
export { default as RollField } from './rollField.mjs';
|
||||||
export { default as MacroField } from './macroField.mjs';
|
export { default as MacroField } from './macroField.mjs';
|
||||||
|
export { default as SummonField } from './summonField.mjs';
|
||||||
|
|
|
||||||
89
module/data/fields/action/summonField.mjs
Normal file
89
module/data/fields/action/summonField.mjs
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
import FormulaField from '../formulaField.mjs';
|
||||||
|
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
|
||||||
|
export default class DHSummonField extends fields.ArrayField {
|
||||||
|
/**
|
||||||
|
* Action Workflow order
|
||||||
|
*/
|
||||||
|
static order = 120;
|
||||||
|
|
||||||
|
constructor(options = {}, context = {}) {
|
||||||
|
const summonFields = new fields.SchemaField({
|
||||||
|
actorUUID: new fields.DocumentUUIDField({
|
||||||
|
type: 'Actor',
|
||||||
|
required: true
|
||||||
|
}),
|
||||||
|
count: new FormulaField({
|
||||||
|
required: true,
|
||||||
|
default: '1'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
super(summonFields, options, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async execute() {
|
||||||
|
if (!canvas.scene) {
|
||||||
|
ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.summon.error'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.summon.length === 0) {
|
||||||
|
ui.notifications.warn('No actors configured for this Summon action.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 actor = 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 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rolls.length) await Promise.all(rolls.map(roll => game.dice3d.showForRoll(roll, game.user, true)));
|
||||||
|
|
||||||
|
this.actor.sheet?.minimize();
|
||||||
|
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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)` : ''}`
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -267,7 +267,8 @@ export function ActionMixin(Base) {
|
||||||
action: {
|
action: {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
img: this.baseAction ? this.parent.parent.img : this.img,
|
img: this.baseAction ? this.parent.parent.img : this.img,
|
||||||
tags: this.tags ? this.tags : ['Spell', 'Arcana', 'Lv 10']
|
tags: this.tags ? this.tags : ['Spell', 'Arcana', 'Lv 10'],
|
||||||
|
summon: this.summon
|
||||||
},
|
},
|
||||||
itemOrigin: this.item,
|
itemOrigin: this.item,
|
||||||
description: this.description || (this.item instanceof Item ? this.item.system.description : '')
|
description: this.description || (this.item instanceof Item ? this.item.system.description : '')
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,4 @@ export { default as DhScene } from './scene.mjs';
|
||||||
export { default as DhToken } from './token.mjs';
|
export { default as DhToken } from './token.mjs';
|
||||||
export { default as DhTooltipManager } from './tooltipManager.mjs';
|
export { default as DhTooltipManager } from './tooltipManager.mjs';
|
||||||
export { default as DhTemplateManager } from './templateManager.mjs';
|
export { default as DhTemplateManager } from './templateManager.mjs';
|
||||||
|
export { default as DhTokenManager } from './tokenManager.mjs';
|
||||||
|
|
|
||||||
104
module/documents/tokenManager.mjs
Normal file
104
module/documents/tokenManager.mjs
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
/**
|
||||||
|
* A singleton class that handles preview tokens.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default class DhTokenManager {
|
||||||
|
#activePreview;
|
||||||
|
#actor;
|
||||||
|
#resolve;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a template preview, deactivating any existing ones.
|
||||||
|
* @param {object} data
|
||||||
|
*/
|
||||||
|
async createPreview(actor, tokenData) {
|
||||||
|
this.#actor = actor;
|
||||||
|
const token = await canvas.tokens._createPreview(
|
||||||
|
{
|
||||||
|
...actor.prototypeToken,
|
||||||
|
displayName: 50,
|
||||||
|
...tokenData
|
||||||
|
},
|
||||||
|
{ renderSheet: false, actor }
|
||||||
|
);
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
#onDragMouseMove(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
const { moveTime, object } = this.#activePreview;
|
||||||
|
const update = {};
|
||||||
|
|
||||||
|
const now = Date.now();
|
||||||
|
if (now - (moveTime || 0) <= 16) return;
|
||||||
|
this.#activePreview.moveTime = now;
|
||||||
|
|
||||||
|
let cursor = event.getLocalPosition(canvas.templates);
|
||||||
|
|
||||||
|
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, x: this.#activePreview.document.x, y: this.#activePreview.document.y }
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.#activePreview = undefined;
|
||||||
|
if (this.#resolve && result.length) this.#resolve(result[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,7 @@ export const preloadHandlebarsTemplates = async function () {
|
||||||
'systems/daggerheart/templates/actionTypes/effect.hbs',
|
'systems/daggerheart/templates/actionTypes/effect.hbs',
|
||||||
'systems/daggerheart/templates/actionTypes/beastform.hbs',
|
'systems/daggerheart/templates/actionTypes/beastform.hbs',
|
||||||
'systems/daggerheart/templates/actionTypes/countdown.hbs',
|
'systems/daggerheart/templates/actionTypes/countdown.hbs',
|
||||||
|
'systems/daggerheart/templates/actionTypes/summon.hbs',
|
||||||
'systems/daggerheart/templates/settings/components/settings-item-line.hbs',
|
'systems/daggerheart/templates/settings/components/settings-item-line.hbs',
|
||||||
'systems/daggerheart/templates/ui/tooltip/parts/tooltipChips.hbs',
|
'systems/daggerheart/templates/ui/tooltip/parts/tooltipChips.hbs',
|
||||||
'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs',
|
'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs',
|
||||||
|
|
|
||||||
|
|
@ -533,33 +533,31 @@
|
||||||
"description": "<p><strong>Spend a Fear</strong> to summon a @UUID[Compendium.daggerheart.adversaries.Actor.YhJrP7rTBiRdX5Fp]{Zombie Legion}, which appears at Close range and immediately takes the spotlight.</p>",
|
"description": "<p><strong>Spend a Fear</strong> to summon a @UUID[Compendium.daggerheart.adversaries.Actor.YhJrP7rTBiRdX5Fp]{Zombie Legion}, which appears at Close range and immediately takes the spotlight.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"gZg3AkzCYUTExjE6": {
|
"qSuWxC8xQOhnbBx9": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "gZg3AkzCYUTExjE6",
|
"_id": "qSuWxC8xQOhnbBx9",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
"description": "",
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [],
|
||||||
{
|
|
||||||
"scalable": false,
|
|
||||||
"key": "fear",
|
|
||||||
"value": 1,
|
|
||||||
"step": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "",
|
||||||
"recovery": null
|
"recovery": null,
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "any",
|
|
||||||
"amount": null
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.YhJrP7rTBiRdX5Fp",
|
||||||
|
"count": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Spend Fear",
|
"name": "Spend Fear",
|
||||||
"img": "icons/magic/death/undead-zombie-grave-green.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -457,11 +457,12 @@
|
||||||
"img": "icons/creatures/unholy/demon-fire-horned-clawed.webp",
|
"img": "icons/creatures/unholy/demon-fire-horned-clawed.webp",
|
||||||
"range": ""
|
"range": ""
|
||||||
},
|
},
|
||||||
"7G6uWlFEeOLsJIWY": {
|
"FlE6i0tbKEguF9wz": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "7G6uWlFEeOLsJIWY",
|
"_id": "FlE6i0tbKEguF9wz",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
"description": "<p>Summon [[/r 1d4]]@UUID[Compendium.daggerheart.adversaries.Actor.3tqCjDwJAQ7JKqMb]{Minor Demons}, who appear at Close range.</p>",
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
"originItem": {
|
"originItem": {
|
||||||
"type": "itemCollection"
|
"type": "itemCollection"
|
||||||
|
|
@ -474,13 +475,13 @@
|
||||||
"recovery": null,
|
"recovery": null,
|
||||||
"consumeOnSuccess": false
|
"consumeOnSuccess": false
|
||||||
},
|
},
|
||||||
"effects": [],
|
"summon": [
|
||||||
"target": {
|
{
|
||||||
"type": "any",
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.3tqCjDwJAQ7JKqMb",
|
||||||
"amount": null
|
"count": "1d4"
|
||||||
},
|
}
|
||||||
|
],
|
||||||
"name": "Summon",
|
"name": "Summon",
|
||||||
"img": "icons/creatures/unholy/demon-fire-horned-clawed.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -363,33 +363,31 @@
|
||||||
"description": "<p><strong>Spend a Fear</strong> to grow three @UUID[Compendium.daggerheart.adversaries.Actor.o63nS0k3wHu6EgKP]{Treant Sapling Minions}, who appear at Close range and immediately take the spotlight.</p>",
|
"description": "<p><strong>Spend a Fear</strong> to grow three @UUID[Compendium.daggerheart.adversaries.Actor.o63nS0k3wHu6EgKP]{Treant Sapling Minions}, who appear at Close range and immediately take the spotlight.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"84Q2b0zIY9c7Yhho": {
|
"R84DdS0OIx2cUt1w": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "84Q2b0zIY9c7Yhho",
|
"_id": "R84DdS0OIx2cUt1w",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
"description": "",
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [],
|
||||||
{
|
|
||||||
"scalable": false,
|
|
||||||
"key": "fear",
|
|
||||||
"value": 1,
|
|
||||||
"step": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "",
|
||||||
"recovery": null
|
"recovery": null,
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "self",
|
|
||||||
"amount": null
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.o63nS0k3wHu6EgKP",
|
||||||
|
"count": "3"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Spend Fear",
|
"name": "Spend Fear",
|
||||||
"img": "icons/magic/unholy/orb-hands-pink.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -510,34 +510,41 @@
|
||||||
"description": "<p>When the @Lookup[@name] has 3 or more HP marked, you can <strong>spend a Fear</strong> to split them into two @UUID[Compendium.daggerheart.adversaries.Actor.aLkLFuVoKz2NLoBK]{Tiny Green Oozes} (with no marked HP or Stress). Immediately spotlight both of them.</p>",
|
"description": "<p>When the @Lookup[@name] has 3 or more HP marked, you can <strong>spend a Fear</strong> to split them into two @UUID[Compendium.daggerheart.adversaries.Actor.aLkLFuVoKz2NLoBK]{Tiny Green Oozes} (with no marked HP or Stress). Immediately spotlight both of them.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"s5mLw6DRGd76MLcC": {
|
"J8U7dw3cDSsEirr5": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "s5mLw6DRGd76MLcC",
|
"_id": "J8U7dw3cDSsEirr5",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
"description": "",
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [
|
||||||
{
|
{
|
||||||
"scalable": false,
|
"scalable": false,
|
||||||
"key": "fear",
|
"key": "fear",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"step": null
|
"itemId": null,
|
||||||
|
"step": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "",
|
||||||
"recovery": null
|
"recovery": null,
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "self",
|
|
||||||
"amount": null
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.aLkLFuVoKz2NLoBK",
|
||||||
|
"count": "2"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Spend Fear",
|
"name": "Spend Fear",
|
||||||
"img": "icons/creatures/slimes/slime-movement-pseudopods-green.webp",
|
"range": "self"
|
||||||
"range": ""
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"originItemType": null,
|
"originItemType": null,
|
||||||
|
|
|
||||||
|
|
@ -474,33 +474,31 @@
|
||||||
"description": "<p><strong>Spend 2 Fear</strong> to summon [[/r 1d4]] @UUID[Compendium.daggerheart.adversaries.Actor.WWyUp6Mxl1S3KYUG]{Vampires}, who appear at Far range and immediately take the spotlight.</p>",
|
"description": "<p><strong>Spend 2 Fear</strong> to summon [[/r 1d4]] @UUID[Compendium.daggerheart.adversaries.Actor.WWyUp6Mxl1S3KYUG]{Vampires}, who appear at Far range and immediately take the spotlight.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"5Q6RMUTiauKw0tDj": {
|
"jGFOnU6PNdWU6iF4": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "5Q6RMUTiauKw0tDj",
|
"_id": "jGFOnU6PNdWU6iF4",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
"description": "",
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [],
|
||||||
{
|
|
||||||
"scalable": false,
|
|
||||||
"key": "fear",
|
|
||||||
"value": 2,
|
|
||||||
"step": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "",
|
||||||
"recovery": null
|
"recovery": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
},
|
},
|
||||||
"effects": [],
|
"summon": [
|
||||||
"target": {
|
{
|
||||||
"type": "any",
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.WWyUp6Mxl1S3KYUG",
|
||||||
"amount": null
|
"count": "1d4"
|
||||||
},
|
}
|
||||||
"name": "Summon Vampires",
|
],
|
||||||
"img": "icons/creatures/mammals/bat-giant-tattered-purple.webp",
|
"name": "Spend Fear",
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -479,33 +479,31 @@
|
||||||
"description": "<p>When the @Lookup[@name] has 4 or more HP marked, you can <strong>spend a Fear</strong> to split them into two @UUID[Compendium.daggerheart.adversaries.Actor.SHXedd9zZPVfUgUa]{Green Oozes}(with no marked HP or Stress). Immediately spotlight both of them.</p>",
|
"description": "<p>When the @Lookup[@name] has 4 or more HP marked, you can <strong>spend a Fear</strong> to split them into two @UUID[Compendium.daggerheart.adversaries.Actor.SHXedd9zZPVfUgUa]{Green Oozes}(with no marked HP or Stress). Immediately spotlight both of them.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"iQsYAqpUFvJslRDr": {
|
"aeRdkiRsDNagTKhp": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "iQsYAqpUFvJslRDr",
|
"_id": "aeRdkiRsDNagTKhp",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
"description": "",
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [],
|
||||||
{
|
|
||||||
"scalable": false,
|
|
||||||
"key": "fear",
|
|
||||||
"value": 1,
|
|
||||||
"step": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "",
|
||||||
"recovery": null
|
"recovery": null,
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "any",
|
|
||||||
"amount": null
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.SHXedd9zZPVfUgUa",
|
||||||
|
"count": "2"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Spend Fear",
|
"name": "Spend Fear",
|
||||||
"img": "icons/creatures/slimes/slime-movement-pseudopods-green.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,35 @@
|
||||||
"system": {
|
"system": {
|
||||||
"description": "<p>Summon three @Compendium[daggerheart.adversaries.Actor.C0OMQqV7pN6t7ouR], who appear at Far range.</p>",
|
"description": "<p>Summon three @Compendium[daggerheart.adversaries.Actor.C0OMQqV7pN6t7ouR], who appear at Far range.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {},
|
"actions": {
|
||||||
|
"MCTBsw9lusUdubj0": {
|
||||||
|
"type": "summon",
|
||||||
|
"_id": "MCTBsw9lusUdubj0",
|
||||||
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
|
"actionType": "action",
|
||||||
|
"cost": [],
|
||||||
|
"uses": {
|
||||||
|
"value": null,
|
||||||
|
"max": "",
|
||||||
|
"recovery": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.C0OMQqV7pN6t7ouR",
|
||||||
|
"count": "3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Summon",
|
||||||
|
"range": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"originItemType": null,
|
"originItemType": null,
|
||||||
"subType": null,
|
"subType": null,
|
||||||
"originId": null,
|
"originId": null,
|
||||||
|
|
|
||||||
|
|
@ -258,57 +258,40 @@
|
||||||
"description": "<p>Once per scene, <strong>mark a Stress</strong> to summon <strong>1d4</strong> @UUID[Compendium.daggerheart.adversaries.Actor.B4LZcGuBAHzyVdzy]{Bladed Guards}, who appear at Far range to enforce the @Lookup[@name]’s will.</p>",
|
"description": "<p>Once per scene, <strong>mark a Stress</strong> to summon <strong>1d4</strong> @UUID[Compendium.daggerheart.adversaries.Actor.B4LZcGuBAHzyVdzy]{Bladed Guards}, who appear at Far range to enforce the @Lookup[@name]’s will.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"cUKwhq1imsTVru8D": {
|
"tioTtYfIGFIXRITN": {
|
||||||
"type": "attack",
|
"type": "summon",
|
||||||
"_id": "cUKwhq1imsTVru8D",
|
"_id": "tioTtYfIGFIXRITN",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
"description": "<p>Once per scene, <strong>mark a Stress</strong> to summon <strong>1d4</strong> @UUID[Compendium.daggerheart.adversaries.Actor.B4LZcGuBAHzyVdzy]{Bladed Guards}, who appear at Far range to enforce the Noble’s will.</p>",
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [
|
||||||
{
|
{
|
||||||
"scalable": false,
|
"scalable": false,
|
||||||
"key": "stress",
|
"key": "stress",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"step": null
|
"itemId": null,
|
||||||
|
"step": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "1",
|
||||||
"recovery": null
|
"recovery": "scene",
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"damage": {
|
|
||||||
"parts": [],
|
|
||||||
"includeBase": false
|
|
||||||
},
|
|
||||||
"target": {
|
|
||||||
"type": "any",
|
|
||||||
"amount": null
|
|
||||||
},
|
|
||||||
"effects": [],
|
|
||||||
"roll": {
|
|
||||||
"type": "diceSet",
|
|
||||||
"trait": null,
|
|
||||||
"difficulty": null,
|
|
||||||
"bonus": null,
|
|
||||||
"advState": "neutral",
|
|
||||||
"diceRolling": {
|
|
||||||
"multiplier": "prof",
|
|
||||||
"flatMultiplier": 1,
|
|
||||||
"dice": "d4",
|
|
||||||
"compare": null,
|
|
||||||
"treshold": null
|
|
||||||
},
|
|
||||||
"useDefault": false
|
|
||||||
},
|
|
||||||
"save": {
|
|
||||||
"trait": null,
|
|
||||||
"difficulty": null,
|
|
||||||
"damageMod": "none"
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.B4LZcGuBAHzyVdzy",
|
||||||
|
"count": "1d4"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Summon Guards",
|
"name": "Summon Guards",
|
||||||
"img": "icons/environment/people/infantry-armored.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -313,36 +313,43 @@
|
||||||
"_id": "WGEGO0DSOs5cF0EL",
|
"_id": "WGEGO0DSOs5cF0EL",
|
||||||
"img": "icons/environment/people/charge.webp",
|
"img": "icons/environment/people/charge.webp",
|
||||||
"system": {
|
"system": {
|
||||||
"description": "<p>Once per scene, <strong>mark a Stress</strong> to summon a Pirate Raiders Horde, which appears at Far range.</p>",
|
"description": "<p>Once per scene, <strong>mark a Stress</strong> to summon a @UUID[Compendium.daggerheart.adversaries.Actor.5YgEajn0wa4i85kC]{Pirate Raider Horde}, which appears at Far range.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"NlgIp0KrmZoS27Xy": {
|
"nuYk5WeLLpIKa69q": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "NlgIp0KrmZoS27Xy",
|
"_id": "nuYk5WeLLpIKa69q",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
"description": "",
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [
|
||||||
{
|
{
|
||||||
"scalable": false,
|
"scalable": false,
|
||||||
"key": "stress",
|
"key": "stress",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"step": null
|
"itemId": null,
|
||||||
|
"step": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "",
|
||||||
"recovery": null
|
"recovery": null,
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "any",
|
|
||||||
"amount": null
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.5YgEajn0wa4i85kC",
|
||||||
|
"count": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Mark Stress",
|
"name": "Mark Stress",
|
||||||
"img": "icons/environment/people/charge.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -454,33 +454,40 @@
|
||||||
"description": "<p>When the @Lookup[@name] has 3 or more HP marked, you can <strong>spend a Fear</strong> to split them into two @UUID[Compendium.daggerheart.adversaries.Actor.1fkLQXVtmILqfJ44]{Tiny Red Oozes} (with no marked HP or Stress). Immediately spotlight both of them.</p>",
|
"description": "<p>When the @Lookup[@name] has 3 or more HP marked, you can <strong>spend a Fear</strong> to split them into two @UUID[Compendium.daggerheart.adversaries.Actor.1fkLQXVtmILqfJ44]{Tiny Red Oozes} (with no marked HP or Stress). Immediately spotlight both of them.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"dw6Juw8mriH7sg0e": {
|
"BMEr77hDxaQyYBna": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "dw6Juw8mriH7sg0e",
|
"_id": "BMEr77hDxaQyYBna",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
"description": "",
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [
|
||||||
{
|
{
|
||||||
"scalable": false,
|
"scalable": false,
|
||||||
"key": "fear",
|
"key": "fear",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"step": null
|
"itemId": null,
|
||||||
|
"step": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "",
|
||||||
"recovery": null
|
"recovery": null,
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "any",
|
|
||||||
"amount": null
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.1fkLQXVtmILqfJ44",
|
||||||
|
"count": "2"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Spend Fear",
|
"name": "Spend Fear",
|
||||||
"img": "icons/creatures/slimes/slime-movement-splashing-red.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -416,28 +416,6 @@
|
||||||
"description": "<p><em>Countdown (6)</em>. When the @Lookup[@name] is in the spotlight for the first time, activate the countdown. When they mark HP, tick down this countdown by the number of HP marked. When it triggers, summon a @UUID[Compendium.daggerheart.adversaries.Actor.3tqCjDwJAQ7JKqMb]{Minor Demon} who appears at Close range.</p>",
|
"description": "<p><em>Countdown (6)</em>. When the @Lookup[@name] is in the spotlight for the first time, activate the countdown. When they mark HP, tick down this countdown by the number of HP marked. When it triggers, summon a @UUID[Compendium.daggerheart.adversaries.Actor.3tqCjDwJAQ7JKqMb]{Minor Demon} who appears at Close range.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"0rixG6jLRynAYNqA": {
|
|
||||||
"type": "effect",
|
|
||||||
"_id": "0rixG6jLRynAYNqA",
|
|
||||||
"systemPath": "actions",
|
|
||||||
"description": "<p>Summon a @UUID[Compendium.daggerheart.adversaries.Actor.3tqCjDwJAQ7JKqMb]{Minor Demon} who appears at Close range.</p>",
|
|
||||||
"chatDisplay": true,
|
|
||||||
"actionType": "action",
|
|
||||||
"cost": [],
|
|
||||||
"uses": {
|
|
||||||
"value": null,
|
|
||||||
"max": "",
|
|
||||||
"recovery": null
|
|
||||||
},
|
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "any",
|
|
||||||
"amount": null
|
|
||||||
},
|
|
||||||
"name": "Summon",
|
|
||||||
"img": "icons/magic/unholy/silhouette-light-fire-blue.webp",
|
|
||||||
"range": "close"
|
|
||||||
},
|
|
||||||
"ZVXHY2fpomoKV7jG": {
|
"ZVXHY2fpomoKV7jG": {
|
||||||
"type": "countdown",
|
"type": "countdown",
|
||||||
"_id": "ZVXHY2fpomoKV7jG",
|
"_id": "ZVXHY2fpomoKV7jG",
|
||||||
|
|
@ -474,6 +452,33 @@
|
||||||
"name": "Start Countdown",
|
"name": "Start Countdown",
|
||||||
"img": "icons/magic/unholy/silhouette-light-fire-blue.webp",
|
"img": "icons/magic/unholy/silhouette-light-fire-blue.webp",
|
||||||
"range": ""
|
"range": ""
|
||||||
|
},
|
||||||
|
"YReYG6DrWp4QGSij": {
|
||||||
|
"type": "summon",
|
||||||
|
"_id": "YReYG6DrWp4QGSij",
|
||||||
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
|
"actionType": "action",
|
||||||
|
"cost": [],
|
||||||
|
"uses": {
|
||||||
|
"value": null,
|
||||||
|
"max": "",
|
||||||
|
"recovery": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.3tqCjDwJAQ7JKqMb",
|
||||||
|
"count": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Summon",
|
||||||
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"originItemType": null,
|
"originItemType": null,
|
||||||
|
|
@ -502,33 +507,31 @@
|
||||||
"description": "<p>Once per scene, when the @Lookup[@name] marks 2 or more HP, you can <strong>mark a Stress</strong> to summon a @UUID[Compendium.daggerheart.adversaries.Actor.NoRZ1PqB8N5wcIw0]{Demonic Hound Pack}, which appears at Close range and is immediately spotlighted.</p>",
|
"description": "<p>Once per scene, when the @Lookup[@name] marks 2 or more HP, you can <strong>mark a Stress</strong> to summon a @UUID[Compendium.daggerheart.adversaries.Actor.NoRZ1PqB8N5wcIw0]{Demonic Hound Pack}, which appears at Close range and is immediately spotlighted.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"JBuQUJhif2A7IlJd": {
|
"tfmY6HYkkY27NBaF": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "JBuQUJhif2A7IlJd",
|
"_id": "tfmY6HYkkY27NBaF",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
"description": "",
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [],
|
||||||
{
|
|
||||||
"scalable": false,
|
|
||||||
"key": "stress",
|
|
||||||
"value": 1,
|
|
||||||
"step": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "1",
|
"max": "",
|
||||||
"recovery": "scene"
|
"recovery": null,
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "self",
|
|
||||||
"amount": null
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.NoRZ1PqB8N5wcIw0",
|
||||||
|
"count": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Mark Stress",
|
"name": "Mark Stress",
|
||||||
"img": "icons/creatures/unholy/demon-fire-horned-clawed.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -340,7 +340,35 @@
|
||||||
"system": {
|
"system": {
|
||||||
"description": "<p>When an attack from the @Lookup[@name] causes a target to mark HP and there are three or more @Lookup[@name] Minions within Close range, you can combine the Minions into a @UUID[Compendium.daggerheart.adversaries.Actor.PKSXFuaIHUCoH63A]{Tangle Bramble Swarm Horde}. The Horde’s HP is equal to the number of Minions combined.</p>",
|
"description": "<p>When an attack from the @Lookup[@name] causes a target to mark HP and there are three or more @Lookup[@name] Minions within Close range, you can combine the Minions into a @UUID[Compendium.daggerheart.adversaries.Actor.PKSXFuaIHUCoH63A]{Tangle Bramble Swarm Horde}. The Horde’s HP is equal to the number of Minions combined.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {},
|
"actions": {
|
||||||
|
"g1OQ5xlMHFWsoktd": {
|
||||||
|
"type": "summon",
|
||||||
|
"_id": "g1OQ5xlMHFWsoktd",
|
||||||
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
|
"actionType": "action",
|
||||||
|
"cost": [],
|
||||||
|
"uses": {
|
||||||
|
"value": null,
|
||||||
|
"max": "",
|
||||||
|
"recovery": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.PKSXFuaIHUCoH63A",
|
||||||
|
"count": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Summon",
|
||||||
|
"range": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"originItemType": null,
|
"originItemType": null,
|
||||||
"subType": null,
|
"subType": null,
|
||||||
"originId": null,
|
"originId": null,
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,7 @@
|
||||||
"name": "Charcoal Constructs",
|
"name": "Charcoal Constructs",
|
||||||
"type": "feature",
|
"type": "feature",
|
||||||
"system": {
|
"system": {
|
||||||
"description": "<p>Warped animals wreathed in indigo f l ame trample through a point of your choice. All targets within Close range of that point must make an Agility Reaction Roll. Targets who fail take <strong>3d12+3</strong> physical damage. Targets who succeed take half damage instead.</p><p>@Template[type:emanation|range:c]</p><section class=\"secret\" id=\"secret-696PMvOPzHmkdtYc\"><p><em>Are these real animals consumed by the fl ame or merely constructs of the corrupting magic?</em></p></section>",
|
"description": "<p>Warped animals wreathed in indigo flame trample through a point of your choice. All targets within Close range of that point must make an Agility Reaction Roll. Targets who fail take <strong>3d12+3</strong> physical damage. Targets who succeed take half damage instead.</p><p>@Template[type:emanation|range:c]</p><section class=\"secret\" id=\"secret-696PMvOPzHmkdtYc\"><p><em>Are these real animals consumed by the fl ame or merely constructs of the corrupting magic?</em></p></section>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"gbXIaKr8em134IZC": {
|
"gbXIaKr8em134IZC": {
|
||||||
|
|
|
||||||
|
|
@ -467,33 +467,48 @@
|
||||||
"description": "<p><strong>Spend a Fear</strong> to summon an @UUID[Compendium.daggerheart.adversaries.Actor.A0SeeDzwjvqOsyof]{Outer Realms Abomination}, an@UUID[Compendium.daggerheart.adversaries.Actor.ms6nuOl3NFkhPj1k]{Outer Realms Corrupter}, and [[/r 2d6]] @UUID[Compendium.daggerheart.adversaries.Actor.moJhHgKqTKPS2WYS]{Outer Realms Thrall}, who appear at Close range of a chosen PC in defiance of logic and causality. Immediately spotlight one of these adversaries, and you can spend an additional Fear to automatically succeed on that adversary’s standard attack.</p><section class=\"secret\" id=\"secret-psXRRXLoibTKFpaW\"><p><em>What halfconsumed remnants of the shattered world do these monstrosities cast aside in pursuit of living flesh? What jagged refl ections of former personhood do you catch between moments of unquestioning malice?</em></p></section>",
|
"description": "<p><strong>Spend a Fear</strong> to summon an @UUID[Compendium.daggerheart.adversaries.Actor.A0SeeDzwjvqOsyof]{Outer Realms Abomination}, an@UUID[Compendium.daggerheart.adversaries.Actor.ms6nuOl3NFkhPj1k]{Outer Realms Corrupter}, and [[/r 2d6]] @UUID[Compendium.daggerheart.adversaries.Actor.moJhHgKqTKPS2WYS]{Outer Realms Thrall}, who appear at Close range of a chosen PC in defiance of logic and causality. Immediately spotlight one of these adversaries, and you can spend an additional Fear to automatically succeed on that adversary’s standard attack.</p><section class=\"secret\" id=\"secret-psXRRXLoibTKFpaW\"><p><em>What halfconsumed remnants of the shattered world do these monstrosities cast aside in pursuit of living flesh? What jagged refl ections of former personhood do you catch between moments of unquestioning malice?</em></p></section>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"5a8ESNroEQHAm7rO": {
|
"KCzdCu2KhAx9KyhT": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "5a8ESNroEQHAm7rO",
|
"_id": "KCzdCu2KhAx9KyhT",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
"description": "<p><strong>Spend a Fear</strong> to summon an @UUID[Compendium.daggerheart.adversaries.Actor.A0SeeDzwjvqOsyof]{Outer Realms Abomination}, an@UUID[Compendium.daggerheart.adversaries.Actor.ms6nuOl3NFkhPj1k]{Outer Realms Corrupter}, and [[/r 2d6]] @UUID[Compendium.daggerheart.adversaries.Actor.moJhHgKqTKPS2WYS]{Outer Realms Thrall}, who appear at Close range of a chosen PC in defiance of logic and causality. Immediately spotlight one of these adversaries, and you can spend an additional Fear to automatically succeed on that adversary’s standard attack.</p><section class=\"secret\" id=\"secret-ADMZbUwBRqcZNks5\"><p><em>What halfconsumed remnants of the shattered world do these monstrosities cast aside in pursuit of living flesh? What jagged refl ections of former personhood do you catch between moments of unquestioning malice?</em></p></section>",
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [
|
||||||
{
|
{
|
||||||
"scalable": false,
|
"scalable": false,
|
||||||
"key": "fear",
|
"key": "fear",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"step": null
|
"itemId": null,
|
||||||
|
"step": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "",
|
||||||
"recovery": null
|
"recovery": null,
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "any",
|
|
||||||
"amount": null
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.A0SeeDzwjvqOsyof",
|
||||||
|
"count": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.ms6nuOl3NFkhPj1k",
|
||||||
|
"count": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.moJhHgKqTKPS2WYS",
|
||||||
|
"count": "2d6"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Spend Fear",
|
"name": "Spend Fear",
|
||||||
"img": "icons/creatures/unholy/demons-horned-glowing-pink.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -343,11 +343,12 @@
|
||||||
"img": "icons/magic/unholy/barrier-fire-pink.webp",
|
"img": "icons/magic/unholy/barrier-fire-pink.webp",
|
||||||
"range": ""
|
"range": ""
|
||||||
},
|
},
|
||||||
"suFEnfpOfeVRvnJF": {
|
"HG7tbEdlYl3yLQnR": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "suFEnfpOfeVRvnJF",
|
"_id": "HG7tbEdlYl3yLQnR",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
"description": "<p>Summon a @UUID[Compendium.daggerheart.adversaries.Actor.3tqCjDwJAQ7JKqMb]{Minor Demon} within Very Close range of the ritual’s leader.</p>",
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
"originItem": {
|
"originItem": {
|
||||||
"type": "itemCollection"
|
"type": "itemCollection"
|
||||||
|
|
@ -360,13 +361,13 @@
|
||||||
"recovery": null,
|
"recovery": null,
|
||||||
"consumeOnSuccess": false
|
"consumeOnSuccess": false
|
||||||
},
|
},
|
||||||
"effects": [],
|
"summon": [
|
||||||
"target": {
|
{
|
||||||
"type": "any",
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.3tqCjDwJAQ7JKqMb",
|
||||||
"amount": null
|
"count": "1"
|
||||||
},
|
}
|
||||||
|
],
|
||||||
"name": "Summon Demon",
|
"name": "Summon Demon",
|
||||||
"img": "icons/magic/unholy/barrier-fire-pink.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -248,33 +248,31 @@
|
||||||
"description": "<p><strong>Spend 2 Fear</strong> to summon [[/r 1d4+2]] @UUID[Compendium.daggerheart.adversaries.Actor.OsLG2BjaEdTZUJU9]{Fallen Shock Troop} that appear within Close range of the Usurper to assist their divine siege. Immediately spotlight the Shock Troops to use a “Group Attack” action.</p><section class=\"secret\" id=\"secret-QJHdwGNSuTgS59gn\"><p><em>Which High Fallen do these troops serve? Which god’s fl esh do they wish to feast upon?</em></p></section>",
|
"description": "<p><strong>Spend 2 Fear</strong> to summon [[/r 1d4+2]] @UUID[Compendium.daggerheart.adversaries.Actor.OsLG2BjaEdTZUJU9]{Fallen Shock Troop} that appear within Close range of the Usurper to assist their divine siege. Immediately spotlight the Shock Troops to use a “Group Attack” action.</p><section class=\"secret\" id=\"secret-QJHdwGNSuTgS59gn\"><p><em>Which High Fallen do these troops serve? Which god’s fl esh do they wish to feast upon?</em></p></section>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"qIQTEO5t72xFtKYI": {
|
"okcqGrI4rdghugUi": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "qIQTEO5t72xFtKYI",
|
"_id": "okcqGrI4rdghugUi",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
"description": "<p><strong>Spend 2 Fear</strong> to summon [[/r 1d4+2]] @UUID[Compendium.daggerheart.adversaries.Actor.OsLG2BjaEdTZUJU9]{Fallen Shock Troop} that appear within Close range of the Usurper to assist their divine siege. Immediately spotlight the Shock Troops to use a “Group Attack” action.</p><section class=\"secret\" id=\"secret-fNfGy8lT8b7elPcE\"><p><em>Which High Fallen do these troops serve? Which god’s fl esh do they wish to feast upon?</em></p></section>",
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [],
|
||||||
{
|
|
||||||
"scalable": false,
|
|
||||||
"key": "fear",
|
|
||||||
"value": 2,
|
|
||||||
"step": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "",
|
||||||
"recovery": null
|
"recovery": null,
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "self",
|
|
||||||
"amount": null
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.OsLG2BjaEdTZUJU9",
|
||||||
|
"count": "1d4+2"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Spend Fear",
|
"name": "Spend Fear",
|
||||||
"img": "icons/magic/unholy/orb-hands-pink.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,35 @@
|
||||||
"system": {
|
"system": {
|
||||||
"description": "<p>When the PCs enter the raptors’ hunting grounds, two @UUID[Compendium.daggerheart.adversaries.Actor.OMQ0v6PE8s1mSU0K]{Giant Eagles} appear at Very Far range of a chosen PC, identifying the PCs as likely prey. </p><section id=\"secret-aU19zKlmhVBdS2oF\" class=\"secret\"><p><em>How long has it been since the eagles last found prey? Do they have eggs in their nest or unfl edged young?</em></p></section>",
|
"description": "<p>When the PCs enter the raptors’ hunting grounds, two @UUID[Compendium.daggerheart.adversaries.Actor.OMQ0v6PE8s1mSU0K]{Giant Eagles} appear at Very Far range of a chosen PC, identifying the PCs as likely prey. </p><section id=\"secret-aU19zKlmhVBdS2oF\" class=\"secret\"><p><em>How long has it been since the eagles last found prey? Do they have eggs in their nest or unfl edged young?</em></p></section>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {},
|
"actions": {
|
||||||
|
"88MyOC3IRcct6VLk": {
|
||||||
|
"type": "summon",
|
||||||
|
"_id": "88MyOC3IRcct6VLk",
|
||||||
|
"systemPath": "actions",
|
||||||
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
|
"actionType": "action",
|
||||||
|
"cost": [],
|
||||||
|
"uses": {
|
||||||
|
"value": null,
|
||||||
|
"max": "",
|
||||||
|
"recovery": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.OMQ0v6PE8s1mSU0K",
|
||||||
|
"count": "2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Summon",
|
||||||
|
"range": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"originItemType": null,
|
"originItemType": null,
|
||||||
"originId": null,
|
"originId": null,
|
||||||
"featureForm": "reaction"
|
"featureForm": "reaction"
|
||||||
|
|
|
||||||
|
|
@ -360,33 +360,40 @@
|
||||||
"description": "<p><strong>Spend a Fear</strong> to summon a @UUID[Compendium.daggerheart.adversaries.Actor.8KWVLWXFhlY2kYx0]{Glass Snake} within Close range of a chosen PC. The Snake appears in or near the river and immediately takes the spotlight to use their “Spinning Serpent” action.</p><section class=\"secret\" id=\"secret-F8zsJQg3xWOPpH5v\"><p><em>What treasures does the beast have in their burrow? What travelers have already fallen victim to this predator?</em></p></section>",
|
"description": "<p><strong>Spend a Fear</strong> to summon a @UUID[Compendium.daggerheart.adversaries.Actor.8KWVLWXFhlY2kYx0]{Glass Snake} within Close range of a chosen PC. The Snake appears in or near the river and immediately takes the spotlight to use their “Spinning Serpent” action.</p><section class=\"secret\" id=\"secret-F8zsJQg3xWOPpH5v\"><p><em>What treasures does the beast have in their burrow? What travelers have already fallen victim to this predator?</em></p></section>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"Mnp0Yzc7EPVXm8So": {
|
"uY9HMKE4Q5g7bRKg": {
|
||||||
"type": "effect",
|
"type": "summon",
|
||||||
"_id": "Mnp0Yzc7EPVXm8So",
|
"_id": "uY9HMKE4Q5g7bRKg",
|
||||||
"systemPath": "actions",
|
"systemPath": "actions",
|
||||||
"description": "<p><strong>Spend a Fear</strong> to summon a @UUID[Compendium.daggerheart.adversaries.Actor.8KWVLWXFhlY2kYx0]{Glass Snake} within Close range of a chosen PC. The Snake appears in or near the river and immediately takes the spotlight to use their “Spinning Serpent” action.</p><section class=\"secret\" id=\"secret-YIc1Y8jgJKanim7f\"><p><em>What treasures does the beast have in their burrow? What travelers have already fallen victim to this predator?</em></p></section>",
|
"baseAction": false,
|
||||||
|
"description": "",
|
||||||
"chatDisplay": true,
|
"chatDisplay": true,
|
||||||
|
"originItem": {
|
||||||
|
"type": "itemCollection"
|
||||||
|
},
|
||||||
"actionType": "action",
|
"actionType": "action",
|
||||||
"cost": [
|
"cost": [
|
||||||
{
|
{
|
||||||
"scalable": false,
|
"scalable": false,
|
||||||
"key": "fear",
|
"key": "fear",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"step": null
|
"itemId": null,
|
||||||
|
"step": null,
|
||||||
|
"consumeOnSuccess": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"uses": {
|
"uses": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"max": "",
|
"max": "",
|
||||||
"recovery": null
|
"recovery": null,
|
||||||
},
|
"consumeOnSuccess": false
|
||||||
"effects": [],
|
|
||||||
"target": {
|
|
||||||
"type": "self",
|
|
||||||
"amount": null
|
|
||||||
},
|
},
|
||||||
|
"summon": [
|
||||||
|
{
|
||||||
|
"actorUUID": "Compendium.daggerheart.adversaries.Actor.8KWVLWXFhlY2kYx0",
|
||||||
|
"count": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "Spend Fear",
|
"name": "Spend Fear",
|
||||||
"img": "icons/creatures/reptiles/snake-fangs-bite-green-yellow.webp",
|
|
||||||
"range": ""
|
"range": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
50
styles/less/sheets/actions/actions.less
Normal file
50
styles/less/sheets/actions/actions.less
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
.application.daggerheart.dh-style.action-config {
|
||||||
|
.actor-summon-items {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
.actor-summon-line {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
.actor-summon-name {
|
||||||
|
flex: 2;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actor-summon-controls {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.summon-dragger {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 40px;
|
||||||
|
margin-top: 10px;
|
||||||
|
border: 1px dashed light-dark(@dark-blue-50, @beige-50);
|
||||||
|
border-radius: 3px;
|
||||||
|
color: light-dark(@dark-blue-50, @beige-50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -148,7 +148,7 @@
|
||||||
padding: 0 0.375rem;
|
padding: 0 0.375rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
button[data-action=viewParty] {
|
button[data-action='viewParty'] {
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,3 +37,5 @@
|
||||||
@import './items/feature.less';
|
@import './items/feature.less';
|
||||||
@import './items/heritage.less';
|
@import './items/heritage.less';
|
||||||
@import './items/item-sheet-shared.less';
|
@import './items/item-sheet-shared.less';
|
||||||
|
|
||||||
|
@import './actions/actions.less';
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,61 @@
|
||||||
|
|
||||||
.description {
|
.description {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
|
||||||
|
.summons-header {
|
||||||
|
font-size: var(--font-size-14);
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
content: ' ';
|
||||||
|
height: 1px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, light-dark(@dark-blue, @golden) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
background: linear-gradient(90deg, light-dark(@dark-blue, @golden) 0%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.summons-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
.summon-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.summon-label-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ability-card-footer {
|
.ability-card-footer {
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.action-use-target {
|
.action-use-target {
|
||||||
display:flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
|
@ -127,7 +127,6 @@
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip.card-style) {
|
||||||
width: 18rem;
|
width: 18rem;
|
||||||
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||||
outline: 1px solid light-dark(@dark-80, @beige-80);
|
outline: 1px solid light-dark(@dark-80, @beige-80);
|
||||||
box-shadow: 0 0 25px rgba(0, 0, 0, 0.80);
|
box-shadow: 0 0 25px rgba(0, 0, 0, 0.8);
|
||||||
|
|
||||||
.tooltip-title {
|
.tooltip-title {
|
||||||
font-size: var(--font-size-20);
|
font-size: var(--font-size-20);
|
||||||
|
|
@ -235,7 +235,6 @@ aside[role='tooltip'].locked-tooltip:has(div.daggerheart.dh-style.tooltip.card-s
|
||||||
.theme-light aside[role='tooltip'].locked-tooltip:has(div.daggerheart.dh-style.tooltip) {
|
.theme-light aside[role='tooltip'].locked-tooltip:has(div.daggerheart.dh-style.tooltip) {
|
||||||
box-shadow: 0 0 25px @dark-blue-90;
|
box-shadow: 0 0 25px @dark-blue-90;
|
||||||
outline: 1px solid light-dark(@dark-blue, @golden);
|
outline: 1px solid light-dark(@dark-blue, @golden);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#tooltip,
|
#tooltip,
|
||||||
|
|
|
||||||
50
templates/actionTypes/summon.hbs
Normal file
50
templates/actionTypes/summon.hbs
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
<fieldset class="one-column" id="summon-drop-zone" data-key="summon">
|
||||||
|
<legend>
|
||||||
|
{{localize "DAGGERHEART.ACTIONS.TYPES.summon.name"}}
|
||||||
|
</legend>
|
||||||
|
|
||||||
|
<ul class="actor-summon-items">
|
||||||
|
{{#each @root.summons as |summon index|}}
|
||||||
|
<li class="actor-summon-line">
|
||||||
|
<div class="actor-summon-name">
|
||||||
|
<img class="image" src="{{summon.actor.img}}" />
|
||||||
|
<h4 class="h4">
|
||||||
|
{{summon.actor.name}}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="actor-summon-controls">
|
||||||
|
<div class="form-group summon-count-wrapper" data-index="{{index}}">
|
||||||
|
<div class="form-fields">
|
||||||
|
<input type="text" value="{{summon.count}}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<a
|
||||||
|
class='effect-control'
|
||||||
|
data-action='editDoc'
|
||||||
|
data-item-uuid="{{summon.actor.uuid}}"
|
||||||
|
data-tooltip='{{localize "DAGGERHEART.UI.Tooltip.openItemWorld"}}'
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-globe"></i>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
class='effect-control'
|
||||||
|
data-action='removeElement'
|
||||||
|
data-target="summon"
|
||||||
|
data-uuid="{{summon.actor.uuid}}"
|
||||||
|
data-index="{{index}}"
|
||||||
|
data-tooltip='{{localize "CONTROLS.CommonDelete"}}'
|
||||||
|
>
|
||||||
|
<i class='fas fa-trash'></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
<div class="summon-dragger">
|
||||||
|
<span>{{localize "DAGGERHEART.ACTIONS.Settings.summon.dropSummonsHere"}}</span>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</fieldset>
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
class="tab {{this.tabs.config.cssClass}}"
|
class="tab {{this.tabs.config.cssClass}}"
|
||||||
data-group="primary"
|
data-group="primary"
|
||||||
data-tab="config"
|
data-tab="config"
|
||||||
>
|
>
|
||||||
{{> 'systems/daggerheart/templates/actionTypes/uses.hbs' fields=fields.uses.fields source=source.uses}}
|
{{> '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/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/range-target.hbs' fields=(object range=fields.range target=fields.target.fields) source=(object target=source.target range=source.range)}}
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,6 @@
|
||||||
{{#if fields.macro}}{{> 'systems/daggerheart/templates/actionTypes/macro.hbs' fields=fields.macro source=source.macro}}{{/if}}
|
{{#if fields.macro}}{{> 'systems/daggerheart/templates/actionTypes/macro.hbs' fields=fields.macro source=source.macro}}{{/if}}
|
||||||
{{#if fields.effects}}{{> 'systems/daggerheart/templates/actionTypes/effect.hbs' fields=fields.effects.element.fields source=source.effects}}{{/if}}
|
{{#if fields.effects}}{{> 'systems/daggerheart/templates/actionTypes/effect.hbs' fields=fields.effects.element.fields source=source.effects}}{{/if}}
|
||||||
{{#if fields.beastform}}{{> 'systems/daggerheart/templates/actionTypes/beastform.hbs' fields=fields.beastform.fields source=source.beastform}}{{/if}}
|
{{#if fields.beastform}}{{> 'systems/daggerheart/templates/actionTypes/beastform.hbs' fields=fields.beastform.fields source=source.beastform}}{{/if}}
|
||||||
|
{{#if fields.summon}}{{> 'systems/daggerheart/templates/actionTypes/summon.hbs' fields=fields.summon.element.fields source=source.summon}}{{/if}}
|
||||||
{{#if fields.countdown}}{{> 'systems/daggerheart/templates/actionTypes/countdown.hbs' fields=fields.countdown.element.fields source=source.countdown}}{{/if}}
|
{{#if fields.countdown}}{{> 'systems/daggerheart/templates/actionTypes/countdown.hbs' fields=fields.countdown.element.fields source=source.countdown}}{{/if}}
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -8,6 +8,22 @@
|
||||||
</div>
|
</div>
|
||||||
<i class="fa-solid fa-chevron-down"></i>
|
<i class="fa-solid fa-chevron-down"></i>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="description">{{{description}}}</div>
|
<div class="description">
|
||||||
|
{{{description}}}
|
||||||
|
{{#if action.summon}}
|
||||||
|
<div class="summons-header"><span>{{localize "DAGGERHEART.GENERAL.summon.plural"}}</span></div>
|
||||||
|
<div class="summons-container">
|
||||||
|
{{#each action.summon}}
|
||||||
|
<div class="summon-container">
|
||||||
|
<div class="summon-label-container">
|
||||||
|
<img src="{{this.actor.img}}" />
|
||||||
|
<label>{{this.actor.name}}</label>
|
||||||
|
</div>
|
||||||
|
<span># {{this.rolledCount}}</span>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
</details>
|
</details>
|
||||||
</div>
|
</div>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue