From 774141a8da52286075113c51976d5fc77cc01fb3 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sun, 19 Apr 2026 15:20:38 +0200 Subject: [PATCH] Completed --- module/data/chat-message/abilityUse.mjs | 45 +++++++------ module/data/fields/action/areaField.mjs | 5 ++ module/data/fields/actionField.mjs | 6 ++ module/documents/chatMessage.mjs | 84 ++++++++++++------------- styles/less/ui/chat/chat.less | 8 ++- templates/actionTypes/area.hbs | 5 +- templates/ui/chat/action.hbs | 5 ++ templates/ui/chat/parts/button-part.hbs | 2 +- 8 files changed, 94 insertions(+), 66 deletions(-) diff --git a/module/data/chat-message/abilityUse.mjs b/module/data/chat-message/abilityUse.mjs index 07209fe2..3c209355 100644 --- a/module/data/chat-message/abilityUse.mjs +++ b/module/data/chat-message/abilityUse.mjs @@ -7,26 +7,31 @@ export default class DHAbilityUse extends foundry.abstract.TypeDataModel { img: new fields.StringField({}), name: new fields.StringField({}), description: new fields.StringField({}), - actions: new fields.ArrayField( - new fields.ObjectField({ - name: new fields.StringField({}), - damage: new fields.SchemaField({ - type: new fields.StringField({}), - value: new fields.StringField({}) - }), - healing: new fields.SchemaField({ - type: new fields.StringField({}), - value: new fields.StringField({}) - }), - cost: new fields.SchemaField({ - type: new fields.StringField({}), - value: new fields.NumberField({}) - }), - target: new fields.SchemaField({ - type: new fields.StringField({ nullable: true }) - }) - }) - ) + source: new fields.SchemaField({ + actor: new fields.StringField(), + item: new fields.StringField(), + action: new fields.StringField() + }), }; } + + get actionActor() { + if (!this.source.actor) return null; + return fromUuidSync(this.source.actor); + } + + get actionItem() { + const actionActor = this.actionActor; + if (!actionActor || !this.source.item) return null; + + const item = actionActor.items.get(this.source.item); + return item ? item.system.actionsList?.find(a => a.id === this.source.action) : null; + } + + get action() { + const { actionItem: itemAction } = this; + if (!this.source.action) return null; + if (itemAction) return itemAction; + return null; + } } diff --git a/module/data/fields/action/areaField.mjs b/module/data/fields/action/areaField.mjs index ec6f616e..28db74fe 100644 --- a/module/data/fields/action/areaField.mjs +++ b/module/data/fields/action/areaField.mjs @@ -9,6 +9,11 @@ export default class AreaField extends fields.ArrayField { /** @inheritDoc */ constructor(options = {}, context = {}) { const element = new fields.SchemaField({ + name: new fields.StringField({ + nullable: false, + initial: 'Area', + label: 'DAGGERHEART.GENERAL.name' + }), type: new fields.StringField({ nullable: false, choices: CONFIG.DH.ACTIONS.areaTypes, diff --git a/module/data/fields/actionField.mjs b/module/data/fields/actionField.mjs index ffdc25cd..d4698d4a 100644 --- a/module/data/fields/actionField.mjs +++ b/module/data/fields/actionField.mjs @@ -281,8 +281,14 @@ export function ActionMixin(Base) { name: this.name, img: this.baseAction ? this.parent.parent.img : this.img, tags: this.tags ? this.tags : ['Spell', 'Arcana', 'Lv 10'], + area: this.area, summon: this.summon }, + source: { + actor: this.actor.uuid, + item: this.item.id, + action: this.id, + }, itemOrigin: this.item, description: this.description || (this.item instanceof Item ? this.item.system.description : '') }; diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs index 702dd0a0..4839e433 100644 --- a/module/documents/chatMessage.mjs +++ b/module/documents/chatMessage.mjs @@ -254,53 +254,51 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { } async onCreateAreas(event) { - let selectedArea = null; - if (this.system.action.area.length === 1) - selectedArea = this.system.action.area[0]; - else if(this.system.action.area.length > 1) { - /* Pop a selection. Possibly a context menu? */ - // new foundry.applications.ux.ContextMenu.implementation( - // event.target, - // '.scene-environment', - // this.system.action.area.map((area, index) => ({ - // name: index, - // callback: () => { - - // } - // })), - // { - // jQuery: false, - // fixed: true - // } - // ); + const createArea = async (selectedArea) => { + const effects = selectedArea.effects.map(effect => this.system.action.item.effects.get(effect).uuid); + const { shape: type, size: range } = selectedArea; + const shapeData = CONFIG.Canvas.layers.regions.layerClass.getTemplateShape({ type, range }); - // CONFIG.ux.ContextMenu.triggerContextMenu(event, '.scene-environment'); + await canvas.regions.placeRegion( + { + name: selectedArea.name, + shapes: [shapeData], + restriction: { enabled: false, type: 'move', priority: 0 }, + behaviors: [{ + name: game.i18n.localize('TYPES.RegionBehavior.applyActiveEffect'), + type: 'applyActiveEffect', + system: { + effects: effects + } + }], + displayMeasurements: true, + locked: false, + ownership: { default: CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE }, + visibility: CONST.REGION_VISIBILITY.ALWAYS + }, + { create: true } + ); } - if(!selectedArea) return; - const effects = selectedArea.effects.map(effect => this.system.action.item.effects.get(effect).uuid); - const { shape: type, size: range } = this.system.action.area[0]; - const shapeData = CONFIG.Canvas.layers.regions.layerClass.getTemplateShape({ type, range }); + if (this.system.action.area.length === 1) + createArea(this.system.action.area[0]); + else if(this.system.action.area.length > 1) { + /* Pop a selection. Possibly a context menu? */ + new foundry.applications.ux.ContextMenu.implementation( + event.target, + '.action-areas', + this.system.action.area.map((area, index) => ({ + name: area.name, + callback: () => createArea(this.system.action.area[index]), + })), + { + jQuery: false, + fixed: true + } + ); - await canvas.regions.placeRegion( - { - name: 'Test', - shapes: [shapeData], - restriction: { enabled: false, type: 'move', priority: 0 }, - behaviors: [{ - name: game.i18n.localize('TYPES.RegionBehavior.applyActiveEffect'), - type: 'applyActiveEffect', - system: { - effects: effects - } - }], - displayMeasurements: true, - locked: false, - ownership: { default: CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE }, - visibility: CONST.REGION_VISIBILITY.ALWAYS - }, - { create: true } - ); + CONFIG.ux.ContextMenu.triggerContextMenu(event, '.action-areas'); + } } filterPermTargets(targets) { diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index 6b11e1ff..abb98ad9 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -629,7 +629,8 @@ height: 32px; flex: 1; - &.no-flex { + &.end-button { + margin-left: auto; flex: 0; } } @@ -703,6 +704,11 @@ } } + .action-roll-buttons { + width: 100%; + padding: 0 8px; + } + .description { padding: 8px; diff --git a/templates/actionTypes/area.hbs b/templates/actionTypes/area.hbs index 810e67b9..bb4a3e05 100644 --- a/templates/actionTypes/area.hbs +++ b/templates/actionTypes/area.hbs @@ -6,11 +6,14 @@ {{#each source as |area index|}} {{#unless @first}}{{/unless}} +
+ {{formField ../fields.name value=area.name name=(concat "area." index ".name") localize=true}} + +
{{formField ../fields.type value=area.type name=(concat "area." index ".type") localize=true}} {{formField ../fields.shape value=area.shape name=(concat "area." index ".shape") localize=true}} {{formField ../fields.size value=area.size name=(concat "area." index ".size") localize=true}} -
diff --git a/templates/ui/chat/action.hbs b/templates/ui/chat/action.hbs index 2854795c..00d01040 100644 --- a/templates/ui/chat/action.hbs +++ b/templates/ui/chat/action.hbs @@ -26,4 +26,9 @@ {{/if}}
+ {{#if action.area.length}} +
+ +
+ {{/if}} \ No newline at end of file diff --git a/templates/ui/chat/parts/button-part.hbs b/templates/ui/chat/parts/button-part.hbs index 73c9d9cb..26855611 100644 --- a/templates/ui/chat/parts/button-part.hbs +++ b/templates/ui/chat/parts/button-part.hbs @@ -14,5 +14,5 @@ {{/unless}} {{/if}} {{#if (and hasEffect)}}{{/if}} - {{#if areas.length}}{{/if}} + {{#if areas.length}}{{/if}} \ No newline at end of file