mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-18 16:09:03 +01:00
f
This commit is contained in:
parent
17dd9b1f61
commit
479e147640
25 changed files with 339 additions and 289 deletions
|
|
@ -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) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 })
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,4 @@ export default class DHAttackAction extends DHDamageAction {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get modifiers() {
|
|
||||||
// return [];
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
0
module/data/action/subDatas/rollData.mjs
Normal file
0
module/data/action/subDatas/rollData.mjs
Normal 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';
|
||||||
|
|
|
||||||
7
module/data/fields/action/_module.mjs
Normal file
7
module/data/fields/action/_module.mjs
Normal 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';
|
||||||
12
module/data/fields/action/beastformField.mjs
Normal file
12
module/data/fields/action/beastformField.mjs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
module/data/fields/action/costField.mjs
Normal file
18
module/data/fields/action/costField.mjs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
0
module/data/fields/action/damageField.mjs
Normal file
0
module/data/fields/action/damageField.mjs
Normal file
11
module/data/fields/action/effectField.mjs
Normal file
11
module/data/fields/action/effectField.mjs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
0
module/data/fields/action/healingField.mjs
Normal file
0
module/data/fields/action/healingField.mjs
Normal file
12
module/data/fields/action/rangeField.mjs
Normal file
12
module/data/fields/action/rangeField.mjs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
0
module/data/fields/action/rollField.mjs
Normal file
0
module/data/fields/action/rollField.mjs
Normal file
19
module/data/fields/action/saveField.mjs
Normal file
19
module/data/fields/action/saveField.mjs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
module/data/fields/action/targetField.mjs
Normal file
16
module/data/fields/action/targetField.mjs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
module/data/fields/action/usesField.mjs
Normal file
16
module/data/fields/action/usesField.mjs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
128
module/data/fields/mappingField.mjs
Normal file
128
module/data/fields/mappingField.mjs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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}}
|
||||||
|
|
@ -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>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue