actions types - attack roll

This commit is contained in:
Dapoolp 2025-06-10 23:41:25 +02:00
parent 4c7f3a02c4
commit edaf5df9e0
35 changed files with 1015 additions and 165 deletions

View file

@ -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 });
}
}

View file

@ -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 : {};

View file

@ -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

View file

@ -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

View file

@ -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)
)
});
}
}

View file

@ -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();