mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-07 22:46:12 +01:00
Fix conflicts
This commit is contained in:
commit
4a044db77f
35 changed files with 1148 additions and 290 deletions
|
|
@ -86,11 +86,11 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
static async updateForm(event, _, formData) {
|
||||
const submitData = this._prepareSubmitData(event, formData),
|
||||
data = foundry.utils.expandObject(foundry.utils.mergeObject(this.action.toObject(), submitData)),
|
||||
newActions = this.action.parent.actions.map(x => x.toObject()); // Find better way
|
||||
newActions = foundry.utils.getProperty(this.action.parent, this.action.systemPath).map(x => x.toObject()); // Find better way
|
||||
if (!newActions.findSplice(x => x._id === data._id, data)) newActions.push(data);
|
||||
const updates = await this.action.parent.parent.update({ 'system.actions': newActions });
|
||||
const updates = await this.action.parent.parent.update({ [`system.${this.action.systemPath}`]: newActions });
|
||||
if (!updates) return;
|
||||
this.action = updates.system.actions[this.action.index];
|
||||
this.action = foundry.utils.getProperty(updates.system, this.action.systemPath)[this.action.index];
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,88 +1,13 @@
|
|||
import DaggerheartSheet from '../daggerheart-sheet.mjs';
|
||||
import DHHeritageSheetV2 from './heritage.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
export default class AncestrySheet extends DaggerheartSheet(ItemSheetV2) {
|
||||
export default class AncestrySheet extends DHHeritageSheetV2(ItemSheetV2) {
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'sheet', 'item', 'dh-style', 'ancestry'],
|
||||
position: { width: 450, height: 700 },
|
||||
actions: {
|
||||
editFeature: this.editFeature,
|
||||
deleteFeature: this.deleteFeature
|
||||
},
|
||||
form: {
|
||||
handler: this.updateForm,
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false
|
||||
},
|
||||
dragDrop: [{ dragSelector: null, dropSelector: null }]
|
||||
classes: ['ancestry']
|
||||
};
|
||||
|
||||
static PARTS = {
|
||||
header: { template: 'systems/daggerheart/templates/sheets/items/ancestry/header.hbs' },
|
||||
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||
description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' },
|
||||
features: {
|
||||
template: 'systems/daggerheart/templates/sheets/global/tabs/tab-feature-section.hbs',
|
||||
scrollable: ['.features']
|
||||
}
|
||||
...super.PARTS
|
||||
};
|
||||
|
||||
static TABS = {
|
||||
description: {
|
||||
active: true,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'description',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.Sheets.Feature.Tabs.Description'
|
||||
},
|
||||
features: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'features',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.Sheets.Feature.Tabs.Features'
|
||||
}
|
||||
};
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.document = this.document;
|
||||
context.tabs = super._getTabs(this.constructor.TABS);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static async updateForm(event, _, formData) {
|
||||
await this.document.update(formData.object);
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async editFeature(_, target) {
|
||||
const feature = await fromUuid(target.dataset.feature);
|
||||
feature.sheet.render(true);
|
||||
}
|
||||
|
||||
static async deleteFeature(event, target) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
await this.item.update({
|
||||
'system.abilities': this.item.system.abilities.filter(x => x.uuid !== target.dataset.feature)
|
||||
});
|
||||
}
|
||||
|
||||
async _onDrop(event) {
|
||||
const data = TextEditor.getDragEventData(event);
|
||||
const item = await fromUuid(data.uuid);
|
||||
if (item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.ancestry.id) {
|
||||
await this.document.update({
|
||||
'system.abilities': [
|
||||
...this.document.system.abilities,
|
||||
{ img: item.img, name: item.name, uuid: item.uuid }
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { armorFeatures } from '../../../config/itemConfig.mjs';
|
||||
import { tagifyElement } from '../../../helpers/utils.mjs';
|
||||
import DHItemSheetV2 from '../item.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
|
|
@ -20,4 +22,28 @@ export default class ArmorSheet extends DHItemSheetV2(ItemSheetV2) {
|
|||
scrollable: ['.settings']
|
||||
}
|
||||
};
|
||||
|
||||
async _preparePartContext(partId, context) {
|
||||
super._preparePartContext(partId, context);
|
||||
|
||||
switch (partId) {
|
||||
case 'settings':
|
||||
context.features = this.document.system.features.map(x => x.value);
|
||||
break;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
const featureInput = htmlElement.querySelector('.features-input');
|
||||
tagifyElement(featureInput, armorFeatures, this.onFeatureSelect.bind(this));
|
||||
}
|
||||
|
||||
async onFeatureSelect(features) {
|
||||
await this.document.update({ 'system.features': features.map(x => ({ value: x.value })) });
|
||||
this.render(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import { actionsTypes } from '../../../data/_module.mjs';
|
||||
import { tagifyElement } from '../../../helpers/utils.mjs';
|
||||
import DHActionConfig from '../../config/Action.mjs';
|
||||
import DaggerheartSheet from '../daggerheart-sheet.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
const { TextEditor } = foundry.applications.ux;
|
||||
|
||||
export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
|
|
@ -11,8 +14,9 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
actions: {
|
||||
removeSubclass: this.removeSubclass,
|
||||
viewSubclass: this.viewSubclass,
|
||||
deleteFeature: this.deleteFeature,
|
||||
addFeature: this.addFeature,
|
||||
editFeature: this.editFeature,
|
||||
deleteFeature: this.deleteFeature,
|
||||
removeItem: this.removeItem,
|
||||
viewItem: this.viewItem,
|
||||
removePrimaryWeapon: this.removePrimaryWeapon,
|
||||
|
|
@ -151,6 +155,69 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
await this.document.update({ 'system.characterGuide.suggestedArmor': null }, { diff: false });
|
||||
}
|
||||
|
||||
async selectActionType() {
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/views/actionType.hbs',
|
||||
{ types: SYSTEM.ACTIONS.actionTypes }
|
||||
),
|
||||
title = 'Select Action Type',
|
||||
type = 'form',
|
||||
data = {};
|
||||
return Dialog.prompt({
|
||||
title,
|
||||
label: title,
|
||||
content,
|
||||
type,
|
||||
callback: html => {
|
||||
const form = html[0].querySelector('form'),
|
||||
fd = new foundry.applications.ux.FormDataExtended(form);
|
||||
foundry.utils.mergeObject(data, fd.object, { inplace: true });
|
||||
|
||||
return data;
|
||||
},
|
||||
rejectClose: false
|
||||
});
|
||||
}
|
||||
|
||||
getActionPath(type) {
|
||||
return type === 'hope' ? 'hopeFeatures' : 'classFeatures';
|
||||
}
|
||||
|
||||
static async addFeature(_, target) {
|
||||
const actionPath = this.getActionPath(target.dataset.type);
|
||||
const actionType = await this.selectActionType();
|
||||
const cls = actionsTypes[actionType?.type] ?? actionsTypes.attack,
|
||||
action = new cls(
|
||||
{
|
||||
_id: foundry.utils.randomID(),
|
||||
systemPath: actionPath,
|
||||
type: actionType.type,
|
||||
name: game.i18n.localize(SYSTEM.ACTIONS.actionTypes[actionType.type].name),
|
||||
...cls.getSourceConfig(this.document)
|
||||
},
|
||||
{
|
||||
parent: this.document
|
||||
}
|
||||
);
|
||||
await this.document.update({ [`system.${actionPath}`]: [...this.document.system[actionPath], action] });
|
||||
}
|
||||
|
||||
static async editFeature(_, target) {
|
||||
const action = this.document.system[this.getActionPath(target.dataset.type)].find(
|
||||
x => x._id === target.dataset.feature
|
||||
);
|
||||
await new DHActionConfig(action).render(true);
|
||||
}
|
||||
|
||||
static async deleteFeature(_, target) {
|
||||
const actionPath = this.getActionPath(target.dataset.type);
|
||||
await this.document.update({
|
||||
[`system.${actionPath}`]: this.document.system[actionPath].filter(
|
||||
action => action._id !== target.dataset.feature
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
async _onDrop(event) {
|
||||
const data = TextEditor.getDragEventData(event);
|
||||
const item = await fromUuid(data.uuid);
|
||||
|
|
@ -158,10 +225,6 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
await this.document.update({
|
||||
'system.subclasses': [...this.document.system.subclasses.map(x => x.uuid), item.uuid]
|
||||
});
|
||||
} else if (item.type === 'feature') {
|
||||
await this.document.update({
|
||||
'system.features': [...this.document.system.features.map(x => x.uuid), item.uuid]
|
||||
});
|
||||
} else if (item.type === 'weapon') {
|
||||
if (event.currentTarget.classList.contains('primary-weapon-section')) {
|
||||
if (!this.document.system.characterGuide.suggestedPrimaryWeapon && !item.system.secondary)
|
||||
|
|
|
|||
|
|
@ -1,88 +1,13 @@
|
|||
import DaggerheartSheet from '../daggerheart-sheet.mjs';
|
||||
import DHHeritageSheetV2 from './heritage.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
export default class CommunitySheet extends DaggerheartSheet(ItemSheetV2) {
|
||||
export default class CommunitySheet extends DHHeritageSheetV2(ItemSheetV2) {
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'sheet', 'item', 'dh-style', 'community'],
|
||||
position: { width: 450, height: 700 },
|
||||
actions: {
|
||||
editFeature: this.editFeature,
|
||||
deleteFeature: this.deleteFeature
|
||||
},
|
||||
form: {
|
||||
handler: this.updateForm,
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false
|
||||
},
|
||||
dragDrop: [{ dragSelector: null, dropSelector: null }]
|
||||
classes: ['community']
|
||||
};
|
||||
|
||||
static PARTS = {
|
||||
header: { template: 'systems/daggerheart/templates/sheets/items/community/header.hbs' },
|
||||
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||
description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' },
|
||||
features: {
|
||||
template: 'systems/daggerheart/templates/sheets/global/tabs/tab-feature-section.hbs',
|
||||
scrollable: ['.features']
|
||||
}
|
||||
...super.PARTS
|
||||
};
|
||||
|
||||
static TABS = {
|
||||
description: {
|
||||
active: true,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'description',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.Sheets.Feature.Tabs.Description'
|
||||
},
|
||||
features: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'features',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.Sheets.Feature.Tabs.Features'
|
||||
}
|
||||
};
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.document = this.document;
|
||||
context.tabs = super._getTabs(this.constructor.TABS);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static async updateForm(event, _, formData) {
|
||||
await this.document.update(formData.object);
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async editFeature(_, target) {
|
||||
const feature = await fromUuid(target.dataset.feature);
|
||||
feature.sheet.render(true);
|
||||
}
|
||||
|
||||
static async deleteFeature(event, target) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
await this.item.update({
|
||||
'system.abilities': this.item.system.abilities.filter(x => x.uuid !== target.dataset.feature)
|
||||
});
|
||||
}
|
||||
|
||||
async _onDrop(event) {
|
||||
const data = TextEditor.getDragEventData(event);
|
||||
const item = await fromUuid(data.uuid);
|
||||
if (item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.community.id) {
|
||||
await this.document.update({
|
||||
'system.abilities': [
|
||||
...this.document.system.abilities,
|
||||
{ img: item.img, name: item.name, uuid: item.uuid }
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
147
module/applications/sheets/items/heritage.mjs
Normal file
147
module/applications/sheets/items/heritage.mjs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
import { actionsTypes } from '../../../data/_module.mjs';
|
||||
import DHActionConfig from '../../config/Action.mjs';
|
||||
import DHItemMixin from '../item.mjs';
|
||||
|
||||
export default function DHHeritageMixin(Base) {
|
||||
return class DHHeritageSheetV2 extends DHItemMixin(Base) {
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
position: { width: 450, height: 700 },
|
||||
actions: {
|
||||
addAction: this.addAction,
|
||||
editAction: this.editAction,
|
||||
removeAction: this.removeAction,
|
||||
addEffect: this.addEffect,
|
||||
editEffect: this.editEffect,
|
||||
removeEffect: this.removeEffect
|
||||
},
|
||||
form: {
|
||||
handler: this.updateForm,
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false
|
||||
}
|
||||
};
|
||||
|
||||
static PARTS = {
|
||||
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||
description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' },
|
||||
actions: {
|
||||
template: 'systems/daggerheart/templates/sheets/global/tabs/tab-actions.hbs',
|
||||
scrollable: ['.actions']
|
||||
},
|
||||
effects: {
|
||||
template: 'systems/daggerheart/templates/sheets/global/tabs/tab-effects.hbs',
|
||||
scrollable: ['.effects']
|
||||
}
|
||||
};
|
||||
|
||||
static TABS = {
|
||||
description: {
|
||||
active: true,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'description',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.Sheets.Feature.Tabs.Description'
|
||||
},
|
||||
actions: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'actions',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.Sheets.Feature.Tabs.Actions'
|
||||
},
|
||||
effects: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'effects',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.Sheets.Feature.Tabs.Effects'
|
||||
}
|
||||
};
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.document = this.document;
|
||||
context.tabs = super._getTabs(this.constructor.TABS);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static async updateForm(event, _, formData) {
|
||||
await this.document.update(formData.object);
|
||||
this.render();
|
||||
}
|
||||
|
||||
async selectActionType() {
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/views/actionType.hbs',
|
||||
{ types: SYSTEM.ACTIONS.actionTypes }
|
||||
),
|
||||
title = 'Select Action Type',
|
||||
type = 'form',
|
||||
data = {};
|
||||
return Dialog.prompt({
|
||||
title,
|
||||
label: title,
|
||||
content,
|
||||
type,
|
||||
callback: html => {
|
||||
const form = html[0].querySelector('form'),
|
||||
fd = new foundry.applications.ux.FormDataExtended(form);
|
||||
foundry.utils.mergeObject(data, fd.object, { inplace: true });
|
||||
return data;
|
||||
},
|
||||
rejectClose: false
|
||||
});
|
||||
}
|
||||
|
||||
static async addAction() {
|
||||
const actionType = await this.selectActionType();
|
||||
const cls = actionsTypes[actionType?.type] ?? actionsTypes.attack,
|
||||
action = new cls(
|
||||
{
|
||||
_id: foundry.utils.randomID(),
|
||||
type: actionType.type,
|
||||
name: game.i18n.localize(SYSTEM.ACTIONS.actionTypes[actionType.type].name),
|
||||
...cls.getSourceConfig(this.document)
|
||||
},
|
||||
{
|
||||
parent: this.document
|
||||
}
|
||||
);
|
||||
await this.document.update({ 'system.actions': [...this.document.system.actions, action] });
|
||||
}
|
||||
|
||||
static async editAction(_, button) {
|
||||
const action = this.document.system.actions[button.dataset.index];
|
||||
await new DHActionConfig(action).render(true);
|
||||
}
|
||||
|
||||
static async removeAction(event, button) {
|
||||
event.stopPropagation();
|
||||
await this.document.update({
|
||||
'system.actions': this.document.system.actions.filter(
|
||||
(_, index) => index !== Number.parseInt(button.dataset.index)
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
static async addEffect() {
|
||||
await this.document.createEmbeddedDocuments('ActiveEffect', [
|
||||
{ name: game.i18n.localize('DAGGERHEART.Feature.NewEffect') }
|
||||
]);
|
||||
}
|
||||
|
||||
static async editEffect(_, target) {
|
||||
const effect = this.document.effects.get(target.dataset.effect);
|
||||
effect.sheet.render(true);
|
||||
}
|
||||
|
||||
static async removeEffect(_, target) {
|
||||
await this.document.effects.get(target.dataset.effect).delete();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -1,28 +1,24 @@
|
|||
import DaggerheartSheet from '../daggerheart-sheet.mjs';
|
||||
import { actionsTypes } from '../../../data/_module.mjs';
|
||||
import DHActionConfig from '../../config/Action.mjs';
|
||||
import DhpApplicationMixin from '../daggerheart-sheet.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
const { TextEditor } = foundry.applications.ux;
|
||||
const { duplicate, getProperty } = foundry.utils;
|
||||
export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) {
|
||||
export default class SubclassSheet extends DhpApplicationMixin(ItemSheetV2) {
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'sheet', 'item', 'dh-style', 'subclass'],
|
||||
position: { width: 600 },
|
||||
window: { resizable: false },
|
||||
actions: {
|
||||
editAbility: this.editAbility,
|
||||
deleteFeatureAbility: this.deleteFeatureAbility
|
||||
addFeature: this.addFeature,
|
||||
editFeature: this.editFeature,
|
||||
deleteFeature: this.deleteFeature
|
||||
},
|
||||
form: {
|
||||
handler: this.updateForm,
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false
|
||||
},
|
||||
dragDrop: [
|
||||
{ dragSelector: null, dropSelector: '.foundation-tab' },
|
||||
{ dragSelector: null, dropSelector: '.specialization-tab' },
|
||||
{ dragSelector: null, dropSelector: '.mastery-tab' }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
static PARTS = {
|
||||
|
|
@ -80,41 +76,99 @@ export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
this.render();
|
||||
}
|
||||
|
||||
static async editAbility(_, button) {
|
||||
const feature = await fromUuid(button.dataset.ability);
|
||||
feature.sheet.render(true);
|
||||
static addFeature(_, target) {
|
||||
if (target.dataset.type === 'action') this.addAction(target.dataset.level);
|
||||
else this.addEffect(target.dataset.level);
|
||||
}
|
||||
|
||||
static async deleteFeatureAbility(event, button) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const feature = button.dataset.feature;
|
||||
const newAbilities = this.document.system[`${feature}Feature`].abilities.filter(
|
||||
x => x.uuid !== button.dataset.ability
|
||||
);
|
||||
const path = `system.${feature}Feature.abilities`;
|
||||
|
||||
await this.document.update({ [path]: newAbilities });
|
||||
static async editFeature(_, target) {
|
||||
if (target.dataset.type === 'action') this.editAction(target.dataset.level, target.dataset.feature);
|
||||
else this.editEffect(target.dataset.feature);
|
||||
}
|
||||
|
||||
async _onDrop(event) {
|
||||
event.preventDefault();
|
||||
const data = TextEditor.getDragEventData(event);
|
||||
const item = await fromUuid(data.uuid);
|
||||
if (!(item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.subclass.id)) return;
|
||||
static async deleteFeature(_, target) {
|
||||
if (target.dataset.type === 'action') this.removeAction(target.dataset.level, target.dataset.feature);
|
||||
else this.removeEffect(target.dataset.level, target.dataset.feature);
|
||||
}
|
||||
|
||||
let featureField;
|
||||
if (event.currentTarget.classList.contains('foundation-tab')) featureField = 'foundation';
|
||||
else if (event.currentTarget.classList.contains('specialization-tab')) featureField = 'specialization';
|
||||
else if (event.currentTarget.classList.contains('mastery-tab')) featureField = 'mastery';
|
||||
else return;
|
||||
async #selectActionType() {
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/views/actionType.hbs',
|
||||
{ types: SYSTEM.ACTIONS.actionTypes }
|
||||
),
|
||||
title = 'Select Action Type',
|
||||
type = 'form',
|
||||
data = {};
|
||||
return Dialog.prompt({
|
||||
title,
|
||||
label: title,
|
||||
content,
|
||||
type,
|
||||
callback: html => {
|
||||
const form = html[0].querySelector('form'),
|
||||
fd = new foundry.applications.ux.FormDataExtended(form);
|
||||
foundry.utils.mergeObject(data, fd.object, { inplace: true });
|
||||
return data;
|
||||
},
|
||||
rejectClose: false
|
||||
});
|
||||
}
|
||||
|
||||
const path = `system.${featureField}Feature.abilities`;
|
||||
const abilities = duplicate(getProperty(this.document, path)) || [];
|
||||
const featureData = { name: item.name, img: item.img, uuid: item.uuid };
|
||||
abilities.push(featureData);
|
||||
async addAction(level) {
|
||||
const actionType = await this.#selectActionType();
|
||||
const cls = actionsTypes[actionType?.type] ?? actionsTypes.attack,
|
||||
action = new cls(
|
||||
{
|
||||
_id: foundry.utils.randomID(),
|
||||
systemPath: `${level}.actions`,
|
||||
type: actionType.type,
|
||||
name: game.i18n.localize(SYSTEM.ACTIONS.actionTypes[actionType.type].name),
|
||||
...cls.getSourceConfig(this.document)
|
||||
},
|
||||
{
|
||||
parent: this.document
|
||||
}
|
||||
);
|
||||
await this.document.update({ [`system.${level}.actions`]: [...this.document.system[level].actions, action] });
|
||||
await new DHActionConfig(
|
||||
this.document.system[level].actions[this.document.system[level].actions.length - 1]
|
||||
).render(true);
|
||||
}
|
||||
|
||||
await this.document.update({ [path]: abilities });
|
||||
async addEffect(level) {
|
||||
const embeddedItems = await this.document.createEmbeddedDocuments('ActiveEffect', [
|
||||
{ name: game.i18n.localize('DAGGERHEART.Feature.NewEffect') }
|
||||
]);
|
||||
await this.document.update({
|
||||
[`system.${level}.effects`]: [
|
||||
...this.document.system[level].effects.map(x => x.uuid),
|
||||
embeddedItems[0].uuid
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async editAction(level, id) {
|
||||
const action = this.document.system[level].actions.find(x => x._id === id);
|
||||
await new DHActionConfig(action).render(true);
|
||||
}
|
||||
|
||||
async editEffect(id) {
|
||||
const effect = this.document.effects.get(id);
|
||||
effect.sheet.render(true);
|
||||
}
|
||||
|
||||
async removeAction(level, id) {
|
||||
await this.document.update({
|
||||
[`system.${level}.actions`]: this.document.system[level].actions.filter(action => action._id !== id)
|
||||
});
|
||||
}
|
||||
|
||||
async removeEffect(level, id) {
|
||||
await this.document.effects.get(id).delete();
|
||||
await this.document.update({
|
||||
[`system.${level}.effects`]: this.document.system[level].effects
|
||||
.filter(x => x && x.id !== id)
|
||||
.map(effect => effect.uuid)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { weaponFeatures } from '../../../config/itemConfig.mjs';
|
||||
import { tagifyElement } from '../../../helpers/utils.mjs';
|
||||
import DHItemSheetV2 from '../item.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
|
|
@ -19,4 +21,28 @@ export default class WeaponSheet extends DHItemSheetV2(ItemSheetV2) {
|
|||
scrollable: ['.settings']
|
||||
}
|
||||
};
|
||||
|
||||
async _preparePartContext(partId, context) {
|
||||
super._preparePartContext(partId, context);
|
||||
|
||||
switch (partId) {
|
||||
case 'settings':
|
||||
context.features = this.document.system.features.map(x => x.value);
|
||||
break;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
const featureInput = htmlElement.querySelector('.features-input');
|
||||
tagifyElement(featureInput, weaponFeatures, this.onFeatureSelect.bind(this));
|
||||
}
|
||||
|
||||
async onFeatureSelect(features) {
|
||||
await this.document.update({ 'system.features': features.map(x => ({ value: x.value })) });
|
||||
this.render(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,15 +5,78 @@ export const armorFeatures = {
|
|||
},
|
||||
channeling: {
|
||||
label: 'DAGGERHEART.ArmorFeature.Channeling.Name',
|
||||
description: 'DAGGERHEART.ArmorFeature.Channeling.Description'
|
||||
description: 'DAGGERHEART.ArmorFeature.Channeling.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.bonuses.spellcast',
|
||||
mode: 2,
|
||||
value: '1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
difficult: {
|
||||
label: 'DAGGERHEART.ArmorFeature.Difficult.Name',
|
||||
description: 'DAGGERHEART.ArmorFeature.Difficult.Description'
|
||||
description: 'DAGGERHEART.ArmorFeature.Difficult.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.traits.agility.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
},
|
||||
{
|
||||
key: 'system.traits.strength.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
},
|
||||
{
|
||||
key: 'system.traits.finesse.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
},
|
||||
{
|
||||
key: 'system.traits.instinct.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
},
|
||||
{
|
||||
key: 'system.traits.presence.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
},
|
||||
{
|
||||
key: 'system.traits.knowledge.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
},
|
||||
{
|
||||
key: 'system.evasion.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
flexible: {
|
||||
label: 'DAGGERHEART.ArmorFeature.Flexible.Name',
|
||||
description: 'DAGGERHEART.ArmorFeature.Flexible.Description'
|
||||
description: 'DAGGERHEART.ArmorFeature.Flexible.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.evasion.bonus',
|
||||
mode: 2,
|
||||
value: '1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
fortified: {
|
||||
label: 'DAGGERHEART.ArmorFeature.Fortified.Name',
|
||||
|
|
@ -21,11 +84,33 @@ export const armorFeatures = {
|
|||
},
|
||||
gilded: {
|
||||
label: 'DAGGERHEART.ArmorFeature.Gilded.Name',
|
||||
description: 'DAGGERHEART.ArmorFeature.Gilded.Description'
|
||||
description: 'DAGGERHEART.ArmorFeature.Gilded.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.traits.presence.bonus',
|
||||
mode: 2,
|
||||
value: '1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
heavy: {
|
||||
label: 'DAGGERHEART.ArmorFeature.Heavy.Name',
|
||||
description: 'DAGGERHEART.ArmorFeature.Heavy.Description'
|
||||
description: 'DAGGERHEART.ArmorFeature.Heavy.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.evasion.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
hopeful: {
|
||||
label: 'DAGGERHEART.ArmorFeature.Hopeful.Name',
|
||||
|
|
@ -77,7 +162,23 @@ export const armorFeatures = {
|
|||
},
|
||||
veryheavy: {
|
||||
label: 'DAGGERHEART.ArmorFeature.VeryHeavy.Name',
|
||||
description: 'DAGGERHEART.ArmorFeature.VeryHeavy.Description'
|
||||
description: 'DAGGERHEART.ArmorFeature.VeryHeavy.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.evasion.bonus',
|
||||
mode: 2,
|
||||
value: '-2'
|
||||
},
|
||||
{
|
||||
key: 'system.traits.agility.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
warded: {
|
||||
label: 'DAGGERHEART.ArmorFeature.Warded.Name',
|
||||
|
|
@ -89,13 +190,41 @@ export const weaponFeatures = {
|
|||
barrier: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Barrier.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Barrier.Description',
|
||||
override: {
|
||||
armorBonus: 1
|
||||
}
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.bonuses.armorScore',
|
||||
mode: 2,
|
||||
value: '@system.tier + 1'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.evasion.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
bonded: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Bonded.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Bonded.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Bonded.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.bonuses.damage',
|
||||
mode: 2,
|
||||
value: 'system.levelData.levels.current'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
bouncing: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Bouncing.Name',
|
||||
|
|
@ -103,7 +232,27 @@ export const weaponFeatures = {
|
|||
},
|
||||
brave: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Brave.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Brave.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Brave.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.evasion.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.damageThresholds.severe',
|
||||
mode: 2,
|
||||
value: '3'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
brutal: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Brutal.Name',
|
||||
|
|
@ -111,15 +260,55 @@ export const weaponFeatures = {
|
|||
},
|
||||
charged: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Charged.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Charged.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Charged.Description',
|
||||
actions: [
|
||||
{
|
||||
type: 'effect',
|
||||
name: 'DAGGERHEART.WeaponFeature.Concussive.Name',
|
||||
img: 'icons/skills/melee/shield-damaged-broken-brown.webp',
|
||||
actionType: 'action',
|
||||
cost: [
|
||||
{
|
||||
type: 'stress',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
// Should add an effect with path system.proficiency.bonus +1
|
||||
}
|
||||
]
|
||||
},
|
||||
concussive: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Concussive.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Concussive.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Concussive.Description',
|
||||
actions: [
|
||||
{
|
||||
type: 'resource',
|
||||
name: 'DAGGERHEART.WeaponFeature.Concussive.Name',
|
||||
img: 'icons/skills/melee/shield-damaged-broken-brown.webp',
|
||||
actionType: 'action',
|
||||
cost: [
|
||||
{
|
||||
type: 'hope',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
cumbersome: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Cumbersome.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Cumbersome.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Cumbersome.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.traits.finesse.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
deadly: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Deadly.Name',
|
||||
|
|
@ -128,18 +317,64 @@ export const weaponFeatures = {
|
|||
deflecting: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Deflecting.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Deflecting.Description'
|
||||
// actions: [{
|
||||
// type: 'effect',
|
||||
// name: 'DAGGERHEART.WeaponFeature.Deflecting.Name',
|
||||
// img: 'icons/skills/melee/strike-flail-destructive-yellow.webp',
|
||||
// actionType: 'reaction',
|
||||
// cost: [{
|
||||
// type: 'armorSlot', // Needs armorSlot as type
|
||||
// value: 1
|
||||
// }],
|
||||
// }],
|
||||
},
|
||||
destructive: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Destructive.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Destructive.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Destructive.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.traits.agility.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
devastating: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Devastating.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Devastating.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Devastating.Description',
|
||||
actions: [
|
||||
{
|
||||
type: 'resource',
|
||||
name: 'DAGGERHEART.WeaponFeature.Devastating.Name',
|
||||
img: 'icons/skills/melee/strike-flail-destructive-yellow.webp',
|
||||
actionType: 'action',
|
||||
cost: [
|
||||
{
|
||||
type: 'stress',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
doubleduty: {
|
||||
label: 'DAGGERHEART.WeaponFeature.DoubleDuty.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.DoubleDuty.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.DoubleDuty.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.bonuses.armorScore',
|
||||
mode: 2,
|
||||
value: '1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
doubledup: {
|
||||
label: 'DAGGERHEART.WeaponFeature.DoubledUp.Name',
|
||||
|
|
@ -155,15 +390,61 @@ export const weaponFeatures = {
|
|||
},
|
||||
grappling: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Grappling.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Grappling.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Grappling.Description',
|
||||
actions: [
|
||||
{
|
||||
type: 'resource',
|
||||
name: 'DAGGERHEART.WeaponFeature.Grappling.Name',
|
||||
img: 'icons/magic/control/debuff-chains-ropes-net-white.webp',
|
||||
actionType: 'action',
|
||||
cost: [
|
||||
{
|
||||
type: 'stress',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
greedy: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Greedy.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Greedy.Description'
|
||||
},
|
||||
healing: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Healing.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Healing.Description',
|
||||
actions: [
|
||||
{
|
||||
type: 'healing',
|
||||
name: 'DAGGERHEART.WeaponFeature.Healing.Name',
|
||||
img: 'icons/magic/life/cross-beam-green.webp',
|
||||
actionType: 'action',
|
||||
healing: {
|
||||
type: 'health',
|
||||
value: {
|
||||
custom: {
|
||||
enabled: true,
|
||||
formula: '1'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
heavy: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Heavy.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Heavy.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Heavy.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.evasion.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
hooked: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Hooked.Name',
|
||||
|
|
@ -189,13 +470,56 @@ export const weaponFeatures = {
|
|||
label: 'DAGGERHEART.WeaponFeature.Long.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Long.Description'
|
||||
},
|
||||
lucky: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Lucky.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Lucky.Description',
|
||||
actions: [
|
||||
{
|
||||
type: 'resource',
|
||||
name: 'DAGGERHEART.WeaponFeature.Lucky.Name',
|
||||
img: 'icons/magic/control/buff-luck-fortune-green.webp',
|
||||
actionType: 'action',
|
||||
cost: [
|
||||
{
|
||||
type: 'stress',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
massive: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Massive.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Massive.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Massive.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.evasion.bonus',
|
||||
mode: 2,
|
||||
value: '-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
painful: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Painful.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Painful.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Painful.Description',
|
||||
actions: [
|
||||
{
|
||||
type: 'resource',
|
||||
name: 'DAGGERHEART.WeaponFeature.Painful.Name',
|
||||
img: 'icons/skills/wounds/injury-face-impact-orange.webp',
|
||||
actionType: 'action',
|
||||
cost: [
|
||||
{
|
||||
type: 'stress',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
paired: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Paired.Name',
|
||||
|
|
@ -223,17 +547,50 @@ export const weaponFeatures = {
|
|||
protective: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Protective.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Protective.Description',
|
||||
override: {
|
||||
armorBonus: 1
|
||||
}
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.bonuses.armorScore',
|
||||
mode: 2,
|
||||
value: '@system.tier'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
quick: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Quick.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Quick.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Quick.Description',
|
||||
actions: [
|
||||
{
|
||||
type: 'resource',
|
||||
name: 'DAGGERHEART.WeaponFeature.Quick.Name',
|
||||
img: 'icons/skills/movement/arrow-upward-yellow.webp',
|
||||
actionType: 'action',
|
||||
cost: [
|
||||
{
|
||||
type: 'stress',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
reliable: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Reliable.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Reliable.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Reliable.Description',
|
||||
effects: [
|
||||
{
|
||||
changes: [
|
||||
{
|
||||
key: 'system.bonuses.attack',
|
||||
mode: 2,
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
reloading: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Reloading.Name',
|
||||
|
|
@ -265,7 +622,21 @@ export const weaponFeatures = {
|
|||
},
|
||||
startling: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Startling.Name',
|
||||
description: 'DAGGERHEART.WeaponFeature.Startling.Description'
|
||||
description: 'DAGGERHEART.WeaponFeature.Startling.Description',
|
||||
actions: [
|
||||
{
|
||||
type: 'resource',
|
||||
name: 'DAGGERHEART.WeaponFeature.Startling.Name',
|
||||
img: 'icons/magic/control/fear-fright-mask-orange.webp',
|
||||
actionType: 'action',
|
||||
cost: [
|
||||
{
|
||||
type: 'stress',
|
||||
value: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
timebending: {
|
||||
label: 'DAGGERHEART.WeaponFeature.Timebending.Name',
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
static defineSchema() {
|
||||
return {
|
||||
_id: new fields.DocumentIdField(),
|
||||
systemPath: new fields.StringField({ required: true, initial: 'actions' }),
|
||||
type: new fields.StringField({ initial: undefined, readonly: true, required: true }),
|
||||
name: new fields.StringField({ initial: undefined }),
|
||||
description: new fields.HTMLField(),
|
||||
|
|
@ -119,7 +120,7 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
prepareData() {}
|
||||
|
||||
get index() {
|
||||
return this.parent.actions.indexOf(this);
|
||||
return foundry.utils.getProperty(this.parent, this.systemPath).indexOf(this);
|
||||
}
|
||||
|
||||
get item() {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export class DHActionDiceData extends foundry.abstract.DataModel {
|
|||
getFormula(actor) {
|
||||
return this.custom.enabled
|
||||
? this.custom.formula
|
||||
: `${actor.system[this.multiplier].value ?? 1}${this.dice}${this.bonus ? (this.bonus < 0 ? ` - ${Math.abs(this.bonus)}` : ` + ${this.bonus}`) : ''}`;
|
||||
: `${actor.system[this.multiplier]?.total ?? 1}${this.dice}${this.bonus ? (this.bonus < 0 ? ` - ${Math.abs(this.bonus)}` : ` + ${this.bonus}`) : ''}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,12 @@ export default class DhCharacter extends BaseDataActor {
|
|||
value: new ForeignDocumentUUIDField({ type: 'Item', nullable: true }),
|
||||
subclass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true })
|
||||
}),
|
||||
levelData: new fields.EmbeddedDataField(DhPCLevelData)
|
||||
levelData: new fields.EmbeddedDataField(DhPCLevelData),
|
||||
bonuses: new fields.SchemaField({
|
||||
attack: new fields.NumberField({ integer: true, initial: 0 }),
|
||||
spellcast: new fields.NumberField({ integer: true, initial: 0 }),
|
||||
armorScore: new fields.NumberField({ integer: true, initial: 0 })
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
import ActionField from '../fields/actionField.mjs';
|
||||
import BaseDataItem from './base.mjs';
|
||||
|
||||
export default class DHAncestry extends BaseDataItem {
|
||||
/** @inheritDoc */
|
||||
static get metadata() {
|
||||
return foundry.utils.mergeObject(super.metadata, {
|
||||
label: "TYPES.Item.ancestry",
|
||||
type: "ancestry",
|
||||
hasDescription: true,
|
||||
label: 'TYPES.Item.ancestry',
|
||||
type: 'ancestry',
|
||||
hasDescription: true
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -15,7 +16,7 @@ export default class DHAncestry extends BaseDataItem {
|
|||
const fields = foundry.data.fields;
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
//TODO: add features field
|
||||
actions: new fields.ArrayField(new ActionField())
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
import BaseDataItem from './base.mjs';
|
||||
import ActionField from '../fields/actionField.mjs';
|
||||
import { armorFeatures } from '../../config/itemConfig.mjs';
|
||||
|
||||
export default class DHArmor extends BaseDataItem {
|
||||
/** @inheritDoc */
|
||||
static get metadata() {
|
||||
return foundry.utils.mergeObject(super.metadata, {
|
||||
label: "TYPES.Item.armor",
|
||||
type: "armor",
|
||||
label: 'TYPES.Item.armor',
|
||||
type: 'armor',
|
||||
hasDescription: true,
|
||||
isQuantifiable: true,
|
||||
isQuantifiable: true
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -17,9 +18,16 @@ export default class DHArmor extends BaseDataItem {
|
|||
const fields = foundry.data.fields;
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
tier: new fields.NumberField({ required: true, integer: true, initial: 1, min: 1 }),
|
||||
equipped: new fields.BooleanField({ initial: false }),
|
||||
baseScore: new fields.NumberField({ integer: true, initial: 0 }),
|
||||
feature: new fields.StringField({ choices: SYSTEM.ITEM.armorFeatures, blank: true }),
|
||||
features: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
value: new fields.StringField({ required: true, choices: SYSTEM.ITEM.armorFeatures, blank: true }),
|
||||
effectIds: new fields.ArrayField(new fields.StringField({ required: true })),
|
||||
actionIds: new fields.ArrayField(new fields.StringField({ required: true }))
|
||||
})
|
||||
),
|
||||
marks: new fields.SchemaField({
|
||||
max: new fields.NumberField({ initial: 6, integer: true }),
|
||||
value: new fields.NumberField({ initial: 0, integer: true })
|
||||
|
|
@ -35,4 +43,47 @@ export default class DHArmor extends BaseDataItem {
|
|||
get featureInfo() {
|
||||
return this.feature ? CONFIG.daggerheart.ITEM.armorFeatures[this.feature] : null;
|
||||
}
|
||||
|
||||
async _preUpdate(changes, options, user) {
|
||||
const allowed = await super._preUpdate(changes, options, user);
|
||||
if (allowed === false) return false;
|
||||
|
||||
if (changes.system.features) {
|
||||
const removed = this.features.filter(x => !changes.system.features.includes(x));
|
||||
const added = changes.system.features.filter(x => !this.features.includes(x));
|
||||
|
||||
for (var feature of removed) {
|
||||
for (var effectId of feature.effectIds) {
|
||||
await this.parent.effects.get(effectId).delete();
|
||||
}
|
||||
|
||||
changes.system.actions = this.actions.filter(x => !feature.actionIds.includes(x._id));
|
||||
}
|
||||
|
||||
for (var feature of added) {
|
||||
const featureData = armorFeatures[feature.value];
|
||||
if (featureData.effects?.length > 0) {
|
||||
const embeddedItems = await this.parent.createEmbeddedDocuments('ActiveEffect', [
|
||||
{
|
||||
name: game.i18n.localize(featureData.label),
|
||||
description: game.i18n.localize(featureData.description),
|
||||
changes: featureData.effects.flatMap(x => x.changes)
|
||||
}
|
||||
]);
|
||||
feature.effectIds = embeddedItems.map(x => x.id);
|
||||
}
|
||||
if (featureData.actions?.length > 0) {
|
||||
const newActions = featureData.actions.map(action => {
|
||||
const cls = actionsTypes[action.type];
|
||||
return new cls(
|
||||
{ ...action, _id: foundry.utils.randomID(), name: game.i18n.localize(action.name) },
|
||||
{ parent: this }
|
||||
);
|
||||
});
|
||||
changes.system.actions = [...this.actions, ...newActions];
|
||||
feature.actionIds = newActions.map(x => x._id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import BaseDataItem from './base.mjs';
|
||||
import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
|
||||
import ActionField from '../fields/actionField.mjs';
|
||||
|
||||
export default class DHClass extends BaseDataItem {
|
||||
/** @inheritDoc */
|
||||
|
|
@ -19,7 +20,8 @@ export default class DHClass extends BaseDataItem {
|
|||
domains: new fields.ArrayField(new fields.StringField(), { max: 2 }),
|
||||
classItems: new fields.ArrayField(new ForeignDocumentUUIDField({ type: 'Item' })),
|
||||
evasion: new fields.NumberField({ initial: 0, integer: true }),
|
||||
features: new fields.ArrayField(new ForeignDocumentUUIDField({ type: 'Item' })),
|
||||
hopeFeatures: new foundry.data.fields.ArrayField(new ActionField()),
|
||||
classFeatures: new foundry.data.fields.ArrayField(new ActionField()),
|
||||
subclasses: new fields.ArrayField(
|
||||
new ForeignDocumentUUIDField({ type: 'Item', required: false, nullable: true, initial: undefined })
|
||||
),
|
||||
|
|
@ -51,6 +53,10 @@ export default class DHClass extends BaseDataItem {
|
|||
};
|
||||
}
|
||||
|
||||
get hopeFeature() {
|
||||
return this.hopeFeatures.length > 0 ? this.hopeFeatures[0] : null;
|
||||
}
|
||||
|
||||
async _preCreate(data, options, user) {
|
||||
const allowed = await super._preCreate(data, options, user);
|
||||
if (allowed === false) return;
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
import ActionField from '../fields/actionField.mjs';
|
||||
import BaseDataItem from './base.mjs';
|
||||
|
||||
export default class DHCommunity extends BaseDataItem {
|
||||
/** @inheritDoc */
|
||||
static get metadata() {
|
||||
return foundry.utils.mergeObject(super.metadata, {
|
||||
label: "TYPES.Item.community",
|
||||
type: "community",
|
||||
hasDescription: true,
|
||||
label: 'TYPES.Item.community',
|
||||
type: 'community',
|
||||
hasDescription: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/** @inheritDoc */
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
//TODO: add features field
|
||||
actions: new fields.ArrayField(new ActionField())
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
import ActionField from '../fields/actionField.mjs';
|
||||
import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
|
||||
import BaseDataItem from './base.mjs';
|
||||
|
||||
const featureSchema = () => {
|
||||
return new foundry.data.fields.SchemaField({
|
||||
name: new foundry.data.fields.StringField({ required: true }),
|
||||
effects: new foundry.data.fields.ArrayField(new ForeignDocumentUUIDField({ type: 'ActiveEffect' })),
|
||||
actions: new foundry.data.fields.ArrayField(new ActionField())
|
||||
});
|
||||
};
|
||||
|
||||
export default class DHSubclass extends BaseDataItem {
|
||||
/** @inheritDoc */
|
||||
static get metadata() {
|
||||
|
|
@ -22,9 +31,9 @@ export default class DHSubclass extends BaseDataItem {
|
|||
nullable: true,
|
||||
initial: null
|
||||
}),
|
||||
foundationFeature: new ForeignDocumentUUIDField({ type: 'Item' }),
|
||||
specializationFeature: new ForeignDocumentUUIDField({ type: 'Item' }),
|
||||
masteryFeature: new ForeignDocumentUUIDField({ type: 'Item' }),
|
||||
foundationFeature: featureSchema(),
|
||||
specializationFeature: featureSchema(),
|
||||
masteryFeature: featureSchema(),
|
||||
featureState: new fields.NumberField({ required: true, initial: 1, min: 1 }),
|
||||
isMulticlass: new fields.BooleanField({ initial: false })
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import BaseDataItem from './base.mjs';
|
||||
import FormulaField from '../fields/formulaField.mjs';
|
||||
import PseudoDocumentsField from '../fields/pseudoDocumentsField.mjs';
|
||||
import BaseFeatureData from '../pseudo-documents/feature/baseFeatureData.mjs';
|
||||
import ActionField from '../fields/actionField.mjs';
|
||||
import { weaponFeatures } from '../../config/itemConfig.mjs';
|
||||
import { actionsTypes } from '../../data/_module.mjs';
|
||||
|
||||
export default class DHWeapon extends BaseDataItem {
|
||||
/** @inheritDoc */
|
||||
|
|
@ -23,6 +23,7 @@ export default class DHWeapon extends BaseDataItem {
|
|||
const fields = foundry.data.fields;
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
tier: new fields.NumberField({ required: true, integer: true, initial: 1, min: 1 }),
|
||||
equipped: new fields.BooleanField({ initial: false }),
|
||||
|
||||
//SETTINGS
|
||||
|
|
@ -39,14 +40,57 @@ export default class DHWeapon extends BaseDataItem {
|
|||
initial: 'physical'
|
||||
})
|
||||
}),
|
||||
feature: new fields.StringField({ choices: SYSTEM.ITEM.weaponFeatures, blank: true }),
|
||||
featureTest: new PseudoDocumentsField(BaseFeatureData, {
|
||||
required: true,
|
||||
nullable: true,
|
||||
max: 1,
|
||||
validTypes: ['weapon']
|
||||
}),
|
||||
features: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
value: new fields.StringField({ required: true, choices: SYSTEM.ITEM.weaponFeatures, blank: true }),
|
||||
effectIds: new fields.ArrayField(new fields.StringField({ required: true })),
|
||||
actionIds: new fields.ArrayField(new fields.StringField({ required: true }))
|
||||
})
|
||||
),
|
||||
actions: new fields.ArrayField(new ActionField())
|
||||
};
|
||||
}
|
||||
|
||||
async _preUpdate(changes, options, user) {
|
||||
const allowed = await super._preUpdate(changes, options, user);
|
||||
if (allowed === false) return false;
|
||||
|
||||
if (changes.system.features) {
|
||||
const removed = this.features.filter(x => !changes.system.features.includes(x));
|
||||
const added = changes.system.features.filter(x => !this.features.includes(x));
|
||||
|
||||
for (var feature of removed) {
|
||||
for (var effectId of feature.effectIds) {
|
||||
await this.parent.effects.get(effectId).delete();
|
||||
}
|
||||
|
||||
changes.system.actions = this.actions.filter(x => !feature.actionIds.includes(x._id));
|
||||
}
|
||||
|
||||
for (var feature of added) {
|
||||
const featureData = weaponFeatures[feature.value];
|
||||
if (featureData.effects?.length > 0) {
|
||||
const embeddedItems = await this.parent.createEmbeddedDocuments('ActiveEffect', [
|
||||
{
|
||||
name: game.i18n.localize(featureData.label),
|
||||
description: game.i18n.localize(featureData.description),
|
||||
changes: featureData.effects.flatMap(x => x.changes)
|
||||
}
|
||||
]);
|
||||
feature.effectIds = embeddedItems.map(x => x.id);
|
||||
}
|
||||
if (featureData.actions?.length > 0) {
|
||||
const newActions = featureData.actions.map(action => {
|
||||
const cls = actionsTypes[action.type];
|
||||
return new cls(
|
||||
{ ...action, _id: foundry.utils.randomID(), name: game.i18n.localize(action.name) },
|
||||
{ parent: this }
|
||||
);
|
||||
});
|
||||
changes.system.actions = [...this.actions, ...newActions];
|
||||
feature.actionIds = newActions.map(x => x._id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,12 @@
|
|||
export default class DhActiveEffect extends ActiveEffect {
|
||||
get isSuppressed() {
|
||||
if (['weapon', 'armor'].includes(this.parent.type)) {
|
||||
return !this.parent.system.equipped;
|
||||
}
|
||||
|
||||
return super.isSuppressed;
|
||||
}
|
||||
|
||||
async _preCreate(data, options, user) {
|
||||
const update = {};
|
||||
if (!data.img) {
|
||||
|
|
@ -11,4 +19,9 @@ export default class DhActiveEffect extends ActiveEffect {
|
|||
|
||||
await super._preCreate(data, options, user);
|
||||
}
|
||||
|
||||
static applyField(model, change, field) {
|
||||
change.value = Roll.safeEval(Roll.replaceFormulaData(change.value, change.effect.parent));
|
||||
super.applyField(model, change, field);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue