mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
actions types - attack roll
This commit is contained in:
parent
4c7f3a02c4
commit
edaf5df9e0
35 changed files with 1015 additions and 165 deletions
|
|
@ -282,6 +282,12 @@ const preloadHandlebarsTemplates = async function () {
|
|||
'systems/daggerheart/templates/components/card-preview.hbs',
|
||||
'systems/daggerheart/templates/views/levelup/parts/selectable-card-preview.hbs',
|
||||
'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs',
|
||||
'systems/daggerheart/templates/ui/combat/combatTrackerSection.hbs'
|
||||
'systems/daggerheart/templates/ui/combat/combatTrackerSection.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/damage.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/uses.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/roll.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/cost.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/range-target.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/effect.hbs'
|
||||
]);
|
||||
};
|
||||
|
|
|
|||
45
lang/en.json
45
lang/en.json
|
|
@ -145,6 +145,7 @@
|
|||
}
|
||||
},
|
||||
"General": {
|
||||
"Name": "Name",
|
||||
"Hope": "Hope",
|
||||
"Fear": "Fear",
|
||||
"Duality": "Duality",
|
||||
|
|
@ -449,6 +450,10 @@
|
|||
"twoHanded": "Two-Handed"
|
||||
},
|
||||
"Range": {
|
||||
"self": {
|
||||
"name": "Self",
|
||||
"description": "means yourself."
|
||||
},
|
||||
"melee": {
|
||||
"name": "Melee",
|
||||
"description": "means a character is within touching distance of the target. PCs can generally touch targets up to a few feet away from them, but melee range may be greater for especially large NPCs."
|
||||
|
|
@ -1202,10 +1207,48 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
"Tooltip": {
|
||||
"openItemWorld": "Open Item World",
|
||||
"delete": "Delete"
|
||||
},
|
||||
"Actions": {
|
||||
"Types": {
|
||||
"Attack": {
|
||||
"Name": "Attack"
|
||||
},
|
||||
"Spellcast": {
|
||||
"Name": "Spellcast"
|
||||
},
|
||||
"Resource": {
|
||||
"Name": "Resource"
|
||||
},
|
||||
"Damage": {
|
||||
"Name": "Damage"
|
||||
},
|
||||
"Healing": {
|
||||
"Name": "Healing"
|
||||
},
|
||||
"Summon": {
|
||||
"Name": "Summon"
|
||||
},
|
||||
"Effect": {
|
||||
"Name": "Effect"
|
||||
},
|
||||
"Macro": {
|
||||
"Name": "Macro"
|
||||
}
|
||||
}
|
||||
},
|
||||
"RollTypes": {
|
||||
"ability": {
|
||||
"name": "Ability"
|
||||
},
|
||||
"weapon": {
|
||||
"name": "Weapon"
|
||||
},
|
||||
"spellcast": {
|
||||
"name": "SpellCast"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ const { ApplicationV2 } = foundry.applications.api;
|
|||
export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
||||
constructor(action) {
|
||||
super({});
|
||||
|
||||
|
||||
this.action = action;
|
||||
this.openSection = null;
|
||||
// console.log(this.action)
|
||||
}
|
||||
|
||||
// get title(){
|
||||
|
|
@ -19,11 +20,19 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
classes: ['daggerheart', 'views', 'action'],
|
||||
position: { width: 600, height: 'auto' },
|
||||
actions: {
|
||||
toggleSection: this.toggleSection
|
||||
toggleSection: this.toggleSection,
|
||||
addEffect: this.addEffect,
|
||||
removeEffect: this.removeEffect,
|
||||
addElement: this.addElement,
|
||||
removeElement: this.removeElement,
|
||||
editEffect: this.editEffect,
|
||||
addDamage: this.addDamage,
|
||||
removeDamage: this.removeDamage
|
||||
},
|
||||
form: {
|
||||
handler: this.updateForm,
|
||||
closeOnSubmit: true
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -36,16 +45,19 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
|
||||
_getTabs() {
|
||||
const tabs = {
|
||||
effects: { active: true, cssClass: '', group: 'primary', id: 'effects', icon: null, label: 'Effects' },
|
||||
useage: { active: false, cssClass: '', group: 'primary', id: 'useage', icon: null, label: 'Useage' },
|
||||
conditions: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'conditions',
|
||||
icon: null,
|
||||
label: 'Conditions'
|
||||
}
|
||||
base: { active: true, cssClass: '', group: 'primary', id: 'base', icon: null, label: 'Base' },
|
||||
config: { active: false, cssClass: '', group: 'primary', id: 'config', icon: null, label: 'Configuration' },
|
||||
effect: { active: false, cssClass: '', group: 'primary', id: 'effect', icon: null, label: 'Effect' },
|
||||
// effects: { active: true, cssClass: '', group: 'primary', id: 'effects', icon: null, label: 'Effects' },
|
||||
// useage: { active: false, cssClass: '', group: 'primary', id: 'useage', icon: null, label: 'Useage' },
|
||||
// conditions: {
|
||||
// active: false,
|
||||
// cssClass: '',
|
||||
// group: 'primary',
|
||||
// id: 'conditions',
|
||||
// icon: null,
|
||||
// label: 'Conditions'
|
||||
// }
|
||||
};
|
||||
|
||||
for (const v of Object.values(tabs)) {
|
||||
|
|
@ -58,9 +70,15 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options, 'action');
|
||||
context.source = this.action.toObject(false);
|
||||
context.openSection = this.openSection;
|
||||
context.tabs = this._getTabs();
|
||||
|
||||
context.config = SYSTEM;
|
||||
context.effects = this.action.effects.map(e => this.action.item.effects.get(e._id));
|
||||
context.hasBaseDamage = !!this.action.parent.damage;
|
||||
context.getRealIndex = this.getRealIndex.bind(this);
|
||||
|
||||
console.log(context, this.action)
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
@ -69,15 +87,103 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
this.render(true);
|
||||
}
|
||||
|
||||
static async updateForm(event, _, formData) {
|
||||
const data = foundry.utils.expandObject(
|
||||
foundry.utils.mergeObject(this.action.toObject(), foundry.utils.expandObject(formData.object))
|
||||
);
|
||||
const newActions = this.action.parent.actions.map(x => x.toObject());
|
||||
if (!newActions.findSplice(x => x.id === data.id, data)) {
|
||||
newActions.push(data);
|
||||
}
|
||||
getRealIndex(index) {
|
||||
const data = this.action.toObject(false);
|
||||
return data.damage.parts.find(d => d.base) ? index - 1 : index;
|
||||
}
|
||||
|
||||
_prepareSubmitData(event, formData) {
|
||||
const submitData = foundry.utils.expandObject(formData.object);
|
||||
// this.element.querySelectorAll("fieldset[disabled] :is(input, select)").forEach(input => {
|
||||
// foundry.utils.setProperty(submitData, input.name, input.value);
|
||||
// });
|
||||
return submitData;
|
||||
}
|
||||
|
||||
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
|
||||
if (!newActions.findSplice(x => x._id === data._id, data)) newActions.push(data);
|
||||
const updates = await this.action.parent.parent.update({ 'system.actions': newActions });
|
||||
if(!updates) return;
|
||||
this.action = updates.system.actions[this.action.index];
|
||||
this.render();
|
||||
}
|
||||
|
||||
/* cleanData(data) {
|
||||
for(let k in data) {
|
||||
if(typeof data[k] === 'object' && !Array.isArray(data[k])) {
|
||||
if(!isNaN(Object.keys(data[k])[0])) data[k] = Object.values(data[k]);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
} */
|
||||
|
||||
static addElement(event) {
|
||||
const data = this.action.toObject(),
|
||||
key = $(event.target).closest('.action-category-data').data('key');
|
||||
if ( !this.action[key] ) return;
|
||||
data[key].push({});
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static removeElement(event) {
|
||||
const data = this.action.toObject(),
|
||||
key = $(event.target).closest('.action-category-data').data('key'),
|
||||
index = $(event.target).data('index');
|
||||
data[key].splice(index, 1);
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static addDamage(event) {
|
||||
if ( !this.action.damage.parts ) return;
|
||||
const data = this.action.toObject();
|
||||
data.damage.parts.push({});
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static removeDamage(event) {
|
||||
if ( !this.action.damage.parts ) return;
|
||||
const data = this.action.toObject(),
|
||||
index = $(event.target).data('index');
|
||||
data.damage.parts.splice(index, 1);
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static async addEffect(event) {
|
||||
if ( !this.action.effects ) return;
|
||||
// console.log(this, this.action.item)
|
||||
const effectData = this._addEffectData.bind(this)(),
|
||||
[created] = await this.action.item.createEmbeddedDocuments("ActiveEffect", [effectData], { render: false }),
|
||||
data = this.action.toObject();
|
||||
data.effects.push( { '_id': created._id } )
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
/**
|
||||
* The data for a newly created applied effect.
|
||||
* @returns {object}
|
||||
* @protected
|
||||
*/
|
||||
_addEffectData() {
|
||||
return {
|
||||
name: this.action.item.name,
|
||||
img: this.action.item.img,
|
||||
origin: this.action.item.uuid,
|
||||
transfer: false
|
||||
};
|
||||
}
|
||||
|
||||
static removeEffect(event) {
|
||||
if ( !this.action.effects ) return;
|
||||
const index = $(event.target).data('index'),
|
||||
effectId = this.action.effects[index]._id;
|
||||
this.constructor.removeElement.bind(this)(event);
|
||||
this.action.item.deleteEmbeddedDocuments("ActiveEffect", [effectId]);
|
||||
}
|
||||
|
||||
static editEffect(event) {
|
||||
|
||||
await this.action.parent.parent.update({ 'system.actions': newActions });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ export default function DhpApplicationMixin(Base) {
|
|||
|
||||
async _prepareContext(_options, objectPath = 'document') {
|
||||
const context = await super._prepareContext(_options);
|
||||
console.log(this, objectPath)
|
||||
context.source = this[objectPath].toObject();
|
||||
context.fields = this[objectPath].schema.fields;
|
||||
context.systemFields = this[objectPath].system ? this[objectPath].system.schema.fields : {};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import DHAction from '../../../data/action.mjs';
|
||||
import DHAction from '../../../data/action/action.mjs';
|
||||
import DHActionConfig from '../../config/Action.mjs';
|
||||
import DaggerheartSheet from '../daggerheart-sheet.mjs';
|
||||
|
||||
|
|
@ -79,6 +79,7 @@ export default class DomainCardSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
const action = await new DHAction(
|
||||
{
|
||||
id: `${this.document.id}-Action-${actionIndexes.length > 0 ? actionIndexes[0] + 1 : 1}`
|
||||
// id: foundry.utils.randomID()
|
||||
},
|
||||
{
|
||||
parent: this.document
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import DHAction from '../../../data/action.mjs';
|
||||
import DHAction from '../../../data/action/action.mjs';
|
||||
import DHActionConfig from '../../config/Action.mjs';
|
||||
import DaggerheartSheet from '../daggerheart-sheet.mjs';
|
||||
|
||||
|
|
@ -132,7 +132,10 @@ export default class FeatureSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
}
|
||||
|
||||
static async addAction() {
|
||||
const action = await new DHAction({ img: this.document.img }, { parent: this.document });
|
||||
const action = new DHAction({
|
||||
id: foundry.utils.randomID(),
|
||||
// img: this.document.img
|
||||
}, { parent: this.document });
|
||||
await this.document.update({ 'system.actions': [...this.document.system.actions, action] });
|
||||
await new DHActionConfig(this.document.system.actions[this.document.system.actions.length - 1]).render(
|
||||
true
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import DHActionConfig from '../../config/Action.mjs';
|
||||
import DaggerheartSheet from '../daggerheart-sheet.mjs';
|
||||
import { actionsTypes } from '../../../data/_module.mjs';
|
||||
|
||||
const { ItemSheetV2 } = foundry.applications.sheets;
|
||||
export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) {
|
||||
|
|
@ -6,6 +8,11 @@ export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
tag: 'form',
|
||||
classes: ['daggerheart', 'sheet', 'item', 'dh-style', 'weapon'],
|
||||
position: { width: 600 },
|
||||
actions: {
|
||||
addAction: this.addAction,
|
||||
editAction: this.editAction,
|
||||
removeAction: this.removeAction
|
||||
},
|
||||
form: {
|
||||
handler: this.updateForm,
|
||||
submitOnChange: true,
|
||||
|
|
@ -17,6 +24,10 @@ export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
header: { template: 'systems/daggerheart/templates/sheets/items/weapon/header.hbs' },
|
||||
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']
|
||||
},
|
||||
settings: {
|
||||
template: 'systems/daggerheart/templates/sheets/items/weapon/settings.hbs',
|
||||
scrollable: ['.settings']
|
||||
|
|
@ -32,6 +43,14 @@ export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
icon: null,
|
||||
label: 'DAGGERHEART.Sheets.Feature.Tabs.Description'
|
||||
},
|
||||
actions: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'actions',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.Sheets.Feature.Tabs.Actions'
|
||||
},
|
||||
settings: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
|
|
@ -55,4 +74,67 @@ export default class WeaponSheet extends DaggerheartSheet(ItemSheetV2) {
|
|||
await this.document.update(formData.object);
|
||||
this.render();
|
||||
}
|
||||
|
||||
static 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 });
|
||||
// if (!data.name?.trim()) data.name = game.i18n.localize(SYSTEM.ACTIONS.actionTypes[data.type].name);
|
||||
return data;
|
||||
},
|
||||
rejectClose: false
|
||||
})
|
||||
}
|
||||
|
||||
static async addAction() {
|
||||
// const actionType = await WeaponSheet.selectActionType();
|
||||
const actionType = await WeaponSheet.selectActionType(),
|
||||
actionIndexes = this.document.system.actions.map(x => x._id.split('-')[2]).sort((a, b) => a - b)
|
||||
try {
|
||||
// const cls = DHAction,
|
||||
const cls = actionsTypes[actionType?.type] ?? actionsTypes.attack,
|
||||
action = new cls(
|
||||
{
|
||||
// id: `${this.document.id}-Action-${actionIndexes.length > 0 ? actionIndexes[0] + 1 : 1}`
|
||||
_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] });
|
||||
await new DHActionConfig(this.document.system.actions[this.document.system.actions.length - 1]).render(true);
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
selectAncestry: this.selectAncestry,
|
||||
selectCommunity: this.selectCommunity,
|
||||
viewObject: this.viewObject,
|
||||
useItem: this.useItem,
|
||||
useFeature: this.useFeature,
|
||||
takeShortRest: this.takeShortRest,
|
||||
takeLongRest: this.takeLongRest,
|
||||
|
|
@ -184,6 +185,9 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
.querySelectorAll('.experience-value')
|
||||
.forEach(element => element.addEventListener('change', this.experienceValueChange.bind(this)));
|
||||
htmlElement.querySelector('.level-value').addEventListener('change', this.onLevelChange.bind(this));
|
||||
htmlElement
|
||||
.querySelectorAll('[data-item-id]')
|
||||
.forEach(element => element.addEventListener('contextmenu', this.editItem.bind(this)));
|
||||
}
|
||||
|
||||
async _prepareContext(_options) {
|
||||
|
|
@ -738,6 +742,12 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
(await game.packs.get('daggerheart.communities'))?.render(true);
|
||||
}
|
||||
|
||||
static useItem(event) {
|
||||
const uuid = event.target.closest('[data-item-id]').dataset.itemId,
|
||||
item = this.document.items.find(i => i.uuid === uuid);
|
||||
item.use(event);
|
||||
}
|
||||
|
||||
static async viewObject(_, button) {
|
||||
const object = await fromUuid(button.dataset.value);
|
||||
if (!object) return;
|
||||
|
|
@ -750,6 +760,16 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
object.sheet.render(true);
|
||||
}
|
||||
|
||||
editItem(event) {
|
||||
const uuid = event.target.closest('[data-item-id]').dataset.itemId,
|
||||
item = this.document.items.find(i => i.uuid === uuid);
|
||||
if (!item) return;
|
||||
|
||||
if (item.sheet.editMode) item.sheet.editMode = false;
|
||||
|
||||
item.sheet.render(true);
|
||||
}
|
||||
|
||||
static async takeShortRest() {
|
||||
await new DhpDowntime(this.document, true).render(true);
|
||||
await this.minimize();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,43 @@
|
|||
export const actionTypes = {
|
||||
attack: {
|
||||
id: 'attack',
|
||||
name: 'DAGGERHEART.Actions.Types.Attack.Name',
|
||||
icon: "fa-swords"
|
||||
},
|
||||
spellcast: {
|
||||
id: 'spellcast',
|
||||
name: 'DAGGERHEART.Actions.Types.Spellcast.Name',
|
||||
icon: "fa-book-sparkles"
|
||||
},
|
||||
resource: {
|
||||
id: 'resource',
|
||||
name: 'DAGGERHEART.Actions.Types.Resource.Name',
|
||||
icon: "fa-honey-pot"
|
||||
},
|
||||
damage: {
|
||||
id: 'damage',
|
||||
name: 'DAGGERHEART.Effects.Types.Health.Name'
|
||||
name: 'DAGGERHEART.Actions.Types.Damage.Name',
|
||||
icon: "fa-bone-break"
|
||||
},
|
||||
healing: {
|
||||
id: 'healing',
|
||||
name: 'DAGGERHEART.Actions.Types.Healing.Name',
|
||||
icon: "fa-kit-medical"
|
||||
},
|
||||
summon: {
|
||||
id: 'summon',
|
||||
name: 'DAGGERHEART.Actions.Types.Summon.Name',
|
||||
icon: "fa-ghost"
|
||||
},
|
||||
effect: {
|
||||
id: 'effect',
|
||||
name: 'DAGGERHEART.Actions.Types.Effect.Name',
|
||||
icon: "fa-person-rays"
|
||||
},
|
||||
macro: {
|
||||
id: 'macro',
|
||||
name: 'DAGGERHEART.Actions.Types.Macro.Name',
|
||||
icon: "fa-scroll"
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
export const range = {
|
||||
self: {
|
||||
label: 'DAGGERHEART.Range.self.name',
|
||||
description: 'DAGGERHEART.Range.self.description',
|
||||
distance: 0
|
||||
},
|
||||
melee: {
|
||||
label: 'DAGGERHEART.Range.melee.name',
|
||||
description: 'DAGGERHEART.Range.melee.description',
|
||||
|
|
@ -247,6 +252,11 @@ export const diceTypes = {
|
|||
d20: 'd20'
|
||||
};
|
||||
|
||||
export const multiplierTypes = {
|
||||
proficiency: 'Proficiency',
|
||||
spellcast: 'Spellcast'
|
||||
};
|
||||
|
||||
export const getDiceSoNicePresets = () => {
|
||||
const { diceSoNice } = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance);
|
||||
|
||||
|
|
@ -311,3 +321,18 @@ export const abilityCosts = {
|
|||
label: 'Stress'
|
||||
}
|
||||
};
|
||||
|
||||
export const rollTypes = {
|
||||
weapon: {
|
||||
id: 'weapon',
|
||||
label: 'DAGGERHEART.RollTypes.weapon.name'
|
||||
},
|
||||
spellcast: {
|
||||
id: 'spellcast',
|
||||
label: 'DAGGERHEART.RollTypes.spellcast.name'
|
||||
},
|
||||
ability: {
|
||||
id: 'ability',
|
||||
label: 'DAGGERHEART.RollTypes.ability.name'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,5 @@ export { default as DhpAdversary } from './adversary.mjs';
|
|||
export { default as DhpEnvironment } from './environment.mjs';
|
||||
|
||||
export * as items from './item/_module.mjs';
|
||||
export { actionsTypes } from './action/_module.mjs';
|
||||
export * as messages from './chat-message/_modules.mjs';
|
||||
|
|
|
|||
|
|
@ -1,123 +0,0 @@
|
|||
export default class DHAction extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
id: new fields.DocumentIdField(),
|
||||
name: new fields.StringField({ initial: 'New Action' }),
|
||||
damage: new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.damageTypes, nullable: true, initial: null }),
|
||||
value: new fields.StringField({})
|
||||
}),
|
||||
healing: new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.healingTypes, nullable: true, initial: null }),
|
||||
value: new fields.StringField()
|
||||
}),
|
||||
conditions: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField(),
|
||||
icon: new fields.StringField(),
|
||||
description: new fields.StringField()
|
||||
})
|
||||
),
|
||||
cost: new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.abilityCosts, nullable: true, initial: null }),
|
||||
value: new fields.NumberField({ nullable: true, initial: null })
|
||||
}),
|
||||
target: new fields.SchemaField({
|
||||
type: new fields.StringField({
|
||||
choices: SYSTEM.ACTIONS.targetTypes,
|
||||
initial: SYSTEM.ACTIONS.targetTypes.other.id
|
||||
})
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
export class DHBaseAction extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
return {
|
||||
_id: new fields.DocumentIdField(),
|
||||
type: new fields.StringField({ blank: false, required: true, readOnly: true, initial: () => '' }),
|
||||
name: new fields.StringField({ initial: 'New Action' }),
|
||||
// description: new fields.StringField({}),
|
||||
// shortDescription: new fields.StringField({}),
|
||||
cost: new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.abilityCosts, nullable: true, initial: null }),
|
||||
value: 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: SYSTEM.ACTIONS.targetTypes,
|
||||
// initial: SYSTEM.ACTIONS.targetTypes.other.id
|
||||
})
|
||||
}),
|
||||
duration: new fields.SchemaField({
|
||||
value: new fields.NumberField({ nullable: true, initial: null }),
|
||||
units: new fields.StringField({required: true, blank: false, initial: "instant"})
|
||||
}),
|
||||
target: new fields.SchemaField({
|
||||
type: new fields.StringField({
|
||||
choices: SYSTEM.ACTIONS.targetTypes,
|
||||
initial: SYSTEM.ACTIONS.targetTypes.other.id
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHAttackAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
attack: new fields.SchemaField({}),
|
||||
damage: new fields.SchemaField({})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHDamageAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
damage: new fields.SchemaField({})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHHealingAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
healing: new fields.SchemaField({})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHSummonAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
healing: new fields.SchemaField({})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHEffectAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHMacroAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema()
|
||||
}
|
||||
}
|
||||
}
|
||||
13
module/data/action/_module.mjs
Normal file
13
module/data/action/_module.mjs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { DHAttackAction, DHBaseAction, DHDamageAction, DHEffectAction, DHHealingAction, DHMacroAction, DHResourceAction, DHSpellCastAction, DHSummonAction } from "./action.mjs";
|
||||
|
||||
export const actionsTypes = {
|
||||
base: DHBaseAction,
|
||||
attack: DHAttackAction,
|
||||
spellcast: DHSpellCastAction,
|
||||
resource: DHResourceAction,
|
||||
damage: DHDamageAction,
|
||||
healing: DHHealingAction,
|
||||
summon: DHSummonAction,
|
||||
effect: DHEffectAction,
|
||||
macro: DHMacroAction
|
||||
}
|
||||
306
module/data/action/action.mjs
Normal file
306
module/data/action/action.mjs
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
import DHDamageData from "./damage.mjs";
|
||||
import { abilities } from "../../config/actorConfig.mjs";
|
||||
// import DHWeapon from "../item/weapon.mjs";
|
||||
|
||||
export default class DHAction extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
id: new fields.DocumentIdField(),
|
||||
name: new fields.StringField({ initial: 'New Action' }),
|
||||
damage: new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.damageTypes, nullable: true, initial: null }),
|
||||
value: new fields.StringField({})
|
||||
}),
|
||||
healing: new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.healingTypes, nullable: true, initial: null }),
|
||||
value: new fields.StringField()
|
||||
}),
|
||||
conditions: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField(),
|
||||
icon: new fields.StringField(),
|
||||
description: new fields.StringField()
|
||||
})
|
||||
),
|
||||
cost: new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.abilityCosts, nullable: true, initial: null }),
|
||||
value: new fields.NumberField({ nullable: true, initial: null })
|
||||
}),
|
||||
target: new fields.SchemaField({
|
||||
type: new fields.StringField({
|
||||
choices: SYSTEM.ACTIONS.targetTypes,
|
||||
initial: SYSTEM.ACTIONS.targetTypes.other.id
|
||||
})
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
// Create Roll Field
|
||||
// Create Damage Field
|
||||
|
||||
export class DHBaseAction extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
return {
|
||||
_id: new fields.DocumentIdField(),
|
||||
type: new fields.StringField({ initial: undefined, readonly: true, required: true }),
|
||||
name: new fields.StringField({ initial: undefined }),
|
||||
img: new fields.FilePathField({ initial: undefined, categories: ["IMAGE"], base64: false }),
|
||||
actionType: new fields.StringField({ choices: SYSTEM.ITEM.actionTypes, initial: 'action', nullable: true }),
|
||||
roll: new fields.SchemaField({
|
||||
type: new fields.StringField({ nullable: true, initial: null, choices: SYSTEM.GENERAL.rollTypes }),
|
||||
trait: new fields.StringField({ nullable: true, initial: null, choices: SYSTEM.ACTOR.abilities }),
|
||||
difficulty: new fields.NumberField({ nullable: true, initial: null, integer: true, min: 0 })
|
||||
}),
|
||||
cost: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.abilityCosts, nullable: false, required: true, initial: 'hope' }),
|
||||
value: new fields.NumberField({ nullable: true, initial: 1 }),
|
||||
scalable: new fields.BooleanField({ initial: false }),
|
||||
step: new fields.NumberField({ nullable: true, initial: null }),
|
||||
})
|
||||
/* ,
|
||||
{ initial: [
|
||||
{ type: "hope", value: 1, scalable: false, step: null },
|
||||
{ type: "stress", value: 2, scalable: true, step: 2 }
|
||||
]} */
|
||||
),
|
||||
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: SYSTEM.GENERAL.refreshTypes, initial: null, nullable: true })
|
||||
}),
|
||||
/* duration: new fields.SchemaField({
|
||||
value: new fields.NumberField({ nullable: true, initial: null }),
|
||||
units: new fields.StringField({ required: true, blank: false, initial: "instant" })
|
||||
}), */
|
||||
target: new fields.SchemaField({
|
||||
type: new fields.StringField({ choices: SYSTEM.ACTIONS.targetTypes, initial: SYSTEM.ACTIONS.targetTypes.other.id })
|
||||
}),
|
||||
range: new fields.StringField({ choices: SYSTEM.GENERAL.range, required: true, blank: false, initial: "self" }),
|
||||
effects: new fields.ArrayField( // ActiveEffect
|
||||
new fields.SchemaField({
|
||||
'_id': new fields.DocumentIdField()
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
prepareData() {}
|
||||
|
||||
get index() {
|
||||
return this.parent.actions.indexOf(this);
|
||||
}
|
||||
|
||||
get item() {
|
||||
return this.parent.parent;
|
||||
}
|
||||
|
||||
get actor() {
|
||||
return this.item?.actor;
|
||||
}
|
||||
|
||||
static getRollType() {
|
||||
return 'ability';
|
||||
}
|
||||
|
||||
static getSourceConfig(parent) {
|
||||
const updateSource = {};
|
||||
updateSource.img ??= parent?.img ?? parent?.system?.img;
|
||||
if(parent?.system?.trait) {
|
||||
updateSource['roll'] = {
|
||||
type: this.getRollType(),
|
||||
trait: parent.system.trait
|
||||
};
|
||||
}
|
||||
if(parent?.system?.range) {
|
||||
updateSource['range'] = parent?.system?.range;
|
||||
}
|
||||
return updateSource;
|
||||
}
|
||||
|
||||
async use(event) {
|
||||
console.log(this)
|
||||
// console.log(this.item.getRollData(), this.item.actor.getRollData())
|
||||
|
||||
// const weapon = await fromUuid(button.dataset.weapon);
|
||||
let damage, modifier, roll, hope, fear, advantage, disadvantage, modifiers, bonusDamageString, targets;
|
||||
if(this.damage.parts.length) {
|
||||
damage = {
|
||||
value: `${this.actor.system[this.damage.parts[0].multiplier].value}${this.damage.parts[0].dice}`,
|
||||
type: this.damage.parts[0].type,
|
||||
bonusDamage: [this.damage.parts[0].bonus ?? 0, ...this.actor.system.bonuses.damage]
|
||||
};
|
||||
damage.value = damage.value.concat(bonusDamageString);
|
||||
}
|
||||
if(this.roll.type && this.roll.trait) {
|
||||
modifier = this.actor.system.traits[this.roll.trait].value;
|
||||
({roll, hope, fear, advantage, disadvantage, modifiers, bonusDamageString} =
|
||||
await this.actor.dualityRoll(
|
||||
{ title: game.i18n.localize(abilities[this.roll.trait].label), value: modifier },
|
||||
event.shiftKey,
|
||||
damage?.bonusDamage ?? 0
|
||||
));
|
||||
}
|
||||
console.log(roll, hope, fear, advantage, disadvantage, modifiers, bonusDamageString)
|
||||
// if(this.target?.type) {
|
||||
targets = Array.from(game.user.targets).map(x => ({
|
||||
id: x.id,
|
||||
name: x.actor.name,
|
||||
img: x.actor.img,
|
||||
difficulty: x.actor.system.difficulty,
|
||||
evasion: x.actor.system.evasion.value
|
||||
}));
|
||||
// }
|
||||
|
||||
const systemData = {
|
||||
title: this.item.name,
|
||||
origin: this.actor.id,
|
||||
roll: roll._formula,
|
||||
modifiers: modifiers,
|
||||
hope: hope,
|
||||
fear: fear,
|
||||
advantage: advantage,
|
||||
disadvantage: disadvantage,
|
||||
damage: damage,
|
||||
targets: targets
|
||||
};
|
||||
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
const msg = new cls({
|
||||
type: 'dualityRoll',
|
||||
sound: CONFIG.sounds.dice,
|
||||
system: systemData,
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/chat/attack-roll.hbs',
|
||||
systemData
|
||||
),
|
||||
rolls: [roll]
|
||||
});
|
||||
|
||||
await cls.create(msg.toObject());
|
||||
}
|
||||
}
|
||||
|
||||
export class DHAttackAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
/* attack: new fields.SchemaField({
|
||||
trait: new fields.StringField({ required: true, choices: SYSTEM.ACTOR.abilities, initial: 'agility' }),
|
||||
bonus: new fields.NumberField({ nullable: true, initial: null })
|
||||
}), */
|
||||
/* damage: new fields.SchemaField({
|
||||
baseDamage: new fields.BooleanField({ initial: true }), // Add damage from source item ?
|
||||
parts: new fields.ArrayField(
|
||||
new fields.SchemaField({ // Create DamageField
|
||||
type: new fields.StringField({
|
||||
choices: SYSTEM.GENERAL.damageTypes,
|
||||
initial: 'physical'
|
||||
}),
|
||||
value: new FormulaField({ initial: 'd6' }),
|
||||
bonus: new fields.NumberField({ nullable: true, initial: null }),
|
||||
base: new fields.BooleanField({ initial: false, readonly: true })
|
||||
})
|
||||
)
|
||||
}) */
|
||||
damage: new fields.SchemaField({
|
||||
parts: new fields.ArrayField(new fields.EmbeddedDataField(DHDamageData)),
|
||||
includeBase: new fields.BooleanField({ initial: true })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
static getRollType() {
|
||||
return 'weapon';
|
||||
}
|
||||
|
||||
prepareData() {
|
||||
super.prepareData();
|
||||
if ( this.damage.includeBase && !!this.item?.system?.damage ) {
|
||||
const baseDamage = this.getParentDamage();
|
||||
this.damage.parts.unshift(new DHDamageData(baseDamage));
|
||||
}
|
||||
}
|
||||
|
||||
getParentDamage() {
|
||||
return {
|
||||
multiplier: 'proficiency',
|
||||
dice: this.item?.system?.damage.value,
|
||||
bonus: this.item?.system?.damage.bonus ?? 0,
|
||||
type: this.item?.system?.damage.type,
|
||||
base: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class DHSpellCastAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
}
|
||||
}
|
||||
|
||||
static getRollType() {
|
||||
return 'spellcast';
|
||||
}
|
||||
}
|
||||
|
||||
export class DHResourceAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
resource: new fields.SchemaField({
|
||||
target: new fields.StringField({ choices: [], required: true, blank: false, initial: "" }),
|
||||
value: new fields.NumberField({ initial: 0 })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHDamageAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
damage: new fields.SchemaField({})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHHealingAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
type: new fields.StringField({ choices: SYSTEM.GENERAL.healingTypes, required: true, blan: false, initial: SYSTEM.GENERAL.healingTypes.health.id }),
|
||||
healing: new fields.SchemaField({})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHSummonAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
healing: new fields.SchemaField({})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHEffectAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DHMacroAction extends DHBaseAction {
|
||||
static defineSchema() {
|
||||
return {
|
||||
...super.defineSchema()
|
||||
}
|
||||
}
|
||||
}
|
||||
26
module/data/action/damage.mjs
Normal file
26
module/data/action/damage.mjs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import FormulaField from "../fields/formulaField.mjs";
|
||||
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
export default class DHDamageData extends foundry.abstract.DataModel {
|
||||
/** @override */
|
||||
static defineSchema() {
|
||||
return {
|
||||
multiplier: new fields.StringField({ choices: SYSTEM.GENERAL.multiplierTypes, initial: 'proficiency', label: 'Multiplier' }),
|
||||
dice: new fields.StringField({ choices: SYSTEM.GENERAL.diceTypes, initial: 'd6', label: 'Formula' }),
|
||||
bonus: new fields.NumberField({ nullable: true, initial: null, label: 'Bonus' }),
|
||||
base: new fields.BooleanField({ initial: false, readonly: true, label: 'Base' }),
|
||||
type: new fields.StringField({
|
||||
choices: SYSTEM.GENERAL.damageTypes,
|
||||
initial: 'physical',
|
||||
label: 'Type',
|
||||
nullable: false,
|
||||
required: true
|
||||
}),
|
||||
custom: new fields.SchemaField({
|
||||
enabled: new fields.BooleanField({ label: 'Custom Formula' }),
|
||||
formula: new FormulaField( { label: 'Formula' } )
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
11
module/data/fields/actionField.mjs
Normal file
11
module/data/fields/actionField.mjs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { actionsTypes } from "../action/_module.mjs";
|
||||
|
||||
// Temporary Solution
|
||||
export default class ActionField extends foundry.data.fields.EmbeddedDataField {
|
||||
/** @override */
|
||||
initialize(value, model, options={}) {
|
||||
this.model = actionsTypes[value?.type] ?? actionsTypes.attack;
|
||||
this.fields = this._initialize(this.model.defineSchema());
|
||||
return super.initialize(value, model, options)
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ export default class ForeignDocumentUUIDField extends foundry.data.fields.Docume
|
|||
/**@override */
|
||||
initialize(value, _model, _options = {}) {
|
||||
if (this.idOnly) return value;
|
||||
return () => {
|
||||
return (() => {
|
||||
try {
|
||||
const doc = fromUuidSync(value);
|
||||
return doc;
|
||||
|
|
@ -32,7 +32,7 @@ export default class ForeignDocumentUUIDField extends foundry.data.fields.Docume
|
|||
console.error(error);
|
||||
return value ?? null;
|
||||
}
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
/**@override */
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export {
|
|||
DHFeature,
|
||||
DHMiscellaneous,
|
||||
DHSubclass,
|
||||
DHWeapon,
|
||||
DHWeapon
|
||||
}
|
||||
|
||||
export const config = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import DHAction from "../action.mjs";
|
||||
import DHAction from "../action/action.mjs";
|
||||
import BaseDataItem from "./base.mjs";
|
||||
|
||||
export default class DHDomainCard extends BaseDataItem {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { getTier } from '../../helpers/utils.mjs';
|
||||
import DHAction from '../action.mjs';
|
||||
import DHAction from '../action/action.mjs';
|
||||
import BaseDataItem from './base.mjs';
|
||||
|
||||
export default class DHFeature extends BaseDataItem {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import BaseDataItem from "./base.mjs";
|
||||
import FormulaField from "../fields/formulaField.mjs";
|
||||
import ActionField from "../fields/actionField.mjs"
|
||||
import { DHBaseAction, DHAttackAction } from "../action/action.mjs";
|
||||
|
||||
export default class DHWeapon extends BaseDataItem {
|
||||
/** @inheritDoc */
|
||||
|
|
@ -33,8 +35,9 @@ export default class DHWeapon extends BaseDataItem {
|
|||
initial: 'physical'
|
||||
})
|
||||
}),
|
||||
|
||||
feature: new fields.StringField({ choices: SYSTEM.ITEM.weaponFeatures, blank: true }),
|
||||
actions: new fields.ArrayField(new fields.EmbeddedDataField(DHAttackAction))
|
||||
// actions: new fields.ArrayField(new ActionField(DHBaseAction))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ export default class DhpItem extends Item {
|
|||
// this.system.domains = CONFIG.daggerheart.DOMAIN.classDomainMap[Object.keys(CONFIG.daggerheart.DOMAIN.classDomainMap).find(x => x === this.name.toLowerCase())];
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
prepareEmbeddedDocuments() {
|
||||
super.prepareEmbeddedDocuments();
|
||||
for ( const action of this.system.actions ?? [] ) action.prepareData();
|
||||
// for ( const action of this.system.actions ?? [] ) console.log(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
|
@ -99,4 +106,46 @@ export default class DhpItem extends Item {
|
|||
options
|
||||
});
|
||||
}
|
||||
|
||||
async selectActionDialog() {
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
"systems/daggerheart/templates/views/actionSelect.hbs",
|
||||
{actions: this.system.actions}
|
||||
),
|
||||
title = 'Select Action',
|
||||
type = 'div',
|
||||
data = {};
|
||||
return Dialog.prompt({
|
||||
title,
|
||||
// label: title,
|
||||
content, type,
|
||||
callback: html => {
|
||||
const form = html[0].querySelector("form"),
|
||||
fd = new foundry.applications.ux.FormDataExtended(form);
|
||||
return this.system.actions.find(a => a._id === fd.object.actionId);
|
||||
},
|
||||
rejectClose: false
|
||||
})
|
||||
}
|
||||
|
||||
async use(event) {
|
||||
const actions = this.system.actions;
|
||||
if(actions?.length) {
|
||||
let action = actions[0];
|
||||
if(actions.length > 1 && !event?.shiftKey) {
|
||||
// Actions Choice Dialog
|
||||
action = await this.selectActionDialog();
|
||||
}
|
||||
if(!action) return;
|
||||
// Check Target
|
||||
// If action.roll => Roll Dialog
|
||||
// Else If action.cost => Cost Dialog
|
||||
// Then
|
||||
// Apply Cost
|
||||
// Apply Effect
|
||||
|
||||
return action.use(event);
|
||||
}
|
||||
// Display Item Card in chat
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -452,6 +452,37 @@ div.daggerheart.views.multiclass {
|
|||
&.open {
|
||||
max-height: initial;
|
||||
}
|
||||
|
||||
.multi-display {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
.form-group {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: .5rem;
|
||||
label {
|
||||
flex: 2;
|
||||
}
|
||||
.form-fields {
|
||||
flex: 3;
|
||||
}
|
||||
img {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.data-form-array {
|
||||
border: 1px solid var(--color-fieldset-border);
|
||||
padding: .5rem;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,3 +125,38 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.unlist {
|
||||
list-style: none;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
.list-select {
|
||||
margin: 1rem;
|
||||
li {
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid #bbb;
|
||||
}
|
||||
label {
|
||||
padding: 4px 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
cursor: pointer;
|
||||
> span {
|
||||
flex: 1;
|
||||
font-weight: bold;
|
||||
font-size: var(--font-size-16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dh-icon, dh-icon > img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: x-large;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
<li class="item inventory-item">
|
||||
<div class="inventory-row" data-item-id="{{item.uuid}}">
|
||||
<div class="inventory-item-title-container">
|
||||
<div data-action="viewObject" data-value="{{item.uuid}}" class="inventory-item-title">
|
||||
<div data-action="useItem" data-value="{{item.uuid}}" class="inventory-item-title">
|
||||
<img src="{{item.img}}" />
|
||||
{{item.name}}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<div>
|
||||
<header>
|
||||
{{formField fields.name value=source.name label="Name" name="name" rootId=partId}}
|
||||
{{!-- {{formField fields.name value=source.name label="Name" name="name" rootId=partId}} --}}
|
||||
<nav class="sheet-tabs tabs">
|
||||
{{#each tabs as |tab|}}
|
||||
<a class="{{tab.cssClass}}" data-action="tab" data-group="{{tab.group}}" data-tab="{{tab.id}}">
|
||||
|
|
@ -11,7 +11,39 @@
|
|||
</nav>
|
||||
</header>
|
||||
<section>
|
||||
<div class="tab {{this.tabs.effects.cssClass}}" data-group="primary" data-tab="effects">
|
||||
<div class="tab {{this.tabs.base.cssClass}}" data-group="primary" data-tab="base">
|
||||
<fieldset class="action-category">
|
||||
<legend class="action-category-label" data-action="toggleSection" data-section="identity">
|
||||
<div>Identity</div>
|
||||
</legend>
|
||||
<div class="action-category-data open">
|
||||
{{formField fields.name value=source.name label="Name" name="name"}}
|
||||
{{formField fields.img value=source.img label="Icon" name="img"}}
|
||||
{{formField fields.actionType value=source.actionType label="Type" name="actionType" localize=true}}
|
||||
</div>
|
||||
</fieldset>
|
||||
{{> 'systems/daggerheart/templates/views/actionTypes/roll.hbs' fields=fields.roll.fields source=source.roll}}
|
||||
</div>
|
||||
<div class="tab {{this.tabs.config.cssClass}}" data-group="primary" data-tab="config">
|
||||
{{> 'systems/daggerheart/templates/views/actionTypes/uses.hbs' fields=fields.uses.fields source=source.uses}}
|
||||
{{> 'systems/daggerheart/templates/views/actionTypes/cost.hbs' fields=fields.cost.element.fields source=source.cost}}
|
||||
{{> 'systems/daggerheart/templates/views/actionTypes/range-target.hbs' fields=(object range=fields.range target=fields.target.fields) source=(object target=source.target range=source.range)}}
|
||||
</div>
|
||||
<div class="tab {{this.tabs.effect.cssClass}}" data-group="primary" data-tab="effect">
|
||||
{{#if source.damage}}
|
||||
{{> 'systems/daggerheart/templates/views/actionTypes/damage.hbs' fields=fields.damage.fields.parts.element.fields source=source.damage}}
|
||||
{{/if}}
|
||||
{{!-- {{#switch source.type}}
|
||||
{{#case 'attack'}}
|
||||
{{> 'systems/daggerheart/templates/views/actionTypes/damage.hbs' fields=fields.damage.element.fields source=source.damage}}
|
||||
{{/case}}
|
||||
{{#case 'spellcast'}}
|
||||
<div>SpellCast</div>
|
||||
{{/case}}
|
||||
{{/switch}} --}}
|
||||
{{> 'systems/daggerheart/templates/views/actionTypes/effect.hbs'}}
|
||||
</div>
|
||||
{{!-- <div class="tab {{this.tabs.effects.cssClass}}" data-group="primary" data-tab="effects">
|
||||
<fieldset class="action-category">
|
||||
<legend class="action-category-label" data-action="toggleSection" data-section="damage">
|
||||
<div>Damage</div>
|
||||
|
|
@ -48,14 +80,14 @@
|
|||
{{formField fields.target.fields.type value=source.target.type label="Target Type" name="target.type" rootId=partId}}
|
||||
</div>
|
||||
<div class="tab {{this.tabs.conditions.cssClass}}" data-group="primary" data-tab="conditions">
|
||||
{{!-- <h2>
|
||||
<h2>
|
||||
{{localize "Conditions"}}
|
||||
<select class="effect-select">
|
||||
{{selectOptions this.config.effectTypes selected=this.selectedEffectType labelAttr="name" localize=true blank=""}}
|
||||
</select>
|
||||
<i class="fa-solid fa-plus icon-button {{#if (not this.selectedEffectType)}}disabled{{/if}}" data-action="addCondition"></i>
|
||||
</h2> --}}
|
||||
</div>
|
||||
</h2>
|
||||
</div> --}}
|
||||
</section>
|
||||
<button type="submit">Save</button>
|
||||
{{!-- <button type="submit">Save</button> --}}
|
||||
</div>
|
||||
13
templates/views/actionSelect.hbs
Normal file
13
templates/views/actionSelect.hbs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<form id="item-action-select">
|
||||
<ul class="unlist list-select">
|
||||
{{#each actions}}
|
||||
<li>
|
||||
<label>
|
||||
<dh-icon><img src="{{ img }}"></dh-icon>
|
||||
<span>{{ name }}</span>
|
||||
<input type="radio" name="actionId" value="{{_id}}" {{#if (eq @index 0)}}checked{{/if}}>
|
||||
</label>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</form>
|
||||
13
templates/views/actionType.hbs
Normal file
13
templates/views/actionType.hbs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<form id="action-type-select">
|
||||
<ul class="unlist list-select">
|
||||
{{#each types}}
|
||||
<li>
|
||||
<label>
|
||||
<dh-icon class="dh-icon fas {{icon}}"></dh-icon>
|
||||
<span>{{localize name}}</span>
|
||||
<input type="radio" name="type" value="{{id}}" {{#if (eq @index 0)}}checked{{/if}}>
|
||||
</label>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</form>
|
||||
21
templates/views/actionTypes/cost.hbs
Normal file
21
templates/views/actionTypes/cost.hbs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<fieldset class="action-category">
|
||||
<legend class="action-category-label" data-action="toggleSection" data-section="cost">
|
||||
<div>Cost</div>
|
||||
</legend>
|
||||
<div class="action-category-data open" data-key="cost">
|
||||
<div class="fas fa-plus icon-button" data-action="addElement"></div>
|
||||
{{#each source as |cost index|}}
|
||||
<fieldset>
|
||||
<div class="multi-display">
|
||||
{{formField ../fields.type label="Resource" value=cost.type name=(concat "cost." index ".type") localize=true}}
|
||||
{{formField ../fields.value label="Value" value=cost.value name=(concat "cost." index ".value")}}
|
||||
</div>
|
||||
<div class="multi-display">
|
||||
{{formField ../fields.scalable label="Scalable" value=cost.scalable name=(concat "cost." index ".scalable")}}
|
||||
{{formField ../fields.step label="Step" value=cost.step name=(concat "cost." index ".step")}}
|
||||
</div>
|
||||
<div class="fas fa-trash" data-action="removeElement" data-index="{{index}}"></div>
|
||||
</fieldset>
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
36
templates/views/actionTypes/damage.hbs
Normal file
36
templates/views/actionTypes/damage.hbs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
<fieldset class="action-category">
|
||||
<legend class="action-category-label" data-action="toggleSection" data-section="effects">
|
||||
<div>Damage</div>
|
||||
</legend>
|
||||
<div class="action-category-data open">
|
||||
<div class="fas fa-plus icon-button" data-action="addDamage"></div>
|
||||
{{#if @root.hasBaseDamage}}
|
||||
<div>
|
||||
{{!-- <input type="checkbox" data-action="addBaseDamage"{{#if @root.hasBaseDamage}} checked{{/if}}> --}}
|
||||
{{formField @root.fields.damage.fields.includeBase value=@root.source.damage.includeBase label="Include Item Damage" name="damage.includeBase" }}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#each source.parts as |dmg index|}}
|
||||
{{#with (@root.getRealIndex index) as | realIndex |}}
|
||||
<fieldset{{#if dmg.base}} disabled{{/if}}>
|
||||
{{#unless dmg.base}}
|
||||
{{formField ../../fields.custom.fields.enabled value=dmg.custom.enabled name=(concat "damage.parts." realIndex ".custom.enabled")}}
|
||||
{{/unless}}
|
||||
{{#if dmg.custom.enabled}}
|
||||
{{formField ../../fields.custom.fields.formula value=dmg.custom.formula name=(concat "damage.parts." realIndex ".custom.formula") localize=true}}
|
||||
{{else}}
|
||||
<div class="multi-display">
|
||||
{{formField ../../fields.multiplier value=dmg.multiplier name=(concat "damage.parts." realIndex ".multiplier") localize=true}}
|
||||
{{formField ../../fields.dice value=dmg.dice name=(concat "damage.parts." realIndex ".dice")}}
|
||||
{{formField ../../fields.bonus value=dmg.bonus name=(concat "damage.parts." realIndex ".bonus") localize=true}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{formField ../../fields.type value=dmg.type name=(concat "damage.parts." realIndex ".type") localize=true}}
|
||||
<input type="hidden" name="damage.parts.{{realIndex}}.base" value="{{dmg.base}}">
|
||||
{{#unless dmg.base}}<div class="fas fa-trash" data-action="removeDamage" data-index="{{realIndex}}"></div>{{/unless}}
|
||||
</fieldset>
|
||||
{{/with}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
19
templates/views/actionTypes/effect.hbs
Normal file
19
templates/views/actionTypes/effect.hbs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<fieldset class="action-category">
|
||||
<legend class="action-category-label" data-action="toggleSection" data-section="effects">
|
||||
<div>Effects</div>
|
||||
</legend>
|
||||
<div class="action-category-data open" data-key="effects">
|
||||
<div class="fas fa-plus icon-button" data-action="addEffect"></div>
|
||||
{{#each @root.effects as | effect index | }}
|
||||
<fieldset>
|
||||
{{!-- <div class="multi-display"> --}}
|
||||
<div class="form-group">
|
||||
<img src="{{img}}">
|
||||
<label data-action="editEffect">{{name}}</label>
|
||||
<div class="fas fa-trash" data-action="removeEffect" data-index="{{index}}"></div>
|
||||
</div>
|
||||
{{!-- </div> --}}
|
||||
</fieldset>
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
11
templates/views/actionTypes/range-target.hbs
Normal file
11
templates/views/actionTypes/range-target.hbs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<fieldset class="action-category">
|
||||
<legend class="action-category-label" data-action="toggleSection" data-section="range">
|
||||
<div>Range & Target</div>
|
||||
</legend>
|
||||
<div class="action-category-data open">
|
||||
{{formField fields.range value=source.range label="Range" name="range" localize=true}}
|
||||
</div>
|
||||
<div class="action-category-data open">
|
||||
{{formField fields.target.type value=source.target.type label="Target" name="target.type" localize=true}}
|
||||
</div>
|
||||
</fieldset>
|
||||
10
templates/views/actionTypes/roll.hbs
Normal file
10
templates/views/actionTypes/roll.hbs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<fieldset class="action-category">
|
||||
<legend class="action-category-label" data-action="toggleSection" data-section="roll">
|
||||
<div>Roll</div>
|
||||
</legend>
|
||||
<div class="action-category-data open">
|
||||
{{formField fields.type label="Type" name="roll.type" value=source.type localize=true}}
|
||||
{{formField fields.trait label="Trait" name="roll.trait" value=source.trait localize=true}}
|
||||
{{formField fields.difficulty label="Difficulty" name="roll.difficulty" value=source.difficulty}}
|
||||
</div>
|
||||
</fieldset>
|
||||
8
templates/views/actionTypes/target.hbs
Normal file
8
templates/views/actionTypes/target.hbs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<fieldset class="action-category">
|
||||
<legend class="action-category-label" data-action="toggleSection" data-section="target">
|
||||
<div>Target</div>
|
||||
</legend>
|
||||
<div class="action-category-data open">
|
||||
{{formField targetField.type label="Target" name="target" rootId=partId localize=true}}
|
||||
</div>
|
||||
</fieldset>
|
||||
12
templates/views/actionTypes/uses.hbs
Normal file
12
templates/views/actionTypes/uses.hbs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<fieldset class="action-category">
|
||||
<legend class="action-category-label" data-action="toggleSection" data-section="uses">
|
||||
<div>Uses</div>
|
||||
</legend>
|
||||
<div class="action-category-data open">
|
||||
<div class="multi-display">
|
||||
{{formField fields.value label="Value" value=source.value name="uses.value" rootId=partId}}
|
||||
{{formField fields.max label="Max" value=source.max name="uses.max" rootId=partId}}
|
||||
</div>
|
||||
{{formField fields.recovery label="Recovery" value=source.recovery name="uses.recovery" rootId=partId localize=true}}
|
||||
</div>
|
||||
</fieldset>
|
||||
Loading…
Add table
Add a link
Reference in a new issue