Merge branch 'main' into feature/death-moves

This commit is contained in:
Chris Ryan 2025-12-03 20:31:44 +10:00
commit fda1581c51
31 changed files with 426 additions and 48 deletions

View file

@ -197,7 +197,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
this.config.actionType = this.reactionOverride
? CONFIG.DH.ITEM.actionTypes.reaction.id
: this.config.actionType === CONFIG.DH.ITEM.actionTypes.reaction.id
? null
? CONFIG.DH.ITEM.actionTypes.action.id
: this.config.actionType;
this.render();
}

View file

@ -21,7 +21,6 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
async _prepareContext(options) {
const context = await super._prepareContext(options);
context.partyOnCanvas =
this.actor.type === 'party' &&
this.actor.system.partyMembers.some(member => member.getActiveTokens().length > 0);
@ -31,6 +30,7 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
context.canToggleCombat = DHTokenHUD.#nonCombatTypes.includes(this.actor.type)
? false
: context.canToggleCombat;
context.systemStatusEffects = Object.keys(context.statusEffects).reduce((acc, key) => {
const effect = context.statusEffects[key];
if (effect.systemEffect) {
@ -193,16 +193,18 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
}
// Update the status of effects which are active for the token actor
const activeEffects = this.actor?.effects || [];
const activeEffects = this.actor?.getActiveEffects() || [];
for (const effect of activeEffects) {
for (const statusId of effect.statuses) {
const status = choices[statusId];
status.instances = 1 + (status.instances ?? 0);
status.locked = status.locked || effect.condition || status.instances > 1;
if (!status) continue;
if (status._id) {
if (status._id !== effect.id) continue;
}
status.isActive = true;
if (effect.getFlag('core', 'overlay')) status.isOverlay = true;
if (effect.getFlag?.('core', 'overlay')) status.isOverlay = true;
}
}

View file

@ -717,6 +717,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
};
const result = await this.document.diceRoll({
...config,
actionType: 'action',
headerTitle: `${game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll')}: ${this.actor.name}`,
title: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
ability: abilityLabel

View file

@ -271,7 +271,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
cancel = true;
}
} else {
await originActor.deleteEmbeddedDocuments('Item', [data.originId], { render: false });
await originActor.deleteEmbeddedDocuments('Item', [data.originId]);
const createData = dropDocument.toObject();
await this.document.createEmbeddedDocuments('Item', [createData]);
}

View file

@ -2,6 +2,7 @@ export { default as CountdownEdit } from './countdownEdit.mjs';
export { default as DhCountdowns } from './countdowns.mjs';
export { default as DhChatLog } from './chatLog.mjs';
export { default as DhCombatTracker } from './combatTracker.mjs';
export { default as DhEffectsDisplay } from './effectsDisplay.mjs';
export { default as DhFearTracker } from './fearTracker.mjs';
export { default as DhHotbar } from './hotbar.mjs';
export { ItemBrowser } from './itemBrowser.mjs';

View file

@ -14,7 +14,6 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
constructor(options = {}) {
super(options);
this.sidebarCollapsed = true;
this.setupHooks();
}
@ -98,11 +97,10 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
async _prepareContext(options) {
const context = await super._prepareContext(options);
context.isGM = game.user.isGM;
context.sidebarCollapsed = this.sidebarCollapsed;
context.iconOnly =
game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode) ===
CONFIG.DH.GENERAL.countdownAppMode.iconOnly;
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
context.countdowns = this.#getCountdowns().reduce((acc, { key, countdown, ownership }) => {
const playersWithAccess = game.users.reduce((acc, user) => {

View file

@ -0,0 +1,117 @@
import { RefreshType } from '../../systemRegistration/socket.mjs';
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
/**
* A UI element which displays the Active Effects on a selected token.
*
* @extends ApplicationV2
* @mixes HandlebarsApplication
*/
export default class DhEffectsDisplay extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(options = {}) {
super(options);
this.setupHooks();
}
/** @inheritDoc */
static DEFAULT_OPTIONS = {
id: 'effects-display',
tag: 'div',
classes: ['daggerheart', 'dh-style', 'effects-display'],
window: {
frame: false,
positioned: false,
resizable: false,
minimizable: false
},
actions: {}
};
/** @override */
static PARTS = {
resources: {
root: true,
template: 'systems/daggerheart/templates/ui/effects-display.hbs'
}
};
get element() {
return document.body.querySelector('.daggerheart.dh-style.effects-display');
}
get hidden() {
return this.element.classList.contains('hidden');
}
_attachPartListeners(partId, htmlElement, options) {
super._attachPartListeners(partId, htmlElement, options);
if (this.element) {
this.element.querySelectorAll('.effect-container a').forEach(element => {
element.addEventListener('contextmenu', this.removeEffect.bind(this));
});
}
}
/** @override */
async _prepareContext(options) {
const context = await super._prepareContext(options);
context.effects = DhEffectsDisplay.getTokenEffects();
return context;
}
static getTokenEffects = token => {
const actor = token
? token.actor
: canvas.tokens.controlled.length === 0
? !game.user.isGM
? game.user.character
: null
: canvas.tokens.controlled[0].actor;
return actor?.getActiveEffects() ?? [];
};
toggleHidden(token, focused) {
const effects = DhEffectsDisplay.getTokenEffects(focused ? token : null);
this.element.hidden = effects.length === 0;
Hooks.callAll(CONFIG.DH.HOOKS.effectDisplayToggle, this.element.hidden, token);
this.render();
}
async removeEffect(event) {
const element = event.target.closest('.effect-container');
const effects = DhEffectsDisplay.getTokenEffects();
const effect = effects.find(x => x.id === element.id);
await effect.delete();
this.render();
}
setupHooks() {
Hooks.on('controlToken', this.toggleHidden.bind(this));
Hooks.on(RefreshType.EffectsDisplay, this.toggleHidden.bind(this));
}
async close(options) {
/* Opt out of Foundry's standard behavior of closing all application windows marked as UI when Escape is pressed */
if (options.closeKey) return;
Hooks.off('controlToken', this.toggleHidden);
Hooks.off(RefreshType.EffectsDisplay, this.toggleHidden);
return super.close(options);
}
async _onRender(context, options) {
await super._onRender(context, options);
this.element.hidden = context.effects.length === 0;
if (options?.force) {
document.getElementById('ui-right-column-1')?.appendChild(this.element);
}
}
}