[Feature] DualityDice DiceSoNice Animations (#1722)

* .

* Fixed translation

* Remove fieldset

* DiceSoNice Animation Overrides (#1726)

* .

* .

* Fixed hope/fear animation input

* Visual tweaks to general tab

* Move general tab to top

* Fixed localizaiton

---------

Co-authored-by: Carlos Fernandez <cfern1990@gmail.com>
This commit is contained in:
WBHarry 2026-03-13 00:15:52 +01:00 committed by GitHub
parent 6c7937a9ff
commit 8172e8baa7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 492 additions and 150 deletions

View file

@ -21,7 +21,7 @@ const bonusField = label =>
dice: new fields.ArrayField(new fields.StringField(), { label: `${game.i18n.localize(label)} Dice` })
});
/**
/**
* Field used for actor resources. It is a resource that validates dynamically based on the config.
* Because "max" may be defined during runtime, we don't attempt to clamp the maximum value.
*/
@ -78,7 +78,7 @@ class ResourcesField extends fields.TypedObjectField {
const resource = resources[key];
value.label = resource.label;
value.isReversed = resources[key].reverse;
value.max = typeof resource.max === 'number' ? value.max ?? resource.max : null;
value.max = typeof resource.max === 'number' ? (value.max ?? resource.max) : null;
}
return data;
}

View file

@ -1,6 +1,16 @@
export default class DhAppearance extends foundry.abstract.DataModel {
static LOCALIZATION_PREFIXES = ['DAGGERHEART.SETTINGS.Appearance'];
static sfxSchema = () =>
new foundry.data.fields.SchemaField({
class: new foundry.data.fields.StringField({
nullable: true,
initial: null,
blank: true,
choices: CONFIG.DH.GENERAL.diceSoNiceSFXClasses
})
});
static defineSchema() {
const { StringField, ColorField, BooleanField, SchemaField } = foundry.data.fields;
@ -15,7 +25,10 @@ export default class DhAppearance extends foundry.abstract.DataModel {
colorset: new StringField({ initial: 'inspired', required: true, blank: false }),
material: new StringField({ initial: 'metal', required: true, blank: false }),
system: new StringField({ initial: 'standard', required: true, blank: false }),
font: new StringField({ initial: 'auto', required: true, blank: false })
font: new StringField({ initial: 'auto', required: true, blank: false }),
sfx: new SchemaField({
higher: DhAppearance.sfxSchema()
})
});
return {
@ -30,7 +43,10 @@ export default class DhAppearance extends foundry.abstract.DataModel {
hope: diceStyle({ fg: '#ffffff', bg: '#ffe760', outline: '#000000', edge: '#ffffff' }),
fear: diceStyle({ fg: '#000000', bg: '#0032b1', outline: '#ffffff', edge: '#000000' }),
advantage: diceStyle({ fg: '#ffffff', bg: '#008000', outline: '#000000', edge: '#ffffff' }),
disadvantage: diceStyle({ fg: '#000000', bg: '#b30000', outline: '#ffffff', edge: '#000000' })
disadvantage: diceStyle({ fg: '#000000', bg: '#b30000', outline: '#ffffff', edge: '#000000' }),
sfx: new SchemaField({
critical: DhAppearance.sfxSchema()
})
}),
extendCharacterDescriptions: new BooleanField(),
extendAdversaryDescriptions: new BooleanField(),
@ -65,4 +81,48 @@ export default class DhAppearance extends foundry.abstract.DataModel {
showGenericStatusEffects: new BooleanField({ initial: true })
};
}
get diceSoNiceData() {
const globalOverrides = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides);
const getSFX = (baseClientData, overrideKey) => {
if (!globalOverrides.diceSoNice.sfx.overrideEnabled) return baseClientData;
const overrideData = globalOverrides.diceSoNice.sfx[overrideKey];
const clientData = foundry.utils.deepClone(baseClientData);
return Object.keys(clientData).reduce((acc, key) => {
const data = clientData[key];
acc[key] = Object.keys(data).reduce((acc, dataKey) => {
const value = data[dataKey];
acc[dataKey] = value ? value : overrideData[key][dataKey];
return acc;
}, {});
return acc;
}, {});
};
return {
...this.diceSoNice,
sfx: getSFX(this.diceSoNice.sfx, 'global'),
hope: {
...this.diceSoNice.hope,
sfx: getSFX(this.diceSoNice.hope.sfx, 'hope')
},
fear: {
...this.diceSoNice.fear,
sfx: getSFX(this.diceSoNice.fear.sfx, 'fear')
}
};
}
/** Invoked by the setting when data changes */
handleChange() {
if (this.displayFear) {
if (ui.resources) {
if (this.displayFear === 'hide') ui.resources.close({ allowed: true });
else ui.resources.render({ force: true });
}
}
const globalOverrides = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides);
globalOverrides.diceSoNiceSFXUpdate(this);
}
}

View file

@ -0,0 +1,55 @@
import DhAppearance from './Appearance.mjs';
/**
* A setting to handle cases where we want to allow the GM to set a global default for client settings.
*/
export default class DhGlobalOverrides extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
diceSoNice: new fields.SchemaField({
sfx: new fields.SchemaField({
overrideEnabled: new fields.BooleanField(),
global: new fields.SchemaField({
critical: DhAppearance.sfxSchema()
}),
hope: new fields.SchemaField({
higher: DhAppearance.sfxSchema()
}),
fear: new fields.SchemaField({
higher: DhAppearance.sfxSchema()
})
})
})
};
}
async diceSoNiceSFXUpdate(appearanceSettings, enabled) {
if (!game.user.isGM) return;
const newEnabled = enabled !== undefined ? enabled : this.diceSoNice.sfx.overrideEnabled;
if (newEnabled) {
const newOverrides = foundry.utils.mergeObject(this.toObject(), {
diceSoNice: {
sfx: {
overrideEnabled: true,
global: appearanceSettings.diceSoNice.sfx,
hope: appearanceSettings.diceSoNice.hope.sfx,
fear: appearanceSettings.diceSoNice.fear.sfx
}
}
});
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides, newOverrides);
} else {
const newOverrides = {
...this.toObject(),
diceSoNice: {
sfx: {
overrideEnabled: false
}
}
};
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.GlobalOverrides, newOverrides);
}
}
}

View file

@ -220,7 +220,7 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
return result;
}, {}),
...config.custom,
...config.base,
...config.base
});
}
}

View file

@ -3,3 +3,4 @@ export { default as DhAutomation } from './Automation.mjs';
export { default as DhHomebrew } from './Homebrew.mjs';
export { default as DhMetagaming } from './Metagaming.mjs';
export { default as DhVariantRules } from './VariantRules.mjs';
export { default as DhGlobalOverrides } from './GlobalOverrides.mjs';