Compare commits

..

No commits in common. "329d820aab0ce538ab4c1696afa27b1e4c827ad4" and "3840f39c9791d441073a02e83a1252d7fc438460" have entirely different histories.

19 changed files with 148 additions and 211 deletions

View file

@ -1451,7 +1451,7 @@
}, },
"triggerType": "Trigger Type", "triggerType": "Trigger Type",
"triggeringActorType": "Triggering Actor Type", "triggeringActorType": "Triggering Actor Type",
"triggerError": "{trigger} trigger on {item}({itemUuid}) failed for {actor}. It's probably configured wrong." "triggerError": "{trigger} trigger failed for {actor}. It's probably configured wrong."
}, },
"WeaponFeature": { "WeaponFeature": {
"barrier": { "barrier": {

View file

@ -160,7 +160,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
} }
if (rest.hasOwnProperty('trait')) { if (rest.hasOwnProperty('trait')) {
this.config.roll.trait = rest.trait; this.config.roll.trait = rest.trait;
if (!this.config.source.item && this.config.roll.trait) if (!this.config.source.item)
this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
ability: game.i18n.localize(abilities[this.config.roll.trait]?.label) ability: game.i18n.localize(abilities[this.config.roll.trait]?.label)
}); });
@ -225,6 +225,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
} }
static async submitRoll(event) { static async submitRoll(event) {
event.preventDefault();
await this.close({ submitted: true }); await this.close({ submitted: true });
} }

View file

@ -10,7 +10,11 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
actions: { actions: {
addExperience: DHAdversarySettings.#addExperience, addExperience: DHAdversarySettings.#addExperience,
removeExperience: DHAdversarySettings.#removeExperience removeExperience: DHAdversarySettings.#removeExperience
} },
dragDrop: [
{ dragSelector: null, dropSelector: '.tab.features' },
{ dragSelector: '.feature-item', dropSelector: null }
]
}; };
/**@override */ /**@override */
@ -34,8 +38,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
}, },
features: { features: {
id: 'features', id: 'features',
template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs', template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs'
scrollable: ['']
} }
}; };
@ -51,16 +54,12 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
async _prepareContext(options) { async _prepareContext(options) {
const context = await super._prepareContext(options); const context = await super._prepareContext(options);
// Get feature groups. Uncategorized go to actions const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm);
const featureFormsTypes = ['passive', 'action', 'reaction']; context.features = context.document.system.features.sort((a, b) =>
const features = this.document.system.features.sort((a, b) => a.sort - b.sort); a.system.featureForm !== b.system.featureForm
const featureGroups = featureFormsTypes.map(t => ({ ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
featureForm: t, : a.sort - b.sort
label: _loc(CONFIG.DH.ITEM.featureForm[t]), );
features: features.filter(f => f.system.featureForm === t)
}));
featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm)));
context.featureGroups = featureGroups;
return context; return context;
} }

View file

@ -32,13 +32,11 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
}, },
features: { features: {
id: 'features', id: 'features',
template: 'systems/daggerheart/templates/sheets-settings/environment-settings/features.hbs', template: 'systems/daggerheart/templates/sheets-settings/environment-settings/features.hbs'
scrollable: ['']
}, },
adversaries: { adversaries: {
id: 'adversaries', id: 'adversaries',
template: 'systems/daggerheart/templates/sheets-settings/environment-settings/adversaries.hbs', template: 'systems/daggerheart/templates/sheets-settings/environment-settings/adversaries.hbs'
scrollable: ['']
} }
}; };
@ -54,16 +52,12 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
async _prepareContext(options) { async _prepareContext(options) {
const context = await super._prepareContext(options); const context = await super._prepareContext(options);
// Get feature groups. Uncategorized go to actions const featureForms = ['passive', 'action', 'reaction'];
const featureFormsTypes = ['passive', 'action', 'reaction']; context.features = context.document.system.features.sort((a, b) =>
const features = this.document.system.features.sort((a, b) => a.sort - b.sort); a.system.featureForm !== b.system.featureForm
const featureGroups = featureFormsTypes.map(t => ({ ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
featureForm: t, : a.sort - b.sort
label: _loc(CONFIG.DH.ITEM.featureForm[t]), );
features: features.filter(f => f.system.featureForm === t)
}));
featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm)));
context.featureGroups = featureGroups;
return context; return context;
} }

View file

@ -27,8 +27,7 @@ export default class DHNPCSettings extends DHBaseActorSettings {
}, },
features: { features: {
id: 'features', id: 'features',
template: 'systems/daggerheart/templates/sheets-settings/npc-settings/features.hbs', template: 'systems/daggerheart/templates/sheets-settings/npc-settings/features.hbs'
scrollable: ['']
} }
}; };
@ -44,16 +43,12 @@ export default class DHNPCSettings extends DHBaseActorSettings {
async _prepareContext(options) { async _prepareContext(options) {
const context = await super._prepareContext(options); const context = await super._prepareContext(options);
// Get feature groups. Uncategorized go to actions const featureForms = ['passive', 'action', 'reaction'];
const featureFormsTypes = ['passive', 'action', 'reaction']; context.features = context.document.system.features.sort((a, b) =>
const features = this.document.system.features.sort((a, b) => a.sort - b.sort); a.system.featureForm !== b.system.featureForm
const featureGroups = featureFormsTypes.map(t => ({ ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
featureForm: t, : a.sort - b.sort
label: _loc(CONFIG.DH.ITEM.featureForm[t]), );
features: features.filter(f => f.system.featureForm === t)
}));
featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm)));
context.featureGroups = featureGroups;
return context; return context;
} }

View file

@ -25,7 +25,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2
}, },
dragDrop: [ dragDrop: [
{ dragSelector: null, dropSelector: '.tab.features' }, { dragSelector: null, dropSelector: '.tab.features' },
{ dragSelector: '.feature-item, .inventory-item[data-type="feature"]', dropSelector: null } { dragSelector: '.feature-item', dropSelector: null }
] ]
}; };
@ -77,7 +77,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2
} }
async _onDragStart(event) { async _onDragStart(event) {
const featureItemEl = event.currentTarget.closest('.feature-item, .inventory-item[data-type="feature"]'); const featureItemEl = event.currentTarget.closest('.feature-item');
const feature = this.actor.items.get(featureItemEl?.dataset.itemId); const feature = this.actor.items.get(featureItemEl?.dataset.itemId);
if (feature && event.target.closest('.tab.features')) { if (feature && event.target.closest('.tab.features')) {
const featureData = { ...feature.toDragData(), fromInternal: true }; const featureData = { ...feature.toDragData(), fromInternal: true };
@ -100,7 +100,4 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2
await this.actor.createEmbeddedDocuments('Item', [itemData]); await this.actor.createEmbeddedDocuments('Item', [itemData]);
} }
} }
/** Setting sheets do not auto extend */
async _autoExpandDescriptions() {}
} }

View file

@ -4,7 +4,6 @@ import { getDocFromElement, getDocFromElementSync, tagifyElement } from '../../.
const typeSettingsMap = { const typeSettingsMap = {
character: 'extendCharacterDescriptions', character: 'extendCharacterDescriptions',
adversary: 'extendAdversaryDescriptions', adversary: 'extendAdversaryDescriptions',
npc: 'extendAdversaryDescriptions',
environment: 'extendEnvironmentDescriptions', environment: 'extendEnvironmentDescriptions',
ancestry: 'extendItemDescriptions', ancestry: 'extendItemDescriptions',
community: 'extendItemDescriptions', community: 'extendItemDescriptions',
@ -263,7 +262,7 @@ export default function DHApplicationMixin(Base) {
if (!!this.options.contextMenus.length) this._createContextMenus(); if (!!this.options.contextMenus.length) this._createContextMenus();
this._autoExpandDescriptions(context); this.#autoExtendDescriptions(context);
} }
/** @inheritDoc */ /** @inheritDoc */
@ -518,7 +517,7 @@ export default function DHApplicationMixin(Base) {
const doc = await getDocFromElement(target), const doc = await getDocFromElement(target),
action = doc?.system?.attack ?? doc; action = doc?.system?.attack ?? doc;
const config = action.prepareConfig(event); const config = action.prepareConfig(event);
config.effects = await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects( config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects(
this.document, this.document,
doc doc
); );
@ -631,9 +630,8 @@ export default function DHApplicationMixin(Base) {
/** /**
* Extend inventory description when enabled in settings. * Extend inventory description when enabled in settings.
* @returns {Promise<void>} * @returns {Promise<void>}
* @protected
*/ */
async _autoExpandDescriptions(context) { async #autoExtendDescriptions(context) {
const inventoryItems = this.element.querySelectorAll('.inventory-item[data-item-uuid]'); const inventoryItems = this.element.querySelectorAll('.inventory-item[data-item-uuid]');
for (const el of inventoryItems) { for (const el of inventoryItems) {
// Get the doc uuid from the element // Get the doc uuid from the element
@ -736,7 +734,7 @@ export default function DHApplicationMixin(Base) {
* @type {ApplicationClickAction} * @type {ApplicationClickAction}
*/ */
static async #onCreateDoc(event, target) { static async #onCreateDoc(event, target) {
const { documentClass, type, inVault, disabled, featureForm } = target.dataset; const { documentClass, type, inVault, disabled } = target.dataset;
const parentIsItem = this.document.documentName === 'Item'; const parentIsItem = this.document.documentName === 'Item';
const featureOnCharacter = this.document.parent?.type === 'character' && type === 'feature'; const featureOnCharacter = this.document.parent?.type === 'character' && type === 'feature';
const parent = featureOnCharacter const parent = featureOnCharacter
@ -754,7 +752,6 @@ export default function DHApplicationMixin(Base) {
identifier: this.document.system.isMulticlass ? 'multiclass' : null identifier: this.document.system.isMulticlass ? 'multiclass' : null
}; };
} }
if (featureForm) systemData.featureForm = featureForm;
const cls = const cls =
type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass); type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass);

View file

@ -212,7 +212,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
const doc = await getDocFromElement(target), const doc = await getDocFromElement(target),
action = doc?.system?.attack ?? doc; action = doc?.system?.attack ?? doc;
const config = action.prepareConfig(event); const config = action.prepareConfig(event);
config.effects = await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects( config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects(
this.document, this.document,
doc doc
); );

View file

@ -342,31 +342,29 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
* Sends updates of the countdowns to the GM player. Since this is asynchronous, be sure to * Sends updates of the countdowns to the GM player. Since this is asynchronous, be sure to
* update all the countdowns at the same time. * update all the countdowns at the same time.
* *
* @param {...(string | { type: string; undo?: boolean })} progressTypes Countdowns to be updated * @param {...any} progressTypes Countdowns to be updated
*/ */
static async updateCountdowns(...progressTypes) { static async updateCountdowns(...progressTypes) {
progressTypes = progressTypes.map(p => typeof p === 'string' ? { type: p } : p);
const { countdownAutomation } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); const { countdownAutomation } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation);
if (!countdownAutomation) return; if (!countdownAutomation) return;
const countdownSetting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); const countdownSetting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
const updatedCountdowns = Object.keys(countdownSetting.countdowns).reduce((acc, key) => { const updatedCountdowns = Object.keys(countdownSetting.countdowns).reduce((acc, key) => {
const countdown = countdownSetting.countdowns[key]; const countdown = countdownSetting.countdowns[key];
const progressData = progressTypes.find(x => x.type === countdown.progress.type); if (progressTypes.indexOf(countdown.progress.type) !== -1 && countdown.progress.current > 0) {
if (progressData && countdown.progress.current > 0) { acc.push(key);
acc[key] = { value: progressData.undo ? 1 : -1 };
} }
return acc; return acc;
}, {}); }, []);
const countdownData = countdownSetting.toObject(); const countdownData = countdownSetting.toObject();
const settings = { const settings = {
...countdownData, ...countdownData,
countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => { countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => {
const countdown = foundry.utils.deepClone(countdownData.countdowns[key]); const countdown = foundry.utils.deepClone(countdownData.countdowns[key]);
if (updatedCountdowns[key]) { if (updatedCountdowns.includes(key)) {
countdown.progress.current += updatedCountdowns[key].value; countdown.progress.current -= 1;
} }
acc[key] = countdown; acc[key] = countdown;

View file

@ -228,8 +228,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
let config = this.prepareConfig(event, configOptions); let config = this.prepareConfig(event, configOptions);
if (!config) return; if (!config) return;
config.effects = config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects(this.actor, this.item);
await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects(this.actor, this.item);
if (Hooks.call(`${CONFIG.DH.id}.preUseAction`, this, config) === false) return; if (Hooks.call(`${CONFIG.DH.id}.preUseAction`, this, config) === false) return;
@ -334,43 +333,27 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
} }
/** /**
* Get the all potentially applicable effects on the actor for the action's RollDialog * Get the all potentially applicable effects on the actor
* @param {DHActor} actor The actor performing the action * @param {DHActor} actor The actor performing the action
* @param {DHItem|DhActor} effectParent The parent of the effect * @param {DHItem|DhActor} effectParent The parent of the effect
* @returns {DhActiveEffect[]} * @returns {DhActiveEffect[]}
*/ */
static async getActionRelevantEffects(actor, effectParent) { static async getEffects(actor, effectParent) {
if (!actor) return []; if (!actor) return [];
// Changes on weapon effects are not typically only applicable to show in the roll dialog for the weapon itself return Array.from(await actor.allApplicableEffects({ noTransferArmor: true, noSelfArmor: true })).filter(
// The exemptions to this rule are listed below effect => {
const weaponTransferredEffectKeys = [ /* Effects on weapons only ever apply for the weapon itself */
'system.bonuses.roll.spellcast.bonus'
];
return Array.from(await actor.allApplicableEffects({ noTransferArmor: true, noSelfArmor: true })).reduce(
(acc, effect) => {
const effectData = effect.toObject();
/* Effects on weapons only ever apply for the weapon itself, with a few defined exceptions */
if (effect.parent.type === 'weapon') { if (effect.parent.type === 'weapon') {
/* Unless they're secondary - then they apply only to other primary weapons */ /* Unless they're secondary - then they apply only to other primary weapons */
if (effect.parent.system.secondary) { if (effect.parent.system.secondary) {
if (effectParent?.type !== 'weapon' || effectParent?.system.secondary) { if (effectParent?.type !== 'weapon' || effectParent?.system.secondary) return false;
effectData.system.changes = } else if (effectParent?.id !== effect.parent.id) return false;
effectData.system.changes.filter(x => weaponTransferredEffectKeys.includes(x.key));
}
} else if (effectParent?.id !== effect.parent.id) {
effectData.system.changes =
effectData.system.changes.filter(x => weaponTransferredEffectKeys.includes(x.key));
}
} }
if (!effect.isSuppressed) { return !effect.isSuppressed;
acc.push(effectData); }
} );
return acc;
}, []);
} }
/** /**

View file

@ -150,14 +150,11 @@ export default class RegisteredTriggers extends Map {
const result = await command(...args); const result = await command(...args);
if (result?.updates?.length) updates.push(...result.updates); if (result?.updates?.length) updates.push(...result.updates);
} catch { } catch {
const item = await foundry.utils.fromUuid(itemUuid);
const triggerName = game.i18n.localize(triggerData.label); const triggerName = game.i18n.localize(triggerData.label);
console.error( ui.notifications.error(
game.i18n.format('DAGGERHEART.CONFIG.Triggers.triggerError', { game.i18n.format('DAGGERHEART.CONFIG.Triggers.triggerError', {
trigger: triggerName, trigger: triggerName,
actor: currentActor?.name, actor: currentActor?.name
item: item?.name ?? '<Missing Item>',
itemUuid: item?.uuid ?? '<Missing UUID>'
}) })
); );
} }

View file

@ -1,28 +1,19 @@
import { ResourceUpdateMap } from '../data/action/baseAction.mjs'; import { ResourceUpdateMap } from '../data/action/baseAction.mjs';
export function updateResourcesForDualityReroll(oldDuality, newDuality, actor) { export function updateResourcesForDualityReroll(oldDuality, newDuality, actor) {
const { hopeFear } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation);
if (game.user.isGM ? !hopeFear.gm : !hopeFear.players) return;
const updates = [];
const hope = (newDuality >= 0 ? 1 : 0) - (oldDuality >= 0 ? 1 : 0); const hope = (newDuality >= 0 ? 1 : 0) - (oldDuality >= 0 ? 1 : 0);
const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0); const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0);
const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0); const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0);
const { hopeFear, countdownAutomation } = if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true });
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true });
if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true });
if (game.user.isGM ? hopeFear.gm : hopeFear.players) { const resourceUpdates = new ResourceUpdateMap(actor);
const updates = []; resourceUpdates.addResources(updates);
if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true }); resourceUpdates.updateResources();
if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true });
if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true })
const resourceUpdates = new ResourceUpdateMap(actor);
resourceUpdates.addResources(updates);
resourceUpdates.updateResources();
}
if (countdownAutomation && fear !== 0) {
game.system.api.applications.ui.DhCountdowns.updateCountdowns({
type: CONFIG.DH.GENERAL.countdownProgressionTypes.fear.id,
undo: fear === 1 ? false : true
});
}
} }

View file

@ -549,7 +549,7 @@ export default class DhpActor extends Actor {
headerTitle: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { headerTitle: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
ability: abilityLabel ability: abilityLabel
}), }),
effects: await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects(this), effects: await game.system.api.data.actions.actionsTypes.base.getEffects(this),
roll: { roll: {
trait: trait, trait: trait,
type: 'trait' type: 'trait'

View file

@ -167,7 +167,7 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
if (this.system.action) { if (this.system.action) {
const actor = await foundry.utils.fromUuid(config.source.actor); const actor = await foundry.utils.fromUuid(config.source.actor);
const item = actor?.items.get(config.source.item) ?? null; const item = actor?.items.get(config.source.item) ?? null;
config.effects = await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects(actor, item); config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects(actor, item);
await this.system.action.workflow.get('damage')?.execute(config, this._id, true); await this.system.action.workflow.get('damage')?.execute(config, this._id, true);
} }
} }

View file

@ -2,7 +2,7 @@
"id": "daggerheart", "id": "daggerheart",
"title": "Daggerheart", "title": "Daggerheart",
"description": "An unofficial implementation of the Daggerheart system", "description": "An unofficial implementation of the Daggerheart system",
"version": "2.4.0", "version": "2.3.4",
"compatibility": { "compatibility": {
"minimum": "14.364", "minimum": "14.364",
"verified": "14.364", "verified": "14.364",
@ -10,7 +10,7 @@
}, },
"url": "https://github.com/Foundryborne/daggerheart", "url": "https://github.com/Foundryborne/daggerheart",
"manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/v14/system.json", "manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/v14/system.json",
"download": "https://github.com/Foundryborne/daggerheart/releases/download/2.4.0/system.zip", "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.3.4/system.zip",
"authors": [ "authors": [
{ {
"name": "WBHarry" "name": "WBHarry"

View file

@ -3,31 +3,27 @@
data-tab='{{tabs.features.id}}' data-tab='{{tabs.features.id}}'
data-group='{{tabs.features.group}}' data-group='{{tabs.features.group}}'
> >
{{#each featureGroups as |group|}} <button type="button" class="add-feature-btn" data-action="createDoc" data-document-class="Item" data-type="feature">
<fieldset> {{localize "DOCUMENT.New" type=(localize "TYPES.Item.feature")}}
<legend> </button>
{{group.label}} <fieldset>
<a data-action="createDoc" data-document-class="Item" data-type="feature" data-tooltip="{{localize 'DOCUMENT.Create' type=(localize "TYPES.Item.feature")}}" data-feature-form="{{group.featureForm}}"> <legend>{{localize tabs.features.label}}</legend>
<i class="fa-solid fa-plus icon-button"></i> <ul class="feature-list">
</a> {{#each @root.features as |feature|}}
</legend> <li class="feature-item" data-item-id="{{feature.id}}" draggable="true">
<ul class="feature-list"> <img src="{{feature.img}}" alt="">
{{#each group.features as |feature|}} <div class="label">
{{> 'daggerheart.inventory-item' <span>{{feature.name}}</span>
item=feature </div>
type='feature' <div class="controls">
actorType=@root.document.type <a data-action="editDoc" data-item-uuid="{{feature.uuid}}" data-tooltip="{{localize 'CONTROLS.CommonEdit'}}"><i class="fa-solid fa-pen-to-square"></i></a>
hideTags=true <a data-action="deleteDoc" data-item-uuid="{{feature.uuid}}" data-tooltip="{{localize 'CONTROLS.CommonDelete'}}"><i class="fa-solid fa-trash"></i></a>
hideContextMenu=true </div>
hideResources=true </li>
showActions=false {{/each}}
hideTooltip=true </ul>
}} <div class="features-dragger">
{{/each}} <span>{{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}}</span>
</ul> </div>
</fieldset> </fieldset>
{{/each}}
<div class="features-dragger">
<span>{{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}}</span>
</div>
</section> </section>

View file

@ -3,31 +3,24 @@
data-tab='{{tabs.features.id}}' data-tab='{{tabs.features.id}}'
data-group='{{tabs.features.group}}' data-group='{{tabs.features.group}}'
> >
{{#each featureGroups as |group|}} <button type="button" class="add-feature-btn" data-action="createDoc" data-document-class="Item" data-type="feature">
<fieldset> {{localize "DOCUMENT.New" type=(localize "TYPES.Item.feature")}}
<legend> </button>
{{group.label}} <fieldset>
<a data-action="createDoc" data-document-class="Item" data-type="feature" data-tooltip="{{localize 'DOCUMENT.Create' type=(localize "TYPES.Item.feature")}}" data-feature-form="{{group.featureForm}}"> <legend>{{localize tabs.features.label}}</legend>
<i class="fa-solid fa-plus icon-button"></i> <ul class="feature-list">
</a> {{#each @root.features as |feature|}}
</legend> <li class="feature-item" data-item-id="{{feature.id}}">
<ul class="feature-list"> <img src="{{feature.img}}" alt="">
{{#each group.features as |feature|}} <div class="label">
{{> 'daggerheart.inventory-item' <span>{{feature.name}}</span>
item=feature </div>
type='feature' <div class="controls">
actorType=@root.document.type <a data-action="editDoc" data-item-uuid="{{feature.uuid}}" data-tooltip="{{localize 'CONTROLS.CommonEdit'}}"><i class="fa-solid fa-pen-to-square"></i></a>
hideTags=true <a data-action="deleteDoc" data-item-uuid="{{feature.uuid}}" data-tooltip="{{localize 'CONTROLS.CommonDelete'}}"><i class="fa-solid fa-trash"></i></a>
hideContextMenu=true </div>
hideResources=true </li>
showActions=false {{/each}}
hideTooltip=true </ul>
}} </fieldset>
{{/each}}
</ul>
</fieldset>
{{/each}}
<div class="features-dragger">
<span>{{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}}</span>
</div>
</section> </section>

View file

@ -3,31 +3,27 @@
data-tab='{{tabs.features.id}}' data-tab='{{tabs.features.id}}'
data-group='{{tabs.features.group}}' data-group='{{tabs.features.group}}'
> >
{{#each featureGroups as |group|}} <button type="button" class="add-feature-btn" data-action="createDoc" data-document-class="Item" data-type="feature">
<fieldset> {{localize "DOCUMENT.New" type=(localize "TYPES.Item.feature")}}
<legend> </button>
{{group.label}} <fieldset>
<a data-action="createDoc" data-document-class="Item" data-type="feature" data-tooltip="{{localize 'DOCUMENT.Create' type=(localize "TYPES.Item.feature")}}" data-feature-form="{{group.featureForm}}"> <legend>{{localize tabs.features.label}}</legend>
<i class="fa-solid fa-plus icon-button"></i> <ul class="feature-list">
</a> {{#each @root.features as |feature|}}
</legend> <li class="feature-item" data-item-id="{{feature.id}}" draggable="true">
<ul class="feature-list"> <img src="{{feature.img}}" alt="">
{{#each group.features as |feature|}} <div class="label">
{{> 'daggerheart.inventory-item' <span>{{feature.name}}</span>
item=feature </div>
type='feature' <div class="controls">
actorType=@root.document.type <a data-action="editDoc" data-item-uuid="{{feature.uuid}}" data-tooltip="{{localize 'CONTROLS.CommonEdit'}}"><i class="fa-solid fa-pen-to-square"></i></a>
hideTags=true <a data-action="deleteDoc" data-item-uuid="{{feature.uuid}}" data-tooltip="{{localize 'CONTROLS.CommonDelete'}}"><i class="fa-solid fa-trash"></i></a>
hideContextMenu=true </div>
hideResources=true </li>
showActions=false {{/each}}
hideTooltip=true </ul>
}} <div class="features-dragger">
{{/each}} <span>{{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}}</span>
</ul> </div>
</fieldset> </fieldset>
{{/each}}
<div class="features-dragger">
<span>{{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}}</span>
</div>
</section> </section>

View file

@ -27,17 +27,17 @@ Parameters:
> >
<div class="inventory-item-header {{#if hideContextMenu}}padded{{/if}}" {{#unless noExtensible}}data-action="toggleExtended" {{/unless}}> <div class="inventory-item-header {{#if hideContextMenu}}padded{{/if}}" {{#unless noExtensible}}data-action="toggleExtended" {{/unless}}>
{{!-- Image --}} {{!-- Image --}}
<div class="img-portait" draggable="true" <div class="img-portait" data-action='{{ifThen item.usable "useItem" (ifThen
{{#unless (eq showActions false)}}data-action='{{ifThen item.usable "useItem" (ifThen (hasProperty item "toChat" ) "toChat" "editDoc" ) }}'{{/unless}} (hasProperty item "toChat" ) "toChat" "editDoc" ) }}' {{#unless hideTooltip}} {{#if (eq type 'attack' )}}
{{#unless hideTooltip}} {{#if (eq type 'attack' )}} data-tooltip="#attack#{{item.actor.uuid}}" {{else}} data-tooltip="#item#{{item.uuid}}" {{/if}} {{/unless}}> data-tooltip="#attack#{{item.actor.uuid}}" {{else}} data-tooltip="#item#{{item.uuid}}" {{/if}} {{/unless}} draggable="true">
<img src="{{item.img}}" class="item-img {{#if isActor}}actor-img{{/if}}" /> <img src="{{item.img}}" class="item-img {{#if isActor}}actor-img{{/if}}" />
{{#if (and item.usable (ne showActions false))}} {{#if item.usable}}
{{#if @root.isNPC}} {{#if @root.isNPC}}
<img class="roll-img d20" src="systems/daggerheart/assets/icons/dice/default/d20.svg" alt="d20"> <img class="roll-img d20" src="systems/daggerheart/assets/icons/dice/default/d20.svg" alt="d20">
{{else}} {{else}}
<img class="roll-img duality" src="systems/daggerheart/assets/icons/dice/duality/DualityBW.svg" alt="2d12"> <img class="roll-img duality" src="systems/daggerheart/assets/icons/dice/duality/DualityBW.svg" alt="2d12">
{{/if}}
{{/if}} {{/if}}
{{/if}}
</div> </div>
{{!-- Name & Tags --}} {{!-- Name & Tags --}}
@ -46,10 +46,10 @@ Parameters:
<span class="item-name">{{localize item.name}} {{#unless (or noExtensible (not item.system.description))}}<span class="expanded-icon"><i class="fa-solid fa-expand"></i></span>{{/unless}}</span> <span class="item-name">{{localize item.name}} {{#unless (or noExtensible (not item.system.description))}}<span class="expanded-icon"><i class="fa-solid fa-expand"></i></span>{{/unless}}</span>
{{!-- Tags Start --}} {{!-- Tags Start --}}
{{#if (not hideTags)}} {{#if (not ../hideTags)}}
{{#> "systems/daggerheart/templates/sheets/global/partials/item-tags.hbs" item}} {{#> "systems/daggerheart/templates/sheets/global/partials/item-tags.hbs" item}}
{{#if (eq ../type 'feature')}} {{#if (eq ../type 'feature')}}
{{#if (and system.featureForm (ne @root.document.type "character"))}} {{#if (and system.featureForm (or (eq @root.document.type "adversary") (eq @root.document.type "environment")))}}
<div class="tag feature-form"> <div class="tag feature-form">
<span class="recall-value">{{localize (concat "DAGGERHEART.CONFIG.FeatureForm." system.featureForm)}}</span> <span class="recall-value">{{localize (concat "DAGGERHEART.CONFIG.FeatureForm." system.featureForm)}}</span>
</div> </div>