daggerheart/module/data/countdowns.mjs
WBHarry 9c58f7058e
[Fix] V13 Migration Fixes (#2044)
* Fixed so that damageParts without an applyTo field is assumed to be hitPoints

* Added the applyTo field to the basic attack for Adversaries and Companions

* Tentative blindfix to issues of entities being null. Can't replicate it

* Added some safety for missing things if someone was on a REALLY old system version and then updated all the way

* Moved v13 countdown migration over to a migrateData

* .
2026-06-29 14:22:12 +02:00

173 lines
6.5 KiB
JavaScript

import FormulaField from './fields/formulaField.mjs';
export default class DhCountdowns extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
countdowns: new fields.TypedObjectField(new fields.EmbeddedDataField(DhCountdown)),
defaultOwnership: new fields.NumberField({
required: true,
choices: CONFIG.DH.GENERAL.basicOwnershiplevels,
initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER
})
};
}
handleChange() {
const previousCountdowns = foundry.ui.countdowns.previousCountdownData;
const changedCountdowns = Object.entries(this.countdowns).reduce((acc, [key, countdown]) => {
const previousCountdown = previousCountdowns[key];
if (!previousCountdown || (previousCountdown.progress.current !== countdown.progress.current)) {
acc.push(key);
}
return acc;
}, []);
for (const countdownKey of changedCountdowns)
foundry.ui.countdowns.changedCountdownsForAnimation.add(countdownKey);
}
static migrateData(source) {
const migrateOldCountdowns = (data, type) => {
for (const key of Object.keys(data.countdowns)) {
const countdown = data.countdowns[key];
source.countdowns[key] = {
...countdown,
type: type,
ownership: Object.keys(countdown.ownership.players).reduce((acc, key) => {
acc[key] =
countdown.ownership.players[key].type === 1 ? 2 : countdown.ownership.players[key].type;
return acc;
}, {}),
progress: {
...countdown.progress,
type: countdown.progress.type.value
}
};
}
source[type] = null;
};
if (source.narrative) {
migrateOldCountdowns(source.narrative, 'narrative');
}
if (source.encounter) {
migrateOldCountdowns(source.encounter, 'encounter');
}
return super.migrateData(source);
}
}
export class DhCountdown extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
type: new fields.StringField({
required: true,
choices: CONFIG.DH.GENERAL.countdownTypes,
initial: CONFIG.DH.GENERAL.countdownTypes.encounter.id,
label: 'DAGGERHEART.GENERAL.type'
}),
name: new fields.StringField({
required: true,
label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.name.label'
}),
img: new fields.FilePathField({
categories: ['IMAGE'],
base64: false,
initial: 'icons/magic/time/hourglass-yellow-green.webp'
}),
ownership: new fields.TypedObjectField(
new fields.NumberField({
required: true,
choices: CONFIG.DH.GENERAL.simpleOwnershiplevels,
initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT
})
),
progress: new fields.SchemaField({
current: new fields.NumberField({
required: true,
integer: true,
initial: 1,
label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.current.label'
}),
start: new fields.NumberField({
required: true,
integer: true,
initial: 1,
label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.start.label',
deterministic: false
}),
startFormula: new FormulaField({
label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.startFormula.label',
deterministic: false
}),
looping: new fields.StringField({
required: true,
choices: CONFIG.DH.GENERAL.countdownLoopingTypes,
initial: CONFIG.DH.GENERAL.countdownLoopingTypes.noLooping.id,
label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.looping.label'
}),
type: new fields.StringField({
required: true,
choices: CONFIG.DH.GENERAL.countdownProgressionTypes,
initial: CONFIG.DH.GENERAL.countdownProgressionTypes.custom.id,
label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.type.label'
})
})
};
}
static defaultCountdown(type, playerHidden) {
const ownership = playerHidden
? game.users.reduce((acc, user) => {
if (!user.isGM) {
acc[user.id] = CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE;
}
return acc;
}, {})
: undefined;
return {
type: type ?? CONFIG.DH.GENERAL.countdownTypes.encounter.id,
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Countdown.newCountdown'),
img: 'icons/magic/time/hourglass-yellow-green.webp',
ownership: ownership,
progress: {
current: 1,
start: 1
}
};
}
get playerOwnership() {
return Array.from(game.users).reduce((acc, user) => {
acc[user.id] = {
value: user.isGM
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
: this.ownership.players[user.id] && this.ownership.players[user.id].type !== -1
? this.ownership.players[user.id].type
: this.ownership.default,
isGM: user.isGM
};
return acc;
}, {});
}
/** @inheritDoc */
static migrateData(source) {
if (source.progress.max) {
source.progress.start = Number(source.progress.max);
source.progress.max = null;
source.progress.startFormula = null;
}
return super.migrateData(source);
}
}