Added actions and effects to Ancestry and Community (#143)

This commit is contained in:
WBHarry 2025-06-15 13:18:52 +02:00 committed by GitHub
parent 5b94675db1
commit 0fbba51ad7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 272 additions and 170 deletions

View file

@ -1194,8 +1194,9 @@
} }
} }
}, },
"Heritage": { "Global": {
"Title": "Abilities" "Actions": "Actions",
"Effects": "Effects"
}, },
"DomainCard": { "DomainCard": {
"Type": "Type", "Type": "Type",

View file

@ -1,88 +1,13 @@
import DaggerheartSheet from '../daggerheart-sheet.mjs'; import DHHeritageSheetV2 from './heritage.mjs';
const { ItemSheetV2 } = foundry.applications.sheets; const { ItemSheetV2 } = foundry.applications.sheets;
export default class AncestrySheet extends DaggerheartSheet(ItemSheetV2) { export default class AncestrySheet extends DHHeritageSheetV2(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', classes: ['ancestry']
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 }]
}; };
static PARTS = { static PARTS = {
header: { template: 'systems/daggerheart/templates/sheets/items/ancestry/header.hbs' }, header: { template: 'systems/daggerheart/templates/sheets/items/ancestry/header.hbs' },
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, ...super.PARTS
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']
}
}; };
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 }
]
});
}
}
} }

View file

@ -1,88 +1,13 @@
import DaggerheartSheet from '../daggerheart-sheet.mjs'; import DHHeritageSheetV2 from './heritage.mjs';
const { ItemSheetV2 } = foundry.applications.sheets; const { ItemSheetV2 } = foundry.applications.sheets;
export default class CommunitySheet extends DaggerheartSheet(ItemSheetV2) { export default class CommunitySheet extends DHHeritageSheetV2(ItemSheetV2) {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', classes: ['community']
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 }]
}; };
static PARTS = { static PARTS = {
header: { template: 'systems/daggerheart/templates/sheets/items/community/header.hbs' }, header: { template: 'systems/daggerheart/templates/sheets/items/community/header.hbs' },
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, ...super.PARTS
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']
}
}; };
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 }
]
});
}
}
} }

View 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();
}
};
}

View file

@ -1,12 +1,13 @@
import ActionField from '../fields/actionField.mjs';
import BaseDataItem from './base.mjs'; import BaseDataItem from './base.mjs';
export default class DHAncestry extends BaseDataItem { export default class DHAncestry extends BaseDataItem {
/** @inheritDoc */ /** @inheritDoc */
static get metadata() { static get metadata() {
return foundry.utils.mergeObject(super.metadata, { return foundry.utils.mergeObject(super.metadata, {
label: "TYPES.Item.ancestry", label: 'TYPES.Item.ancestry',
type: "ancestry", type: 'ancestry',
hasDescription: true, hasDescription: true
}); });
} }
@ -15,7 +16,7 @@ export default class DHAncestry extends BaseDataItem {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
...super.defineSchema(), ...super.defineSchema(),
//TODO: add features field actions: new fields.ArrayField(new ActionField())
}; };
} }
} }

View file

@ -1,22 +1,22 @@
import ActionField from '../fields/actionField.mjs';
import BaseDataItem from './base.mjs'; import BaseDataItem from './base.mjs';
export default class DHCommunity extends BaseDataItem { export default class DHCommunity extends BaseDataItem {
/** @inheritDoc */ /** @inheritDoc */
static get metadata() { static get metadata() {
return foundry.utils.mergeObject(super.metadata, { return foundry.utils.mergeObject(super.metadata, {
label: "TYPES.Item.community", label: 'TYPES.Item.community',
type: "community", type: 'community',
hasDescription: true, hasDescription: true
}); });
} }
/** @inheritDoc */ /** @inheritDoc */
static defineSchema() { static defineSchema() {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
...super.defineSchema(), ...super.defineSchema(),
//TODO: add features field actions: new fields.ArrayField(new ActionField())
}; };
} }
} }

View file

@ -3415,6 +3415,41 @@ div.daggerheart.views.multiclass {
.sheet.daggerheart.dh-style .tab.actions .actions-list .action-item .controls a { .sheet.daggerheart.dh-style .tab.actions .actions-list .action-item .controls a {
text-shadow: none; text-shadow: none;
} }
.sheet.daggerheart.dh-style .tab.effects .effects-list {
display: flex;
flex-direction: column;
list-style: none;
padding: 0;
margin: 0;
width: 100%;
gap: 5px;
}
.sheet.daggerheart.dh-style .tab.effects .effects-list .effect-item {
display: grid;
align-items: center;
grid-template-columns: 1fr 4fr 1fr;
cursor: pointer;
}
.sheet.daggerheart.dh-style .tab.effects .effects-list .effect-item h4 {
font-family: 'Montserrat', sans-serif;
font-weight: lighter;
color: #efe6d8;
}
.sheet.daggerheart.dh-style .tab.effects .effects-list .effect-item .image {
height: 40px;
width: 40px;
object-fit: cover;
border-radius: 6px;
border: none;
}
.sheet.daggerheart.dh-style .tab.effects .effects-list .effect-item .controls {
display: flex;
justify-content: center;
gap: 10px;
}
.sheet.daggerheart.dh-style .tab.effects .effects-list .effect-item .controls a {
text-shadow: none;
}
.application.sheet.daggerheart.dh-style .item-sheet-header { .application.sheet.daggerheart.dh-style .item-sheet-header {
display: flex; display: flex;
} }

View file

@ -29,6 +29,7 @@
@import './less/global/tab-navigation.less'; @import './less/global/tab-navigation.less';
@import './less/global/tab-form-footer.less'; @import './less/global/tab-form-footer.less';
@import './less/global/tab-actions.less'; @import './less/global/tab-actions.less';
@import './less/global/tab-effects.less';
@import './less/global/item-header.less'; @import './less/global/item-header.less';
@import './less/global/feature-section.less'; @import './less/global/feature-section.less';

View file

@ -0,0 +1,46 @@
@import '../utils/colors.less';
@import '../utils/fonts.less';
.sheet.daggerheart.dh-style {
.tab.effects {
.effects-list {
display: flex;
flex-direction: column;
list-style: none;
padding: 0;
margin: 0;
width: 100%;
gap: 5px;
.effect-item {
display: grid;
align-items: center;
grid-template-columns: 1fr 4fr 1fr;
cursor: pointer;
h4 {
font-family: @font-body;
font-weight: lighter;
color: @beige;
}
.image {
height: 40px;
width: 40px;
object-fit: cover;
border-radius: 6px;
border: none;
}
.controls {
display: flex;
justify-content: center;
gap: 10px;
a {
text-shadow: none;
}
}
}
}
}
}

View file

@ -4,7 +4,7 @@
data-group='{{tabs.actions.group}}' data-group='{{tabs.actions.group}}'
> >
<fieldset class="one-column"> <fieldset class="one-column">
<legend>{{localize "Actions"}} <a><i class="fa-solid fa-plus icon-button" data-action="addAction"></i></a></legend> <legend>{{localize "DAGGERHEART.Sheets.Global.Actions"}} <a><i class="fa-solid fa-plus icon-button" data-action="addAction"></i></a></legend>
<div class="actions-list"> <div class="actions-list">
{{#each document.system.actions as |action index|}} {{#each document.system.actions as |action index|}}
<div class="action-item"> <div class="action-item">

View file

@ -0,0 +1,21 @@
<section
class='tab {{tabs.effects.cssClass}} {{tabs.effects.id}}'
data-tab='{{tabs.effects.id}}'
data-group='{{tabs.effects.group}}'
>
<fieldset class="one-column">
<legend>{{localize "DAGGERHEART.Sheets.Global.Effects"}} <a><i class="fa-solid fa-plus icon-button" data-action="addEffect"></i></a></legend>
<div class="effects-list">
{{#each document.effects as |effect|}}
<div class="effect-item">
<img class="image" src="{{effect.img}}" />
<span>{{effect.name}}</span>
<div class="controls">
<a data-action="editEffect" data-effect="{{effect.id}}"><i class="fa-solid fa-pen-to-square"></i></a>
<a data-action="removeEffect" data-effect="{{effect.id}}"><i class="fa-solid fa-trash"></i></a>
</div>
</div>
{{/each}}
</div>
</fieldset>
</section>