mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-07-21 18:09:54 +02:00
Compare commits
No commits in common. "8d68166e4c643c26bc82882fd50773b4caf19e18" and "effab8db0cc1815ca552a3eafb3247c785c7e037" have entirely different histories.
8d68166e4c
...
effab8db0c
8 changed files with 37 additions and 119 deletions
13
daggerheart.d.ts
vendored
13
daggerheart.d.ts
vendored
|
|
@ -11,9 +11,6 @@ import * as documents from './module/documents/_module.mjs';
|
|||
import { macros } from './module/_module.mjs';
|
||||
import * as dice from './module/dice/_module.mjs';
|
||||
import * as fields from './module/data/fields/_module.mjs';
|
||||
import { gameSettings } from './module/config/settingsConfig.mjs';
|
||||
import DhCountdowns from './module/data/countdowns.mjs';
|
||||
import DhAutomation from './module/data/settings/Automation.mjs';
|
||||
|
||||
|
||||
// Foundry's use of `Object.assign(globalThis) means many globally available objects are not read as such
|
||||
|
|
@ -106,13 +103,3 @@ declare module '@client/packages/system.mjs' {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@client/helpers/client-settings.mjs' {
|
||||
// Add explicit typed overrides for auto complete. These require /** @type {"string"} on the vars themselves to work */
|
||||
export default interface ClientSettings {
|
||||
get(namespace: 'daggerheart', key: typeof gameSettings.Automation): DhAutomation;
|
||||
get(namespace: 'daggerheart', key: typeof gameSettings.Homebrew): DhHomebrew;
|
||||
get(namespace: 'daggerheart', key: typeof gameSettings.Countdowns): DhCountdowns;
|
||||
get(namespace: 'daggerheart', key: string): unknown;
|
||||
}
|
||||
}
|
||||
|
|
@ -153,6 +153,7 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio
|
|||
action: socketEvent.Refresh,
|
||||
data: { refreshType: RefreshType.Countdown }
|
||||
});
|
||||
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
|
||||
}
|
||||
|
||||
static #addCountdown() {
|
||||
|
|
|
|||
|
|
@ -12,11 +12,14 @@ const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
|||
|
||||
export default class DhCountdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
previousCountdownData = null;
|
||||
changedCountdownsForAnimation = new Set();
|
||||
|
||||
constructor(options = {}) {
|
||||
super(options);
|
||||
|
||||
this.previousCountdownData =
|
||||
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns).countdowns;
|
||||
this.setupHooks();
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
|
|
@ -77,15 +80,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
return frame;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
async _onFirstRender(context, options) {
|
||||
await super._onFirstRender(context, options);
|
||||
this._createContextMenu(this._getCountdownContextOptions, '.countdown-container[data-countdown]', {
|
||||
parentClassHooks: false, fixed: true
|
||||
});
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
async _onRender(context, options) {
|
||||
await super._onRender(context, options);
|
||||
|
||||
|
|
@ -100,7 +95,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
|
||||
/* Handle animations to draw attention to countdown values changing */
|
||||
const typesToAnimate = new Set();
|
||||
for (const countdownKey of options.animate ?? []) {
|
||||
for (const countdownKey of this.changedCountdownsForAnimation) {
|
||||
const shimmerAnimation = [
|
||||
{ backgroundPositionX: '98%' },
|
||||
{ backgroundPositionX: '0%' }
|
||||
|
|
@ -132,6 +127,8 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
const element = this.element.querySelector(`.header-type-toggles .header-type[data-type="${type}"]`);
|
||||
element?.animate(pulseAnimation, pulseTiming);
|
||||
}
|
||||
|
||||
this.changedCountdownsForAnimation.clear();
|
||||
}
|
||||
|
||||
/** Returns countdown data filtered by ownership */
|
||||
|
|
@ -140,15 +137,17 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
const values = Object.entries(setting.countdowns).map(([key, countdown]) => ({
|
||||
key,
|
||||
countdown,
|
||||
ownership: countdown.getUserLevel(game.user)
|
||||
ownership: DhCountdowns.#getPlayerOwnership(game.user, setting, countdown)
|
||||
}));
|
||||
return values.filter(v => v.ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE);
|
||||
}
|
||||
|
||||
_getCountdownData() {
|
||||
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||
|
||||
return this.#getCountdowns().reduce((acc, { key, countdown, ownership }) => {
|
||||
const playersWithAccess = game.users.reduce((acc, user) => {
|
||||
const ownership = countdown.getUserLevel(user);
|
||||
const ownership = DhCountdowns.#getPlayerOwnership(user, setting, countdown);
|
||||
if (!user.isGM && ownership && ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
|
||||
acc.push(user);
|
||||
}
|
||||
|
|
@ -214,6 +213,19 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
return context;
|
||||
}
|
||||
|
||||
static #getPlayerOwnership(user, setting, countdown) {
|
||||
if (user.isGM) return CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER;
|
||||
|
||||
const playerOwnership = countdown.ownership[user.id];
|
||||
return playerOwnership === undefined || playerOwnership === CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT
|
||||
? setting.defaultOwnership
|
||||
: playerOwnership;
|
||||
}
|
||||
|
||||
cooldownRefresh = ({ refreshType }) => {
|
||||
if (refreshType === RefreshType.Countdown) this.render();
|
||||
};
|
||||
|
||||
static canPerformEdit() {
|
||||
if (game.user.isGM) return true;
|
||||
|
||||
|
|
@ -311,12 +323,18 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
action: socketEvent.Refresh,
|
||||
data: { refreshType: RefreshType.Countdown }
|
||||
});
|
||||
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
|
||||
}
|
||||
|
||||
setupHooks() {
|
||||
Hooks.on(socketEvent.Refresh, this.cooldownRefresh.bind());
|
||||
}
|
||||
|
||||
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(socketEvent.Refresh, this.cooldownRefresh);
|
||||
return super.close(options);
|
||||
}
|
||||
|
||||
|
|
@ -359,30 +377,4 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
refreshType: RefreshType.Countdown
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {import('@client/applications/ux/context-menu.mjs').ContextMenuEntry[]}
|
||||
*/
|
||||
_getCountdownContextOptions() {
|
||||
/** @param {HTMLElement} element */
|
||||
const getCountdownFromElement = element => {
|
||||
const id = element.closest('[data-countdown]').dataset.countdown;
|
||||
if (!id) return null;
|
||||
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||
return setting.countdowns[id ?? ''];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
label: 'CONTROLS.CommonDelete',
|
||||
icon: 'fa-solid fa-trash',
|
||||
visible: element => {
|
||||
return getCountdownFromElement(element)?.isOwner;
|
||||
},
|
||||
onClick: (_, target) => {
|
||||
getCountdownFromElement(target)?.delete();
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,8 @@ export const menu = {
|
|||
};
|
||||
|
||||
export const gameSettings = {
|
||||
/** @type {'Automation'} */
|
||||
Automation: 'Automation',
|
||||
Metagaming: 'Metagaming',
|
||||
/** @type {'Homebrew'} */
|
||||
Homebrew: 'Homebrew',
|
||||
appearance: 'Appearance',
|
||||
GlobalOverrides: 'GlobalOverrides',
|
||||
|
|
@ -39,7 +37,6 @@ export const gameSettings = {
|
|||
Fear: 'ResourcesFear'
|
||||
},
|
||||
LevelTiers: 'LevelTiers',
|
||||
/** @type {'Countdowns'} */
|
||||
Countdowns: 'Countdowns',
|
||||
LastMigrationVersion: 'LastMigrationVersion',
|
||||
SpotlightRequestQueue: 'SpotlightRequestQueue',
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import * as HOOKS from './hooksConfig.mjs';
|
|||
import * as TRIGGER from './triggerConfig.mjs';
|
||||
import * as ITEMBROWSER from './itemBrowserConfig.mjs';
|
||||
|
||||
/** @type {"daggerheart"} */
|
||||
export const SYSTEM_ID = 'daggerheart';
|
||||
|
||||
export const SYSTEM = {
|
||||
|
|
|
|||
7
module/data/_types.d.ts
vendored
7
module/data/_types.d.ts
vendored
|
|
@ -1,7 +0,0 @@
|
|||
import { DhCountdown } from './countdowns.mjs'
|
||||
|
||||
declare module './countdowns.mjs' {
|
||||
export default interface DhCountdowns {
|
||||
countdowns: Record<string, DhCountdown>;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import { RefreshType, socketEvent } from '../systemRegistration/socket.mjs';
|
||||
import FormulaField from './fields/formulaField.mjs';
|
||||
|
||||
export default class DhCountdowns extends foundry.abstract.DataModel {
|
||||
|
|
@ -15,36 +14,19 @@ export default class DhCountdowns extends foundry.abstract.DataModel {
|
|||
};
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
_initialize(options) {
|
||||
super._initialize(options);
|
||||
for (const [id, countdown] of Object.entries(this.countdowns)) {
|
||||
countdown.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
async handleChange() {
|
||||
handleChange() {
|
||||
const previousCountdowns = foundry.ui.countdowns.previousCountdownData;
|
||||
const changedCountdowns = Object.entries(this.countdowns).reduce((acc, [key, countdown]) => {
|
||||
const previous = previousCountdowns[key];
|
||||
const currentChanged = !previous || (previous.progress.current !== countdown.progress.current);
|
||||
if (currentChanged && previous?.progress.start === countdown.progress.start) {
|
||||
const previousCountdown = previousCountdowns[key];
|
||||
if (!previousCountdown || (previousCountdown.progress.current !== countdown.progress.current)) {
|
||||
acc.push(key);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
// Re-render countdowns applications. When the change is due to an actual update, resync the editor
|
||||
if (!foundry.utils.equals(previousCountdowns, this.countdowns)) {
|
||||
await foundry.ui.countdowns.render({ animate: changedCountdowns });
|
||||
for (const instance of game.system.api.applications.ui.CountdownEdit.instances()) {
|
||||
instance.data = this;
|
||||
await instance.render();
|
||||
}
|
||||
}
|
||||
|
||||
// Inform modules of updates
|
||||
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
|
||||
for (const countdownKey of changedCountdowns)
|
||||
foundry.ui.countdowns.changedCountdownsForAnimation.add(countdownKey);
|
||||
}
|
||||
|
||||
static migrateData(source) {
|
||||
|
|
@ -178,14 +160,6 @@ export class DhCountdown extends foundry.abstract.DataModel {
|
|||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* A boolean indicator for whether the current game User has ownership rights for this countdown
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get isOwner() {
|
||||
return this.getUserLevel(game.user) === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
static migrateData(source) {
|
||||
if (source.progress.max) {
|
||||
|
|
@ -196,29 +170,4 @@ export class DhCountdown extends foundry.abstract.DataModel {
|
|||
|
||||
return super.migrateData(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the explicit permission level that a User has over this Document, a value in CONST.DOCUMENT_OWNERSHIP_LEVELS.
|
||||
* Compendium content ignores the ownership field in favor of User role-based ownership. Otherwise, Documents use
|
||||
* granular per-User ownership definitions and Embedded Documents defer to their parent ownership.
|
||||
*
|
||||
* @param {BaseUser} [user=game.user] The User being tested
|
||||
* @returns {DocumentOwnershipNumber} A numeric permission level from {@link CONST.DOCUMENT_OWNERSHIP_LEVELS}
|
||||
*/
|
||||
getUserLevel(user) {
|
||||
if (user.isGM) return CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER;
|
||||
|
||||
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||
const playerOwnership = this.ownership[user.id];
|
||||
return playerOwnership === undefined || playerOwnership === CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT
|
||||
? setting.defaultOwnership
|
||||
: playerOwnership;
|
||||
}
|
||||
|
||||
async delete() {
|
||||
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||
const data = foundry.utils.deepClone(setting._source);
|
||||
delete data.countdowns[this.id];
|
||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"version": "2.5.4",
|
||||
"compatibility": {
|
||||
"minimum": "14.364",
|
||||
"verified": "14.365",
|
||||
"verified": "14.364",
|
||||
"maximum": "14"
|
||||
},
|
||||
"url": "https://github.com/Foundryborne/daggerheart",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue