Feature/200 beastform (#255)

* Temp

* Dialog setup

* Fixed basic beastform

* Reworked beastform to hold it's data entirely in the beastformEffect

* UpdateActorTokens fix

* Removed hardcoded tierlimit on beastform

* PR fixes
This commit is contained in:
WBHarry 2025-07-04 02:02:14 +02:00 committed by GitHub
parent c4448226e0
commit d071fadf7d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 1102 additions and 298 deletions

View file

@ -15,7 +15,8 @@ export { default as DhpChatMessage } from './chatMessage.mjs';
export { default as DhpEnvironment } from './sheets/actors/environment.mjs';
export { default as DhActiveEffectConfig } from './sheets/activeEffectConfig.mjs';
export { default as DhContextMenu } from './contextMenu.mjs';
export { default as DhBeastform } from './sheets/items/beastform.mjs';
export { default as DhTooltipManager } from './tooltipManager.mjs';
export * as api from './sheets/api/_modules.mjs';
export * as ux from "./ux/_module.mjs";
export * as ux from './ux/_module.mjs';

View file

@ -69,6 +69,13 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
context.disableOption = this.disableOption.bind(this);
context.isNPC = this.action.actor && this.action.actor.type !== 'character';
context.hasRoll = this.action.hasRoll;
const settingsTiers = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.LevelTiers).tiers;
context.tierOptions = [
{ key: 1, label: game.i18n.localize('DAGGERHEART.Tiers.tier1') },
...Object.values(settingsTiers).map(x => ({ key: x.tier, label: x.name }))
];
return context;
}

View file

@ -5,7 +5,7 @@ const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
export default class RollSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(experiences, costs, action, resolve) {
super({}, {});
this.experiences = experiences;
this.costs = costs;
this.action = action;
@ -67,9 +67,9 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
context.fear = this.data.fear;
context.advantage = this.data.advantage;
context.experiences = Object.keys(this.experiences).map(id => ({ id, ...this.experiences[id] }));
if(this.costs?.length) {
if (this.costs?.length) {
const updatedCosts = this.action.calcCosts(this.costs);
context.costs = updatedCosts
context.costs = updatedCosts;
context.canRoll = this.action.getRealCosts(updatedCosts)?.hasCost;
} else context.canRoll = true;

View file

@ -7,6 +7,8 @@ import { abilities } from '../../../config/actorConfig.mjs';
import DhCharacterlevelUp from '../../levelup/characterLevelup.mjs';
import DhCharacterCreation from '../../characterCreation.mjs';
import FilterMenu from '../../ux/filter-menu.mjs';
import { DhBeastformAction } from '../../../data/action/action.mjs';
import DHActionConfig from '../../config/Action.mjs';
const { ActorSheetV2 } = foundry.applications.sheets;
const { TextEditor } = foundry.applications.ux;
@ -306,11 +308,14 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
getItem(element) {
const listElement = (element.target ?? element).closest('[data-item-id]');
const document = listElement.dataset.companion ? this.document.system.companion : this.document;
const itemId = listElement.dataset.itemId,
item = document.items.get(itemId);
return item;
const itemId = listElement.dataset.itemId;
if (listElement.dataset.type === 'effect') {
return this.document.effects.get(itemId);
} else if (['armor', 'weapon', 'feature', 'consumable', 'miscellaneous'].includes(listElement.dataset.type)) {
return this.document.items.get(itemId);
} else {
return this.document.system[listElement.dataset.type].system.actions.find(x => x.id === itemId);
}
}
static triggerContextMenu(event, button) {
@ -733,7 +738,9 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
// Should dandle its actions. Or maybe they'll be separate buttons as per an Issue on the board
if (item.type === 'feature') {
item.toChat();
item.use(event);
} else if (item instanceof ActiveEffect) {
item.toChat(this);
} else {
const wasUsed = await item.use(event);
if (wasUsed && item.type === 'weapon') {
@ -746,7 +753,11 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
const item = this.getItem(event);
if (!item) return;
item.sheet.render(true);
if (item.sheet) {
item.sheet.render(true);
} else {
await new DHActionConfig(item).render(true);
}
}
editItem(event) {

View file

@ -0,0 +1,65 @@
import DHBaseItemSheet from '../api/base-item.mjs';
export default class BeastformSheet extends DHBaseItemSheet {
/**@inheritdoc */
static DEFAULT_OPTIONS = {
classes: ['beastform'],
dragDrop: [{ dragSelector: null, dropSelector: '.drop-section' }],
actions: {
editFeature: this.editFeature,
removeFeature: this.removeFeature
}
};
/**@override */
static PARTS = {
header: { template: 'systems/daggerheart/templates/sheets/items/beastform/header.hbs' },
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
settings: { template: 'systems/daggerheart/templates/sheets/items/beastform/settings.hbs' },
features: {
template: 'systems/daggerheart/templates/sheets/global/tabs/tab-features.hbs',
scrollable: ['.features']
},
effects: {
template: 'systems/daggerheart/templates/sheets/global/tabs/tab-effects.hbs',
scrollable: ['.effects']
}
};
static TABS = {
primary: {
tabs: [{ id: 'settings' }, { id: 'features' }, { id: 'effects' }],
initial: 'settings',
labelPrefix: 'DAGGERHEART.Sheets.TABS'
}
};
/**@inheritdoc */
async _preparePartContext(partId, context) {
await super._preparePartContext(partId, context);
return context;
}
static editFeature(event) {
const target = event.target.closest('[data-action="editFeature"]');
const feature = this.document.system.features[target.dataset.index];
feature.sheet.render({ force: true });
}
static async removeFeature(_, target) {
const current = this.document.system.features.map(x => x.uuid);
await this.document.update({
'system.features': current.filter((_, index) => index !== Number(target.dataset.index))
});
}
async _onDrop(event) {
const data = TextEditor.getDragEventData(event);
const item = await fromUuid(data.uuid);
if (item.type === 'feature') {
const current = this.document.system.features.map(x => x.uuid);
await this.document.update({ 'system.features': [...current, item.uuid] });
}
}
}