diff --git a/lang/en.json b/lang/en.json index 14292e5b..182c7419 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1561,7 +1561,11 @@ "foreground": "Foreground", "background": "Background", "outline": "Outline", - "edge": "Edge" + "edge": "Edge", + "texture": "Texture", + "colorset": "Theme", + "material": "Material", + "system": "Dice Preset" } }, "variantRules": { diff --git a/module/applications/settings/appearanceSettings.mjs b/module/applications/settings/appearanceSettings.mjs index a03bef9a..b4a6be04 100644 --- a/module/applications/settings/appearanceSettings.mjs +++ b/module/applications/settings/appearanceSettings.mjs @@ -59,8 +59,20 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App const context = await super._prepareContext(_options); context.settingFields = this.settings; - context.diceSoNiceTextures = game.dice3d?.exports?.TEXTURELIST ?? {}; - context.diceSoNiceColorsets = game.dice3d?.exports?.COLORSETS ?? {}; + context.showDiceSoNice = game.modules.get('dice-so-nice')?.active; + if (game.dice3d) { + context.diceSoNiceTextures = game.dice3d.exports.TEXTURELIST; + context.diceSoNiceColorsets = game.dice3d.exports.COLORSETS; + context.diceSoNiceMaterials = Object.keys(game.dice3d.DiceFactory.material_options).map(key => ({ + key: key, + name: `DICESONICE.Material${key.capitalize()}` + })); + context.diceSoNiceSystems = []; + for (const [key, system] of game.dice3d.DiceFactory.systems.entries()) { + context.diceSoNiceSystems.push({ key, name: system.name }); + } + } + context.diceTab = { key: this.tabGroups.diceSoNice, source: this.settings._source.diceSoNice[this.tabGroups.diceSoNice], diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index a03a0e2a..2b20e742 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -369,42 +369,28 @@ export const diceSetNumbers = { flat: 'Flat' }; -export const getDiceSoNicePresets = () => { +export const getDiceSoNicePresets = async (hopeFaces, fearFaces, advantageFaces = 'd6', disadvantageFaces = 'd6') => { const { diceSoNice } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance); + const getPreset = async (type, faces) => { + const system = game.dice3d.DiceFactory.systems.get(type.system).dice.get(faces); + if (!system.modelLoaded) { + await system.loadModel(game.dice3d.DiceFactory.loaderGLTF); + } + + return { + modelFile: system.modelFile, + appearance: { + ...system.appearance, + ...type + } + }; + }; return { - hope: { - ...diceSoNice.hope, - colorset: 'inspired', - texture: 'bloodmoon', - material: 'metal', - font: 'Arial Black', - system: 'standard' - }, - fear: { - ...diceSoNice.fear, - colorset: 'bloodmoon', - texture: 'bloodmoon', - material: 'metal', - font: 'Arial Black', - system: 'standard' - }, - advantage: { - ...diceSoNice.advantage, - colorset: 'bloodmoon', - texture: 'bloodmoon', - material: 'metal', - font: 'Arial Black', - system: 'standard' - }, - disadvantage: { - ...diceSoNice.disadvantage, - colorset: 'bloodmoon', - texture: 'bloodmoon', - material: 'metal', - font: 'Arial Black', - system: 'standard' - } + hope: await getPreset(diceSoNice.hope, hopeFaces), + fear: await getPreset(diceSoNice.fear, fearFaces), + advantage: await getPreset(diceSoNice.advantage, advantageFaces), + disadvantage: await getPreset(diceSoNice.disadvantage, disadvantageFaces) }; }; diff --git a/module/data/settings/Appearance.mjs b/module/data/settings/Appearance.mjs index ccdf3c0b..c59cd436 100644 --- a/module/data/settings/Appearance.mjs +++ b/module/data/settings/Appearance.mjs @@ -21,25 +21,41 @@ export default class DhAppearance extends foundry.abstract.DataModel { foreground: new fields.ColorField({ required: true, initial: '#ffffff' }), background: new fields.ColorField({ required: true, initial: '#ffe760' }), outline: new fields.ColorField({ required: true, initial: '#000000' }), - edge: new fields.ColorField({ required: true, initial: '#ffffff' }) + edge: new fields.ColorField({ required: true, initial: '#ffffff' }), + texture: new fields.StringField({ initial: 'astralsea' }), + colorset: new fields.StringField({ initial: 'inspired' }), + material: new fields.StringField({ initial: 'metal' }), + system: new fields.StringField({ initial: 'standard' }) }), fear: new fields.SchemaField({ foreground: new fields.ColorField({ required: true, initial: '#000000' }), background: new fields.ColorField({ required: true, initial: '#0032b1' }), outline: new fields.ColorField({ required: true, initial: '#ffffff' }), - edge: new fields.ColorField({ required: true, initial: '#000000' }) + edge: new fields.ColorField({ required: true, initial: '#000000' }), + texture: new fields.StringField({ initial: 'astralsea' }), + colorset: new fields.StringField({ initial: 'inspired' }), + material: new fields.StringField({ initial: 'metal' }), + system: new fields.StringField({ initial: 'standard' }) }), advantage: new fields.SchemaField({ foreground: new fields.ColorField({ required: true, initial: '#ffffff' }), background: new fields.ColorField({ required: true, initial: '#008000' }), outline: new fields.ColorField({ required: true, initial: '#000000' }), - edge: new fields.ColorField({ required: true, initial: '#ffffff' }) + edge: new fields.ColorField({ required: true, initial: '#ffffff' }), + texture: new fields.StringField({ initial: 'astralsea' }), + colorset: new fields.StringField({ initial: 'inspired' }), + material: new fields.StringField({ initial: 'metal' }), + system: new fields.StringField({ initial: 'standard' }) }), disadvantage: new fields.SchemaField({ foreground: new fields.ColorField({ required: true, initial: '#000000' }), background: new fields.ColorField({ required: true, initial: '#b30000' }), outline: new fields.ColorField({ required: true, initial: '#ffffff' }), - edge: new fields.ColorField({ required: true, initial: '#000000' }) + edge: new fields.ColorField({ required: true, initial: '#000000' }), + texture: new fields.StringField({ initial: 'astralsea' }), + colorset: new fields.StringField({ initial: 'inspired' }), + material: new fields.StringField({ initial: 'metal' }), + system: new fields.StringField({ initial: 'standard' }) }) }), showGenericStatusEffects: new fields.BooleanField({ diff --git a/module/dice/d20Roll.mjs b/module/dice/d20Roll.mjs index dcf0143a..bee7717c 100644 --- a/module/dice/d20Roll.mjs +++ b/module/dice/d20Roll.mjs @@ -1,5 +1,4 @@ import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; -import { getDiceSoNicePresets } from '../config/generalConfig.mjs'; import DHRoll from './dhRoll.mjs'; export default class D20Roll extends DHRoll { @@ -141,8 +140,8 @@ export default class D20Roll extends DHRoll { return modifiers; } - static postEvaluate(roll, config = {}) { - const data = super.postEvaluate(roll, config); + static async postEvaluate(roll, config = {}) { + const data = await super.postEvaluate(roll, config); if (config.targets?.length) { config.targets.forEach(target => { const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion; @@ -185,7 +184,7 @@ export default class D20Roll extends DHRoll { static async reroll(rollString, _target, message) { let parsedRoll = game.system.api.dice.D20Roll.fromData(rollString); parsedRoll = await parsedRoll.reroll(); - const newRoll = game.system.api.dice.D20Roll.postEvaluate(parsedRoll, { + const newRoll = await game.system.api.dice.D20Roll.postEvaluate(parsedRoll, { targets: message.system.targets, roll: { advantage: message.system.roll.advantage?.type, diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs index 49aa3551..6c99dae4 100644 --- a/module/dice/damageRoll.mjs +++ b/module/dice/damageRoll.mjs @@ -16,14 +16,19 @@ export default class DamageRoll extends DHRoll { for (const roll of config.roll) await roll.roll.evaluate(); } roll._evaluated = true; - const parts = config.roll.map(r => this.postEvaluate(r)); + const parts = []; + for (let r of config.roll) { + const part = this.postEvaluate(r); + parts.push(part); + } + config.roll = this.unifyDamageRoll(parts); } - static postEvaluate(roll, config = {}) { + static async postEvaluate(roll, config = {}) { return { ...roll, - ...super.postEvaluate(roll.roll, config), + ...(await super.postEvaluate(roll.roll, config)), damageTypes: [...(roll.damageTypes ?? [])], roll: roll.roll, type: config.type, diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index 4bc1a5bd..3236710b 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -47,7 +47,7 @@ export default class DHRoll extends Roll { static async buildEvaluate(roll, config = {}, message = {}) { if (config.evaluate !== false) await roll.evaluate(); - config.roll = this.postEvaluate(roll, config); + config.roll = await this.postEvaluate(roll, config); } static async buildPost(roll, config, message) { @@ -67,7 +67,7 @@ export default class DHRoll extends Roll { } else config.message = await this.toMessage(roll, config); } - static postEvaluate(roll, config = {}) { + static async postEvaluate(roll, config = {}) { return { total: roll.total, formula: roll.formula, diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 1c414a63..c229999e 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -166,8 +166,8 @@ export default class DualityRoll extends D20Roll { return modifiers; } - static postEvaluate(roll, config = {}) { - const data = super.postEvaluate(roll, config); + static async postEvaluate(roll, config = {}) { + const data = await super.postEvaluate(roll, config); data.hope = { dice: roll.dHope.denomination, @@ -198,7 +198,13 @@ export default class DualityRoll extends D20Roll { if (roll._rallyIndex && roll.data?.parent) roll.data.parent.deleteEmbeddedDocuments('ActiveEffect', [roll._rallyIndex]); - setDiceSoNiceForDualityRoll(roll, data.advantage.type); + await setDiceSoNiceForDualityRoll( + roll, + data.advantage.type, + data.hope.dice, + data.fear.dice, + data.advantage.dice + ); return data; } @@ -220,10 +226,10 @@ export default class DualityRoll extends D20Roll { options: { appearance: {} } }; - const diceSoNicePresets = getDiceSoNicePresets(); + const diceSoNicePresets = await getDiceSoNicePresets(); const type = target.dataset.type; if (diceSoNicePresets[type]) { - diceSoNiceRoll.dice[0].options = { appearance: diceSoNicePresets[type] }; + diceSoNiceRoll.dice[0].options = diceSoNicePresets[type]; } await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true); @@ -231,7 +237,7 @@ export default class DualityRoll extends D20Roll { await parsedRoll.evaluate(); - const newRoll = game.system.api.dice.DualityRoll.postEvaluate(parsedRoll, { + const newRoll = await game.system.api.dice.DualityRoll.postEvaluate(parsedRoll, { targets: message.system.targets, roll: { advantage: message.system.roll.advantage?.type, diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index f9349da9..749591ef 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -52,14 +52,13 @@ export const getCommandTarget = () => { return target; }; -export const setDiceSoNiceForDualityRoll = (rollResult, advantageState) => { - const diceSoNicePresets = getDiceSoNicePresets(); - rollResult.dice[0].options = { appearance: diceSoNicePresets.hope }; - rollResult.dice[1].options = { appearance: diceSoNicePresets.fear }; //diceSoNicePresets.fear; +export const setDiceSoNiceForDualityRoll = async (rollResult, advantageState, hopeFaces, fearFaces, advantageFaces) => { + const diceSoNicePresets = await getDiceSoNicePresets(hopeFaces, fearFaces, advantageFaces, advantageFaces); + rollResult.dice[0].options = diceSoNicePresets.hope; + rollResult.dice[1].options = diceSoNicePresets.fear; if (rollResult.dice[2] && advantageState) { - rollResult.dice[2].options = { - appearance: advantageState === 1 ? diceSoNicePresets.advantage : diceSoNicePresets.disadvantage - }; + rollResult.dice[2].options = + advantageState === 1 ? diceSoNicePresets.advantage : diceSoNicePresets.disadvantage; } }; diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index dda82362..8a3677ae 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -443,6 +443,10 @@ } .field-section { + display: flex; + flex-direction: column; + gap: 10px; + .split-section { display: grid; grid-template-columns: 1fr 1fr; @@ -455,9 +459,18 @@ grid-template-columns: 1fr 1fr; gap: 10px; + &.full-width { + grid-template-columns: 1fr 1fr 1fr 1fr; + + select { + grid-column: span 3; + } + } + label { align-self: center; text-align: center; + white-space: nowrap; } } } diff --git a/templates/settings/appearance-settings.hbs b/templates/settings/appearance-settings.hbs index 59f6345e..4a8c7e26 100644 --- a/templates/settings/appearance-settings.hbs +++ b/templates/settings/appearance-settings.hbs @@ -7,47 +7,74 @@ {{formGroup settingFields.schema.fields.dualityColorScheme value=settingFields._source.dualityColorScheme localize=true}} -