This commit is contained in:
Dapoolp 2025-07-24 15:28:43 +02:00
parent 17dd9b1f61
commit 479e147640
25 changed files with 339 additions and 289 deletions

View file

@ -105,7 +105,6 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
if (!!this.action.effects) context.effects = this.action.effects.map(e => this.action.item.effects.get(e._id)); if (!!this.action.effects) context.effects = this.action.effects.map(e => this.action.item.effects.get(e._id));
if (this.action.damage?.hasOwnProperty('includeBase') && this.action.type === 'attack') if (this.action.damage?.hasOwnProperty('includeBase') && this.action.type === 'attack')
context.hasBaseDamage = !!this.action.parent.attack; context.hasBaseDamage = !!this.action.parent.attack;
context.getRealIndex = this.getRealIndex.bind(this);
context.getEffectDetails = this.getEffectDetails.bind(this); context.getEffectDetails = this.getEffectDetails.bind(this);
context.costOptions = this.getCostOptions(); context.costOptions = this.getCostOptions();
context.disableOption = this.disableOption.bind(this); context.disableOption = this.disableOption.bind(this);
@ -147,11 +146,6 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
return filtered; return filtered;
} }
getRealIndex(index) {
const data = this.action.toObject(false);
return data.damage.parts.find(d => d.base) ? index - 1 : index;
}
getEffectDetails(id) { getEffectDetails(id) {
return this.action.item.effects.get(id); return this.action.item.effects.get(id);
} }
@ -199,8 +193,10 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
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(),
data.damage.parts.push({}); part = {};
if(this.action.actor.isNPC) part.value = { multiplier: 'flat' };
data.damage.parts.push(part);
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
} }

View file

@ -283,6 +283,10 @@ export default function DHApplicationMixin(Base) {
{ {
name: 'CONTROLS.CommonEdit', name: 'CONTROLS.CommonEdit',
icon: 'fa-solid fa-pen-to-square', icon: 'fa-solid fa-pen-to-square',
condition: target => {
const doc = getDocFromElement(target);
return !doc.hasOwnProperty('systemPath') || doc.inCollection
},
callback: target => getDocFromElement(target).sheet.render({ force: true }) callback: target => getDocFromElement(target).sheet.render({ force: true })
} }
]; ];

View file

@ -46,8 +46,4 @@ export default class DHAttackAction extends DHDamageAction {
return result; return result;
} }
// get modifiers() {
// return [];
// }
} }

View file

@ -2,6 +2,7 @@ import { DHActionDiceData, DHActionRollData, DHDamageData, DHDamageField, DHReso
import DhpActor from '../../documents/actor.mjs'; import DhpActor from '../../documents/actor.mjs';
import D20RollDialog from '../../applications/dialogs/d20RollDialog.mjs'; import D20RollDialog from '../../applications/dialogs/d20RollDialog.mjs';
import { ActionMixin } from '../fields/actionField.mjs'; import { ActionMixin } from '../fields/actionField.mjs';
import * as ActionFields from '../fields/action/_module.mjs';
const fields = foundry.data.fields; const fields = foundry.data.fields;
@ -18,10 +19,11 @@ const fields = foundry.data.fields;
*/ */
export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel) { export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel) {
static extraSchemas = []; static baseFields = ['cost', 'uses', 'range'];
static extraFields = [];
static defineSchema() { static defineSchema() {
return { const schemaFields = {
_id: new fields.DocumentIdField({ initial: () => foundry.utils.randomID() }), _id: new fields.DocumentIdField({ initial: () => foundry.utils.randomID() }),
systemPath: new fields.StringField({ required: true, initial: 'actions' }), systemPath: new fields.StringField({ required: true, initial: 'actions' }),
type: new fields.StringField({ initial: undefined, readonly: true, required: true }), type: new fields.StringField({ initial: undefined, readonly: true, required: true }),
@ -33,76 +35,25 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
choices: CONFIG.DH.ITEM.actionTypes, choices: CONFIG.DH.ITEM.actionTypes,
initial: 'action', initial: 'action',
nullable: true nullable: true
}), })
cost: new fields.ArrayField(
new fields.SchemaField({
key: new fields.StringField({
nullable: false,
required: true,
initial: 'hope'
}),
keyIsID: new fields.BooleanField(),
value: new fields.NumberField({ nullable: true, initial: 1 }),
scalable: new fields.BooleanField({ initial: false }),
step: new fields.NumberField({ nullable: true, initial: null })
})
),
uses: new fields.SchemaField({
value: new fields.NumberField({ nullable: true, initial: null }),
max: new fields.NumberField({ nullable: true, initial: null }),
recovery: new fields.StringField({
choices: CONFIG.DH.GENERAL.refreshTypes,
initial: null,
nullable: true
})
}),
range: new fields.StringField({
choices: CONFIG.DH.GENERAL.range,
required: false,
blank: true
// initial: null
}),
...this.defineExtraSchema()
}; };
[...this.baseFields, ...extraFields].forEach(s => {
// const clsField =
});
return schemaFields;
} }
static defineExtraSchema() { static defineExtraSchema() {
const extraFields = { const extraFields = {
damage: new DHDamageField(), damage: new DHDamageField(),
roll: new fields.EmbeddedDataField(DHActionRollData), roll: new fields.EmbeddedDataField(DHActionRollData),
save: new fields.SchemaField({ save: new ActionFields.SaveField(),
trait: new fields.StringField({ target: new ActionFields.TargetField(),
nullable: true, effects: new ActionFields.EffectField(),
initial: null,
choices: CONFIG.DH.ACTOR.abilities
}),
difficulty: new fields.NumberField({ nullable: true, initial: 10, integer: true, min: 0 }),
damageMod: new fields.StringField({
initial: CONFIG.DH.ACTIONS.damageOnSave.none.id,
choices: CONFIG.DH.ACTIONS.damageOnSave
})
}),
target: new fields.SchemaField({
type: new fields.StringField({
choices: CONFIG.DH.ACTIONS.targetTypes,
initial: CONFIG.DH.ACTIONS.targetTypes.any.id,
nullable: true,
initial: null
}),
amount: new fields.NumberField({ nullable: true, initial: null, integer: true, min: 0 })
}),
effects: new fields.ArrayField( // ActiveEffect
new fields.SchemaField({
_id: new fields.DocumentIdField(),
onSave: new fields.BooleanField({ initial: false })
})
),
healing: new fields.EmbeddedDataField(DHResourceData), healing: new fields.EmbeddedDataField(DHResourceData),
beastform: new fields.SchemaField({ beastform: new ActionFields.BeastformField()
tierAccess: new fields.SchemaField({
exact: new fields.NumberField({ integer: true, nullable: true, initial: null })
})
})
}, },
extraSchemas = {}; extraSchemas = {};
@ -115,10 +66,6 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
this.img = this.img ?? this.parent?.parent?.img; this.img = this.img ?? this.parent?.parent?.img;
} }
get index() {
return foundry.utils.getProperty(this.parent, this.systemPath).indexOf(this);
}
get id() { get id() {
return this._id; return this._id;
} }

View file

View file

@ -2,3 +2,4 @@ export { ActionCollection } from './actionField.mjs';
export { default as FormulaField } from './formulaField.mjs'; export { default as FormulaField } from './formulaField.mjs';
export { default as ForeignDocumentUUIDField } from './foreignDocumentUUIDField.mjs'; export { default as ForeignDocumentUUIDField } from './foreignDocumentUUIDField.mjs';
export { default as ForeignDocumentUUIDArrayField } from './foreignDocumentUUIDArrayField.mjs'; export { default as ForeignDocumentUUIDArrayField } from './foreignDocumentUUIDArrayField.mjs';
export { default as MappingField } from './mappingField.mjs';

View file

@ -0,0 +1,7 @@
export { default as CostField } from './costField.mjs';
export { default as UsesField } from './usesField.mjs';
export { default as RangeField } from './rangeField.mjs';
export { default as TargetField } from './targetField.mjs';
export { default as EffectField } from './effectField.mjs';
export { default as SaveField } from './saveField.mjs';
export { default as BeastformField } from './beastformField.mjs';

View file

@ -0,0 +1,12 @@
const fields = foundry.data.fields;
export default class BeastformField extends fields.SchemaField {
constructor(options={}, context={}) {
const beastformFields = {
tierAccess: new fields.SchemaField({
exact: new fields.NumberField({ integer: true, nullable: true, initial: null })
})
};
super(beastformFields, options, context);
}
}

View file

@ -0,0 +1,18 @@
const fields = foundry.data.fields;
export default class CostField extends fields.ArrayField {
constructor(options={}, context={}) {
const element = new fields.SchemaField({
key: new fields.StringField({
nullable: false,
required: true,
initial: 'hope'
}),
keyIsID: new fields.BooleanField(),
value: new fields.NumberField({ nullable: true, initial: 1 }),
scalable: new fields.BooleanField({ initial: false }),
step: new fields.NumberField({ nullable: true, initial: null })
});
super(element, options, context);
}
}

View file

@ -0,0 +1,11 @@
const fields = foundry.data.fields;
export default class EffectField extends fields.ArrayField {
constructor(options={}, context={}) {
const element = new fields.SchemaField({
_id: new fields.DocumentIdField(),
onSave: new fields.BooleanField({ initial: false })
});
super(element, options, context);
}
}

View file

@ -0,0 +1,12 @@
const fields = foundry.data.fields;
export default class RangeField extends fields.StringField {
constructor(context={}) {
const options = {
choices: CONFIG.DH.GENERAL.range,
required: false,
blank: true
};
super(options, context);
}
}

View file

View file

@ -0,0 +1,19 @@
const fields = foundry.data.fields;
export default class SaveField extends fields.SchemaField {
constructor(options={}, context={}) {
const saveFields = {
trait: new fields.StringField({
nullable: true,
initial: null,
choices: CONFIG.DH.ACTOR.abilities
}),
difficulty: new fields.NumberField({ nullable: true, initial: 10, integer: true, min: 0 }),
damageMod: new fields.StringField({
initial: CONFIG.DH.ACTIONS.damageOnSave.none.id,
choices: CONFIG.DH.ACTIONS.damageOnSave
})
};
super(saveFields, options, context);
}
}

View file

@ -0,0 +1,16 @@
const fields = foundry.data.fields;
export default class TargetField extends fields.SchemaField {
constructor(options={}, context={}) {
const targetFields = {
type: new fields.StringField({
choices: CONFIG.DH.ACTIONS.targetTypes,
initial: CONFIG.DH.ACTIONS.targetTypes.any.id,
nullable: true,
initial: null
}),
amount: new fields.NumberField({ nullable: true, initial: null, integer: true, min: 0 })
};
super(targetFields, options, context);
}
}

View file

@ -0,0 +1,16 @@
const fields = foundry.data.fields;
export default class UsesField extends fields.SchemaField {
constructor(options={}, context={}) {
const usesFields = {
value: new fields.NumberField({ nullable: true, initial: null }),
max: new fields.NumberField({ nullable: true, initial: null }),
recovery: new fields.StringField({
choices: CONFIG.DH.GENERAL.refreshTypes,
initial: null,
nullable: true
})
};
super(usesFields, options, context);
}
}

View file

@ -1,4 +1,5 @@
import DHActionConfig from "../../applications/sheets-configs/action-config.mjs"; import DHActionConfig from "../../applications/sheets-configs/action-config.mjs";
import MappingField from "./mappingField.mjs";
/** /**
* Specialized collection type for stored actions. * Specialized collection type for stored actions.
@ -56,137 +57,6 @@ export class ActionCollection extends Collection {
/* -------------------------------------------- */ /* -------------------------------------------- */
/**
* A subclass of ObjectField that represents a mapping of keys to the provided DataField type.
*
* @param {DataField} model The class of DataField which should be embedded in this field.
* @param {MappingFieldOptions} [options={}] Options which configure the behavior of the field.
* @property {string[]} [initialKeys] Keys that will be created if no data is provided.
* @property {MappingFieldInitialValueBuilder} [initialValue] Function to calculate the initial value for a key.
* @property {boolean} [initialKeysOnly=false] Should the keys in the initialized data be limited to the keys provided
* by `options.initialKeys`?
*/
export class MappingField extends foundry.data.fields.ObjectField {
constructor(model, options) {
if ( !(model instanceof foundry.data.fields.DataField) ) {
throw new Error("MappingField must have a DataField as its contained element");
}
super(options);
/**
* The embedded DataField definition which is contained in this field.
* @type {DataField}
*/
this.model = model;
model.parent = this;
}
/* -------------------------------------------- */
/** @inheritDoc */
static get _defaults() {
return foundry.utils.mergeObject(super._defaults, {
initialKeys: null,
initialValue: null,
initialKeysOnly: false
});
}
/* -------------------------------------------- */
/** @inheritDoc */
_cleanType(value, options) {
Object.entries(value).forEach(([k, v]) => {
if ( k.startsWith("-=") ) return;
value[k] = this.model.clean(v, options);
});
return value;
}
/* -------------------------------------------- */
/** @inheritDoc */
getInitialValue(data) {
let keys = this.initialKeys;
const initial = super.getInitialValue(data);
if ( !keys || !foundry.utils.isEmpty(initial) ) return initial;
if ( !(keys instanceof Array) ) keys = Object.keys(keys);
for ( const key of keys ) initial[key] = this._getInitialValueForKey(key);
return initial;
}
/* -------------------------------------------- */
/**
* Get the initial value for the provided key.
* @param {string} key Key within the object being built.
* @param {object} [object] Any existing mapping data.
* @returns {*} Initial value based on provided field type.
*/
_getInitialValueForKey(key, object) {
const initial = this.model.getInitialValue();
return this.initialValue?.(key, initial, object) ?? initial;
}
/* -------------------------------------------- */
/** @override */
_validateType(value, options={}) {
if ( foundry.utils.getType(value) !== "Object" ) throw new Error("must be an Object");
const errors = this._validateValues(value, options);
if ( !foundry.utils.isEmpty(errors) ) {
const failure = new foundry.data.validation.DataModelValidationFailure();
failure.elements = Object.entries(errors).map(([id, failure]) => ({ id, failure }));
throw failure.asError();
}
}
/* -------------------------------------------- */
/**
* Validate each value of the object.
* @param {object} value The object to validate.
* @param {object} options Validation options.
* @returns {Record<string, Error>} An object of value-specific errors by key.
*/
_validateValues(value, options) {
const errors = {};
for ( const [k, v] of Object.entries(value) ) {
if ( k.startsWith("-=") ) continue;
const error = this.model.validate(v, options);
if ( error ) errors[k] = error;
}
return errors;
}
/* -------------------------------------------- */
/** @override */
initialize(value, model, options={}) {
if ( !value ) return value;
const obj = {};
const initialKeys = (this.initialKeys instanceof Array) ? this.initialKeys : Object.keys(this.initialKeys ?? {});
const keys = this.initialKeysOnly ? initialKeys : Object.keys(value);
for ( const key of keys ) {
const data = value[key] ?? this._getInitialValueForKey(key, value);
obj[key] = this.model.initialize(data, model, options);
}
return obj;
}
/* -------------------------------------------- */
/** @inheritDoc */
_getField(path) {
if ( path.length === 0 ) return this;
else if ( path.length === 1 ) return this.model;
path.shift();
return this.model._getField(path);
}
}
/* -------------------------------------------- */
/** /**
* Field that stores actions. * Field that stores actions.
*/ */

View file

@ -0,0 +1,128 @@
/**
* A subclass of ObjectField that represents a mapping of keys to the provided DataField type.
*
* @param {DataField} model The class of DataField which should be embedded in this field.
* @param {MappingFieldOptions} [options={}] Options which configure the behavior of the field.
* @property {string[]} [initialKeys] Keys that will be created if no data is provided.
* @property {MappingFieldInitialValueBuilder} [initialValue] Function to calculate the initial value for a key.
* @property {boolean} [initialKeysOnly=false] Should the keys in the initialized data be limited to the keys provided
* by `options.initialKeys`?
*/
export default class MappingField extends foundry.data.fields.ObjectField {
constructor(model, options) {
if ( !(model instanceof foundry.data.fields.DataField) ) {
throw new Error("MappingField must have a DataField as its contained element");
}
super(options);
/**
* The embedded DataField definition which is contained in this field.
* @type {DataField}
*/
this.model = model;
model.parent = this;
}
/* -------------------------------------------- */
/** @inheritDoc */
static get _defaults() {
return foundry.utils.mergeObject(super._defaults, {
initialKeys: null,
initialValue: null,
initialKeysOnly: false
});
}
/* -------------------------------------------- */
/** @inheritDoc */
_cleanType(value, options) {
Object.entries(value).forEach(([k, v]) => {
if ( k.startsWith("-=") ) return;
value[k] = this.model.clean(v, options);
});
return value;
}
/* -------------------------------------------- */
/** @inheritDoc */
getInitialValue(data) {
let keys = this.initialKeys;
const initial = super.getInitialValue(data);
if ( !keys || !foundry.utils.isEmpty(initial) ) return initial;
if ( !(keys instanceof Array) ) keys = Object.keys(keys);
for ( const key of keys ) initial[key] = this._getInitialValueForKey(key);
return initial;
}
/* -------------------------------------------- */
/**
* Get the initial value for the provided key.
* @param {string} key Key within the object being built.
* @param {object} [object] Any existing mapping data.
* @returns {*} Initial value based on provided field type.
*/
_getInitialValueForKey(key, object) {
const initial = this.model.getInitialValue();
return this.initialValue?.(key, initial, object) ?? initial;
}
/* -------------------------------------------- */
/** @override */
_validateType(value, options={}) {
if ( foundry.utils.getType(value) !== "Object" ) throw new Error("must be an Object");
const errors = this._validateValues(value, options);
if ( !foundry.utils.isEmpty(errors) ) {
const failure = new foundry.data.validation.DataModelValidationFailure();
failure.elements = Object.entries(errors).map(([id, failure]) => ({ id, failure }));
throw failure.asError();
}
}
/* -------------------------------------------- */
/**
* Validate each value of the object.
* @param {object} value The object to validate.
* @param {object} options Validation options.
* @returns {Record<string, Error>} An object of value-specific errors by key.
*/
_validateValues(value, options) {
const errors = {};
for ( const [k, v] of Object.entries(value) ) {
if ( k.startsWith("-=") ) continue;
const error = this.model.validate(v, options);
if ( error ) errors[k] = error;
}
return errors;
}
/* -------------------------------------------- */
/** @override */
initialize(value, model, options={}) {
if ( !value ) return value;
const obj = {};
const initialKeys = (this.initialKeys instanceof Array) ? this.initialKeys : Object.keys(this.initialKeys ?? {});
const keys = this.initialKeysOnly ? initialKeys : Object.keys(value);
for ( const key of keys ) {
const data = value[key] ?? this._getInitialValueForKey(key, value);
obj[key] = this.model.initialize(data, model, options);
}
return obj;
}
/* -------------------------------------------- */
/** @inheritDoc */
_getField(path) {
if ( path.length === 0 ) return this;
else if ( path.length === 1 ) return this.model;
path.shift();
return this.model._getField(path);
}
}

View file

@ -69,7 +69,7 @@ export default class DHWeapon extends AttachableItem {
} }
get actionsList() { get actionsList() {
return [this.attack, ...this.actions]; return new Set([this.attack, ...this.actions]);
} }
get customActions() { get customActions() {

View file

@ -125,7 +125,7 @@ export default class DHItem extends foundry.documents.Item {
async use(event) { async use(event) {
const actions = this.system.actionsList; const actions = this.system.actionsList;
if (actions?.size) { if (actions?.size) {
let action = actions.contents[0]; let action = actions.first(0);
if (actions.size > 1 && !event?.shiftKey) { if (actions.size > 1 && !event?.shiftKey) {
// Actions Choice Dialog // Actions Choice Dialog
action = await this.selectActionDialog(event); action = await this.selectActionDialog(event);

View file

@ -9,7 +9,8 @@ export default class RegisterHandlebarsHelpers {
damageFormula: this.damageFormula, damageFormula: this.damageFormula,
damageSymbols: this.damageSymbols, damageSymbols: this.damageSymbols,
rollParsed: this.rollParsed, rollParsed: this.rollParsed,
hasProperty: foundry.utils.hasProperty hasProperty: foundry.utils.hasProperty,
setVar: this.setVar
}); });
} }
static add(a, b) { static add(a, b) {
@ -50,4 +51,8 @@ export default class RegisterHandlebarsHelpers {
const result = itemAbleRollParse(value, actor, item); const result = itemAbleRollParse(value, actor, item);
return isNumerical && !result ? 0 : result; return isNumerical && !result ? 0 : result;
} }
static setVar(name, value, context) {
this[name] = value;
}
} }

View file

@ -346,6 +346,12 @@
&:has(.list-w-img) { &:has(.list-w-img) {
gap: 0; gap: 0;
} }
&.no-style {
border-width: 0;
margin: 0;
padding: 0;
}
} }
.two-columns { .two-columns {

View file

@ -4,90 +4,78 @@
{{localize "DAGGERHEART.GENERAL.damage"}} {{localize "DAGGERHEART.GENERAL.damage"}}
{{#unless (eq path 'system.attack.')}}<a><i class="fa-solid fa-plus icon-button" data-action="addDamage"></i></a>{{/unless}} {{#unless (eq path 'system.attack.')}}<a><i class="fa-solid fa-plus icon-button" data-action="addDamage"></i></a>{{/unless}}
</legend> </legend>
{{#unless (or @root.isNPC path)}} {{#if @root.hasBaseDamage}}
{{#if @root.hasBaseDamage}} {{formField @root.fields.damage.fields.includeBase value=@root.source.damage.includeBase name="damage.includeBase" classes="checkbox" localize=true }}
{{formField @root.fields.damage.fields.includeBase value=@root.source.damage.includeBase name="damage.includeBase" classes="checkbox" localize=true }} {{/if}}
{{/if}}
{{/unless}}
{{#each source.parts as |dmg index|}} {{#each source.parts as |dmg index|}}
{{#if (or @root.isNPC ../path)}} {{#if (and @root.hasBaseDamage @root.source.damage.includeBase)}}
{{formField ../fields.value.fields.custom.fields.enabled value=dmg.value.custom.enabled name=(concat ../path "damage.parts." index ".value.custom.enabled") classes="checkbox"}} {{setVar 'realIndex' (add index -1)}}
<input type="hidden" name="{{../path}}damage.parts.{{index}}.value.multiplier" value="{{dmg.value.multiplier}}">
{{#if dmg.value.custom.enabled}}
{{formField ../fields.value.fields.custom.fields.formula value=dmg.value.custom.formula name=(concat ../path "damage.parts." index ".value.custom.formula") localize=true}}
{{else}}
<div class="nest-inputs">
{{#if @root.isNPC}}{{formField ../fields.value.fields.flatMultiplier value=dmg.value.flatMultiplier name=(concat ../path "damage.parts." index ".value.flatMultiplier") label="DAGGERHEART.ACTIONS.Settings.multiplier" classes="inline-child" localize=true }}{{/if}}
{{formField ../fields.value.fields.dice value=dmg.value.dice name=(concat ../path "damage.parts." index ".value.dice") classes="inline-child"}}
{{formField ../fields.value.fields.bonus value=dmg.value.bonus name=(concat ../path "damage.parts." index ".value.bonus") localize=true classes="inline-child"}}
</div>
{{/if}}
<div class="nest-inputs">
{{formField ../fields.applyTo value=dmg.applyTo name=(concat ../path "damage.parts." realIndex ".applyTo") localize=true}}
{{#if (eq dmg.applyTo 'hitPoints')}}
{{formField ../fields.type value=dmg.type name=(concat ../path "damage.parts." index ".type") localize=true}}
{{/if}}
</div>
{{#if ../horde}}
<fieldset class="one-column">
<legend>{{localize "DAGGERHEART.ACTORS.Adversary.hordeDamage"}}</legend>
<div class="nest-inputs">
{{formField ../fields.valueAlt.fields.flatMultiplier value=dmg.valueAlt.flatMultiplier name=(concat ../path "damage.parts." index ".valueAlt.flatMultiplier") label="DAGGERHEART.ACTIONS.Settings.multiplier" classes="inline-child" localize=true }}
{{formField ../fields.valueAlt.fields.dice value=dmg.valueAlt.dice name=(concat ../path "damage.parts." index ".valueAlt.dice") classes="inline-child"}}
{{formField ../fields.valueAlt.fields.bonus value=dmg.valueAlt.bonus name=(concat ../path "damage.parts." index ".valueAlt.bonus") localize=true classes="inline-child"}}
</div>
</fieldset>
{{/if}}
{{else}} {{else}}
{{#with (@root.getRealIndex index) as | realIndex |}} {{setVar 'realIndex' index}}
<div class="nest-inputs">
<fieldset{{#if dmg.base}} disabled{{/if}} class="one-column">
{{#if (and (not @root.isNPC) @root.hasRoll (not dmg.base))}}
{{formField ../../fields.resultBased value=dmg.resultBased name=(concat "damage.parts." realIndex ".resultBased") localize=true classes="checkbox"}}
{{/if}}
{{#if (and (not @root.isNPC) @root.hasRoll (not dmg.base) dmg.resultBased)}}
<div class="nest-inputs">
<fieldset class="one-column">
<legend>{{localize "DAGGERHEART.GENERAL.withThing" thing=(localize "DAGGERHEART.GENERAL.hope")}}</legend>
{{> formula fields=../../fields.value.fields type=../../fields.type dmg=dmg source=dmg.value target="value" realIndex=realIndex}}
</fieldset>
<fieldset class="one-column">
<legend>{{localize "DAGGERHEART.GENERAL.withThing" thing=(localize "DAGGERHEART.GENERAL.fear")}}</legend>
{{> formula fields=../../fields.valueAlt.fields type=../../fields.type dmg=dmg source=dmg.valueAlt target="valueAlt" realIndex=realIndex}}
</fieldset>
</div>
{{else}}
<fieldset{{#if dmg.base}} disabled{{/if}} class="one-column">
{{> formula fields=../../fields.value.fields type=../fields.type dmg=dmg source=dmg.value target="value" realIndex=realIndex}}
</fieldset>
{{/if}}
<div class="nest-inputs">
{{formField ../../fields.applyTo value=dmg.applyTo name=(concat "damage.parts." realIndex ".applyTo") localize=true}}
{{#if (eq dmg.applyTo 'hitPoints')}}
{{formField ../../fields.type value=dmg.type name=(concat "damage.parts." realIndex ".type") localize=true}}
{{/if}}
</div>
<input type="hidden" name="damage.parts.{{realIndex}}.base" value="{{dmg.base}}">
</fieldset>
{{#unless dmg.base}}<div class="fas fa-trash" data-action="removeDamage" data-index="{{realIndex}}"></div>{{/unless}}
</div>
{{/with}}
{{/if}} {{/if}}
<div class="nest-inputs">
<fieldset{{#if dmg.base}} disabled{{/if}} class="one-column{{#if ../path}} no-style{{/if}}">
{{#if (and (not @root.isNPC) @root.hasRoll (not dmg.base))}}
{{formField ../fields.resultBased value=dmg.resultBased name=(concat "damage.parts." realIndex ".resultBased") localize=true classes="checkbox"}}
{{/if}}
{{#if (and (not @root.isNPC) @root.hasRoll (not dmg.base) dmg.resultBased)}}
<div class="nest-inputs">
<fieldset class="one-column">
<legend>{{localize "DAGGERHEART.GENERAL.withThing" thing=(localize "DAGGERHEART.GENERAL.hope")}}</legend>
{{> formula fields=../fields.value.fields type=../fields.type dmg=dmg source=dmg.value target="value" realIndex=realIndex path=../path}}
</fieldset>
<fieldset class="one-column">
<legend>{{localize "DAGGERHEART.GENERAL.withThing" thing=(localize "DAGGERHEART.GENERAL.fear")}}</legend>
{{> formula fields=../fields.valueAlt.fields type=../fields.type dmg=dmg source=dmg.valueAlt target="valueAlt" realIndex=realIndex path=../path}}
</fieldset>
</div>
{{else}}
<fieldset{{#if dmg.base}} disabled{{/if}} class="one-column">
<legend>{{localize "DAGGERHEART.GENERAL.formula"}}</legend>
{{> formula fields=../fields.value.fields type=../fields.type dmg=dmg source=dmg.value target="value" realIndex=realIndex path=../path}}
</fieldset>
{{/if}}
<div class="nest-inputs">
{{formField ../fields.applyTo value=dmg.applyTo name=(concat ../path "damage.parts." realIndex ".applyTo") localize=true}}
{{#if (eq dmg.applyTo 'hitPoints')}}
{{formField ../fields.type value=dmg.type name=(concat ../path "damage.parts." realIndex ".type") localize=true}}
{{/if}}
</div>
{{#if ../horde}}
<fieldset class="one-column">
<legend>{{localize "DAGGERHEART.ACTORS.Adversary.hordeDamage"}}</legend>
<div class="nest-inputs">
<input type="hidden" name="{{../path}}damage.parts.{{realIndex}}.valueAlt.multiplier" value="flat">
{{formField ../fields.valueAlt.fields.flatMultiplier value=dmg.valueAlt.flatMultiplier name=(concat ../path "damage.parts." realIndex ".valueAlt.flatMultiplier") label="DAGGERHEART.ACTIONS.Settings.multiplier" classes="inline-child" localize=true }}
{{formField ../fields.valueAlt.fields.dice value=dmg.valueAlt.dice name=(concat ../path "damage.parts." realIndex ".valueAlt.dice") classes="inline-child"}}
{{formField ../fields.valueAlt.fields.bonus value=dmg.valueAlt.bonus name=(concat ../path "damage.parts." realIndex ".valueAlt.bonus") localize=true classes="inline-child"}}
</div>
</fieldset>
{{/if}}
<input type="hidden" name="damage.parts.{{realIndex}}.base" value="{{dmg.base}}">
</fieldset>
{{#unless (or dmg.base ../path)}}<div class="fas fa-trash" data-action="removeDamage" data-index="{{realIndex}}"></div>{{/unless}}
</div>
{{/each}} {{/each}}
</fieldset> </fieldset>
{{#*inline "formula"}} {{#*inline "formula"}}
{{#unless dmg.base}} {{#unless dmg.base}}
{{formField fields.custom.fields.enabled value=source.custom.enabled name=(concat "damage.parts." realIndex "." target ".custom.enabled") classes="checkbox"}} {{formField fields.custom.fields.enabled value=source.custom.enabled name=(concat path "damage.parts." realIndex "." target ".custom.enabled") classes="checkbox"}}
{{/unless}} {{/unless}}
{{#if source.custom.enabled}} {{#if source.custom.enabled}}
{{formField fields.custom.fields.formula value=source.custom.formula name=(concat "damage.parts." realIndex "." target ".custom.formula") localize=true}} {{formField fields.custom.fields.formula value=source.custom.formula name=(concat path "damage.parts." realIndex "." target ".custom.formula") localize=true}}
{{else}} {{else}}
<div class="nest-inputs"> <div class="nest-inputs">
{{formField fields.multiplier value=source.multiplier name=(concat "damage.parts." realIndex "." target ".multiplier") localize=true}} {{#unless @root.isNPC}}
{{#if (eq source.multiplier 'flat')}}{{formField fields.flatMultiplier value=source.flatMultiplier name=(concat "damage.parts." realIndex ".flatMultiplier") }}{{/if}} {{formField fields.multiplier value=source.multiplier name=(concat path "damage.parts." realIndex "." target ".multiplier") localize=true}}
{{formField fields.dice value=source.dice name=(concat "damage.parts." realIndex "." target ".dice")}} {{/unless}}
{{formField fields.bonus value=source.bonus name=(concat "damage.parts." realIndex "." target ".bonus") localize=true}} {{#if (eq source.multiplier 'flat')}}{{formField fields.flatMultiplier value=source.flatMultiplier name=(concat ../path "damage.parts." realIndex "." target ".flatMultiplier") }}{{/if}}
{{formField fields.dice value=source.dice name=(concat path "damage.parts." realIndex "." target ".dice")}}
{{formField fields.bonus value=source.bonus name=(concat path "damage.parts." realIndex "." target ".bonus") localize=true}}
</div> </div>
{{/if}} {{/if}}
{{#if @root.isNPC}}
<input type="hidden" name="{{path}}damage.parts.{{realIndex}}.{{target}}.multiplier" value="flat">
{{/if}}
{{/inline}} {{/inline}}

View file

@ -19,7 +19,5 @@
{{/if}} {{/if}}
{{/if}} {{/if}}
</fieldset> </fieldset>
{{#if (eq document.system.type 'horde')}} {{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." horde=(eq document.system.type 'horde')}}
{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." horde=true}}
{{/if}}
</section> </section>