diff --git a/lang/fr.json b/lang/fr.json index ccf59d5..54a6829 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -103,7 +103,6 @@ }, "Roll": { "clickToRoll": "Cliquer pour lancer", - "moonPhase": "Phase de lune", "difficulty": "Difficulté", "modifier": "Modificateur", "nbDice": "Nombre de dés", @@ -112,29 +111,29 @@ "failure": "ÉCHEC", "criticalSuccess": "Succès critique !", "criticalFailure": "Échec critique !", - "moonBonus": "Bonus de lune", "title": "Jet de dés", "roll": "Lancer !", "rollTitle": "Lancer les dés", - "aspect": "Modificateur d'Aspect", + "aspect": "Aspect", "woundMalus": "Malus de blessures", "diceSum": "Somme des dés", "margin": "Marge", "above": "au-dessus du seuil", "below": "en dessous du seuil", - "destin": "Dépenser 1 Destin", - "destinBonus": "+2 dés", - "destinAvailable": "disponible(s)", - "destinNone": "Aucun Destin disponible", + "destin": "Utiliser le Destin", + "destinBonus": "3d8 au lieu de 2d8", + "destGaugeFull": "Jauge pleine — vider pour 3d8", + "destGaugeEmpty": "Jauge vide", "usedAspect": "Aspect utilisé", - "usedDestin": "Destin dépensé", + "usedDestin": "Destin utilisé (jauge vidée)", "criticalSuccessDesc": "Marge ≥ 5 — résultat exceptionnel !", "criticalFailureDesc": "Marge ≤ −5 — résultat désastreux !", "woundLevel": "Niveau de blessures", - "diceBreakdown": "Détail du jet", "threshold": "Seuil", - "nbDiceBase": "Dés de base", + "baseDice": "2d8 de base", "formula": "Formule", + "rollMoonDie": "Lancer le Dé de la Lune", + "moonDieResult": "Dé de la Lune", "visibility": "Visibilité", "visibilityPublic": "Public", "visibilityGM": "MJ uniquement", @@ -149,7 +148,15 @@ "lunevoutee": "Lune Voûtée", "derniercroissant": "Dernier Croissant", "dernierquartier": "Dernier Quartier", - "pleinelune": "Pleine Lune" + "pleinelune": "Pleine Lune", + "triomphe": "Triomphe", + "triompheFull": "Succès critique, regain d'1 utilisation d'Anomalie, ou perte d'1 Spleen", + "brio": "Brio", + "brioFull": "Info ou avantage significatif, gain de 2 Destin, ou +4 au prochain jet", + "contrecoup": "Contrecoup", + "contrecoupFull": "Complication négative significative, perte de 2 Destin, ou −4 au prochain jet", + "catastrophe": "Catastrophe", + "catastropheFull": "Échec catastrophique, perte d'1 utilisation d'Anomalie, ou gain d'1 Spleen" }, "Difficulty": { "unknown": "Aucun seuil", diff --git a/module/config/system.mjs b/module/config/system.mjs index 1479645..bf29cc2 100644 --- a/module/config/system.mjs +++ b/module/config/system.mjs @@ -111,17 +111,25 @@ export const DIFFICULTY_CHOICES = { extreme: { id: "extreme", label: "CELESTOPOL.Difficulty.extreme", value: 13 }, } -/** Phases de la lune (dé de lune). */ -export const MOON_DICE_PHASES = { - none: { id: "none", label: "CELESTOPOL.Moon.none", bonus: 0 }, - nouvellelune: { id: "nouvellelune", label: "CELESTOPOL.Moon.nouvellelune", bonus: 0 }, - premiercroissant: { id: "premiercroissant", label: "CELESTOPOL.Moon.premiercroissant", bonus: 1 }, - premierquartier: { id: "premierquartier", label: "CELESTOPOL.Moon.premierquartier", bonus: 1 }, - lunegibbeuse: { id: "lunegibbeuse", label: "CELESTOPOL.Moon.lunegibbeuse", bonus: 2 }, - lunevoutee: { id: "lunevoutee", label: "CELESTOPOL.Moon.lunevoutee", bonus: 2 }, - derniercroissant: { id: "derniercroissant", label: "CELESTOPOL.Moon.derniercroissant", bonus: 1 }, - dernierquartier: { id: "dernierquartier", label: "CELESTOPOL.Moon.dernierquartier", bonus: 1 }, - pleinelune: { id: "pleinelune", label: "CELESTOPOL.Moon.pleinelune", bonus: 3 }, +/** Phases de la lune (dé de lune d8). Index 1-8 = résultat du dé. */ +export const MOON_DIE_FACES = [ + null, // index 0 non utilisé + { phase: "nouvellelune", label: "CELESTOPOL.Moon.nouvellelune", result: "triomphe", symbol: "🌑" }, + { phase: "premiercroissant", label: "CELESTOPOL.Moon.premiercroissant", result: "triomphe", symbol: "🌒" }, + { phase: "premierquartier", label: "CELESTOPOL.Moon.premierquartier", result: "brio", symbol: "🌓" }, + { phase: "lunegibbeuse", label: "CELESTOPOL.Moon.lunegibbeuse", result: "brio", symbol: "🌔" }, + { phase: "lunevoutee", label: "CELESTOPOL.Moon.lunevoutee", result: "contrecoup", symbol: "🌕" }, + { phase: "dernierquartier", label: "CELESTOPOL.Moon.dernierquartier", result: "contrecoup", symbol: "🌖" }, + { phase: "derniercroissant", label: "CELESTOPOL.Moon.derniercroissant", result: "catastrophe", symbol: "🌗" }, + { phase: "pleinelune", label: "CELESTOPOL.Moon.pleinelune", result: "catastrophe", symbol: "🌘" }, +] + +/** Types de résultats narratifs du dé de Lune. */ +export const MOON_RESULT_TYPES = { + triomphe: { id: "triomphe", label: "CELESTOPOL.Moon.triomphe", desc: "CELESTOPOL.Moon.triompheFull", cssClass: "moon-triomphe" }, + brio: { id: "brio", label: "CELESTOPOL.Moon.brio", desc: "CELESTOPOL.Moon.brioFull", cssClass: "moon-brio" }, + contrecoup: { id: "contrecoup", label: "CELESTOPOL.Moon.contrecoup", desc: "CELESTOPOL.Moon.contrecoupFull", cssClass: "moon-contrecoup" }, + catastrophe: { id: "catastrophe", label: "CELESTOPOL.Moon.catastrophe", desc: "CELESTOPOL.Moon.catastropheFull", cssClass: "moon-catastrophe" }, } /** Types d'équipements. */ @@ -143,6 +151,7 @@ export const SYSTEM = { FACTIONS, WOUND_LEVELS, DIFFICULTY_CHOICES, - MOON_DICE_PHASES, + MOON_DIE_FACES, + MOON_RESULT_TYPES, EQUIPMENT_TYPES, } diff --git a/module/documents/roll.mjs b/module/documents/roll.mjs index 1fb0b83..f8a0428 100644 --- a/module/documents/roll.mjs +++ b/module/documents/roll.mjs @@ -1,25 +1,18 @@ import { SYSTEM } from "../config/system.mjs" -/** Symboles Unicode pour chaque phase de lune. */ -const MOON_SYMBOLS = { - none: "☽", - nouvellelune: "🌑", - premiercroissant: "🌒", - premierquartier: "🌓", - lunegibbeuse: "🌔", - lunevoutee: "🌕", - derniercroissant: "🌖", - dernierquartier: "🌗", - pleinelune: "🌕", +/** Construit la formule de jet à partir du nombre de dés et du modificateur total. */ +function buildFormula(nbDice, totalModifier) { + if (totalModifier > 0) return `${nbDice}d8 + ${totalModifier}` + if (totalModifier < 0) return `${nbDice}d8 - ${Math.abs(totalModifier)}` + return `${nbDice}d8` } /** * Système de dés de Célestopol 1922. * - * Le jet de base est : (valeur domaine + malus blessures)d6 + bonus lune + modificateurs - * comparé à un seuil de difficulté. - * - Succès critique : marge ≥ 5 - * - Échec critique : marge ≤ −5 + * Formule de base : 2d8 + Spécialisation + modificateurs (aspect, blessures, manual) + * Destin (jauge pleine à 8) : 3d8 + modificateurs, puis reset de la jauge à 0 + * Dé de la Lune (optionnel) : 1d8 séparé → résultat narratif (Triomphe/Brio/Contrecoup/Catastrophe) */ export class CelestopolRoll extends Roll { static CHAT_TEMPLATE = "systems/fvtt-celestopol/templates/chat-message.hbs" @@ -34,7 +27,6 @@ export class CelestopolRoll extends Roll { get actorImage() { return this.options.actorImage } get skillLabel() { return this.options.skillLabel } get difficulty() { return this.options.difficulty } - get moonBonus() { return this.options.moonBonus ?? 0 } /** * Ouvre le dialogue de configuration du jet via DialogV2 et exécute le jet. @@ -43,33 +35,24 @@ export class CelestopolRoll extends Roll { */ static async prompt(options = {}) { const woundMalus = options.woundMalus ?? 0 - const baseSkillVal = options.skillValue ?? 0 - const nbDiceBase = Math.max(1, baseSkillVal + woundMalus) + const skillValue = options.skillValue ?? 0 const woundLevelId = options.woundLevel ?? 0 + const destGaugeFull = options.destGaugeFull ?? false const woundLabel = woundLevelId > 0 ? game.i18n.localize(SYSTEM.WOUND_LEVELS[woundLevelId]?.label ?? "") : null - // Construire les phases lune avec symboles - const moonPhaseChoices = Object.fromEntries( - Object.entries(SYSTEM.MOON_DICE_PHASES).map(([key, val]) => [ - key, { ...val, symbol: MOON_SYMBOLS[key] ?? "☽" } - ]) - ) - const dialogContext = { - actorName: options.actorName, - statLabel: options.statLabel, - skillLabel: options.skillLabel, - skillValue: baseSkillVal, + actorName: options.actorName, + statLabel: options.statLabel, + skillLabel: options.skillLabel, + skillValue, woundMalus, woundLabel, - nbDiceBase, - difficultyChoices: SYSTEM.DIFFICULTY_CHOICES, - moonPhaseChoices, - defaultDifficulty: options.difficulty ?? "normal", - defaultMoonPhase: options.moonPhase ?? "none", - destActuel: options.destActuel ?? null, + difficultyChoices: SYSTEM.DIFFICULTY_CHOICES, + defaultDifficulty: options.difficulty ?? "normal", + destGaugeFull, + defaultRollMoonDie: options.rollMoonDie ?? false, } const content = await foundry.applications.handlebars.renderTemplate( @@ -79,9 +62,7 @@ export class CelestopolRoll extends Roll { const skillLocalized = game.i18n.localize(options.skillLabel ?? "") const statLocalized = options.statLabel ? game.i18n.localize(options.statLabel) : null - const title = statLocalized - ? `${statLocalized} › ${skillLocalized}` - : skillLocalized + const title = statLocalized ? `${statLocalized} › ${skillLocalized}` : skillLocalized const rollContext = await foundry.applications.api.DialogV2.wait({ window: { title }, @@ -108,34 +89,39 @@ export class CelestopolRoll extends Roll { const difficulty = rollContext.difficulty ?? "normal" const diffConfig = SYSTEM.DIFFICULTY_CHOICES[difficulty] ?? SYSTEM.DIFFICULTY_CHOICES.normal - const moonPhase = rollContext.moonPhase ?? "none" - const moonConfig = SYSTEM.MOON_DICE_PHASES[moonPhase] ?? SYSTEM.MOON_DICE_PHASES.none const modifier = parseInt(rollContext.modifier ?? 0) || 0 const aspectMod = parseInt(rollContext.aspectModifier ?? 0) || 0 - const useDestin = rollContext.useDestin === true || rollContext.useDestin === "true" - const destinDice = useDestin ? 2 : 0 - const skillValue = Math.max(0, baseSkillVal + woundMalus) - const nbDice = Math.max(1, skillValue) + destinDice - const moonBonus = moonConfig.bonus ?? 0 - const totalModifier = moonBonus + modifier + aspectMod + const useDestin = destGaugeFull && (rollContext.useDestin === true || rollContext.useDestin === "true") + const rollMoonDie = rollContext.rollMoonDie === true || rollContext.rollMoonDie === "true" + const nbDice = useDestin ? 3 : 2 + const totalModifier = skillValue + woundMalus + aspectMod + modifier + const formula = buildFormula(nbDice, totalModifier) - const formula = totalModifier !== 0 - ? `${nbDice}d6 + ${totalModifier}` - : `${nbDice}d6` + // Jet du dé de lune séparé (narratif) + let moonDieResult = null + let moonFace = null + let moonResultType = null + if (rollMoonDie) { + const moonRoll = await new Roll("1d8").evaluate() + moonDieResult = moonRoll.total + moonFace = SYSTEM.MOON_DIE_FACES[moonDieResult] ?? null + moonResultType = moonFace ? SYSTEM.MOON_RESULT_TYPES[moonFace.result] ?? null : null + } const rollData = { ...options, difficulty, difficultyValue: diffConfig.value, - moonPhase, - moonBonus, modifier, aspectMod, useDestin, - destinDice, nbDice, formula, - rollMode: rollContext.visibility ?? "publicroll", + rollMode: rollContext.visibility ?? "publicroll", + rollMoonDie, + moonDieResult, + moonFace, + moonResultType, } const roll = new this(formula, {}, rollData) @@ -143,22 +129,27 @@ export class CelestopolRoll extends Roll { roll.computeResult() await roll.toMessage({}, { rollMode: rollData.rollMode }) - // Déduire automatiquement 1 point de Destin si utilisé + // Destin utilisé → vider la jauge (reset à 0) const actor = game.actors.get(options.actorId) - if (useDestin && actor && (options.destActuel ?? 1) > 0) { - const currentLvl = actor.system.destin?.lvl ?? 0 - const newLvl = Math.min(8, currentLvl + 1) + if (useDestin && actor) { await actor.update({ - "system.destin.lvl": newLvl, - [`system.destin.d${newLvl}.checked`]: true, + "system.destin.lvl": 0, + "system.destin.d1.checked": false, + "system.destin.d2.checked": false, + "system.destin.d3.checked": false, + "system.destin.d4.checked": false, + "system.destin.d5.checked": false, + "system.destin.d6.checked": false, + "system.destin.d7.checked": false, + "system.destin.d8.checked": false, }) } // Mémoriser les préférences sur l'acteur if (actor) { await actor.update({ - "system.prefs.moonPhase": moonPhase, - "system.prefs.difficulty": difficulty, + "system.prefs.rollMoonDie": rollMoonDie, + "system.prefs.difficulty": difficulty, }) } @@ -166,7 +157,7 @@ export class CelestopolRoll extends Roll { } /** - * Détermine succès/échec et critiques selon la marge (total − seuil). + * Détermine succès/échec selon la marge (total − seuil). * - Marge ≥ 5 → succès critique * - Marge ≥ 0 → succès * - Marge ≤ −5 → échec critique @@ -194,22 +185,24 @@ export class CelestopolRoll extends Roll { } async _getChatCardData(isPrivate) { - const statLabel = this.options.statLabel - const skillLabel = this.options.skillLabel - const resultType = this.resultType - const diceResults = this.dice[0]?.results?.map(r => r.result) ?? [] - const diceSum = diceResults.reduce((a, b) => a + b, 0) - const threshold = SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.value ?? 0 - const margin = this.options.margin - const moonPhase = this.options.moonPhase ?? "none" - const moonSymbol = MOON_SYMBOLS[moonPhase] ?? "☽" - const woundMalus = this.options.woundMalus ?? 0 - const woundLevelId = this.options.woundLevel ?? 0 - const woundLabel = woundLevelId > 0 + const statLabel = this.options.statLabel + const skillLabel = this.options.skillLabel + const resultType = this.resultType + const diceResults = this.dice[0]?.results?.map(r => r.result) ?? [] + const diceSum = diceResults.reduce((a, b) => a + b, 0) + const threshold = SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.value ?? 0 + const margin = this.options.margin + const woundMalus = this.options.woundMalus ?? 0 + const woundLevelId = this.options.woundLevel ?? 0 + const woundLabel = woundLevelId > 0 ? game.i18n.localize(SYSTEM.WOUND_LEVELS[woundLevelId]?.label ?? "") : null - // Classe CSS principale du résultat + // Dé de lune + const moonDieResult = this.options.moonDieResult ?? null + const moonFace = this.options.moonFace ?? null + const moonResultType = this.options.moonResultType ?? null + const resultClassMap = { "critical-success": "critical-success", "success": "success", @@ -219,41 +212,44 @@ export class CelestopolRoll extends Roll { } return { - cssClass: [SYSTEM.id, "dice-roll"].join(" "), - actorId: this.actorId, - actorName: this.actorName, - actorImg: this.actorImage, - statLabel: statLabel ? game.i18n.localize(statLabel) : "", - skillLabel: skillLabel ? game.i18n.localize(skillLabel) : "", - formula: this.formula, - total: this.total, + cssClass: [SYSTEM.id, "dice-roll"].join(" "), + actorId: this.actorId, + actorName: this.actorName, + actorImg: this.actorImage, + statLabel: statLabel ? game.i18n.localize(statLabel) : "", + skillLabel: skillLabel ? game.i18n.localize(skillLabel) : "", + formula: this.formula, + total: this.total, diceSum, diceResults, resultType, - resultClass: resultClassMap[resultType] ?? "", - isSuccess: this.isSuccess, - isFailure: this.isFailure, - isCriticalSuccess: this.isCriticalSuccess, - isCriticalFailure: this.isCriticalFailure, - difficulty: this.options.difficulty, - difficultyLabel: game.i18n.localize(SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.label ?? ""), - difficultyValue: threshold, + resultClass: resultClassMap[resultType] ?? "", + isSuccess: this.isSuccess, + isFailure: this.isFailure, + isCriticalSuccess: this.isCriticalSuccess, + isCriticalFailure: this.isCriticalFailure, + difficulty: this.options.difficulty, + difficultyLabel: game.i18n.localize(SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.label ?? ""), + difficultyValue: threshold, margin, - marginAbs: margin !== null ? Math.abs(margin) : null, - marginAbove: margin !== null && margin >= 0, - moonPhase, - moonPhaseLabel: game.i18n.localize(SYSTEM.MOON_DICE_PHASES[moonPhase]?.label ?? ""), - moonSymbol, - moonBonus: this.moonBonus, - modifier: this.options.modifier, - aspectMod: this.options.aspectMod ?? 0, - useDestin: this.options.useDestin ?? false, - destinDice: this.options.destinDice ?? 0, - nbDice: this.options.nbDice ?? diceResults.length, + marginAbs: margin !== null ? Math.abs(margin) : null, + marginAbove: margin !== null && margin >= 0, + modifier: this.options.modifier, + aspectMod: this.options.aspectMod ?? 0, + useDestin: this.options.useDestin ?? false, + nbDice: this.options.nbDice ?? diceResults.length, woundMalus, woundLabel, + // Dé de lune + hasMoonDie: moonDieResult !== null, + moonDieResult, + moonFaceSymbol: moonFace?.symbol ?? "", + moonFaceLabel: moonFace ? game.i18n.localize(moonFace.label) : "", + moonResultClass: moonResultType?.cssClass ?? "", + moonResultLabel: moonResultType ? game.i18n.localize(moonResultType.label) : "", + moonResultDesc: moonResultType ? game.i18n.localize(moonResultType.desc) : "", isPrivate, - tooltip: isPrivate ? "" : await this.getTooltip(), + tooltip: isPrivate ? "" : await this.getTooltip(), } } diff --git a/module/models/character.mjs b/module/models/character.mjs index 017a368..5e527af 100644 --- a/module/models/character.mjs +++ b/module/models/character.mjs @@ -127,8 +127,8 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel // Préférences de jet (mémorisé entre sessions) schema.prefs = new fields.SchemaField({ - moonPhase: new fields.StringField({ required: true, nullable: false, initial: "none" }), - difficulty: new fields.StringField({ required: true, nullable: false, initial: "normal" }), + rollMoonDie: new fields.BooleanField({ required: true, initial: false }), + difficulty: new fields.StringField({ required: true, nullable: false, initial: "normal" }), }) // Description & notes @@ -177,19 +177,19 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel if (!skill) return null return CelestopolRoll.prompt({ - actorId: this.parent.id, - actorName: this.parent.name, - actorImage: this.parent.img, + actorId: this.parent.id, + actorName: this.parent.name, + actorImage: this.parent.img, statId, skillId, - statLabel: SYSTEM.STATS[statId]?.label, - skillLabel: skill.label, - skillValue: skill.value, - woundMalus: this.getWoundMalus(), - woundLevel: this.blessures.lvl, - moonPhase: this.prefs.moonPhase, - difficulty: this.prefs.difficulty, - destActuel: Math.max(0, 8 - (this.destin.lvl ?? 0)), + statLabel: SYSTEM.STATS[statId]?.label, + skillLabel: skill.label, + skillValue: skill.value, + woundMalus: this.getWoundMalus(), + woundLevel: this.blessures.lvl, + difficulty: this.prefs.difficulty, + rollMoonDie: this.prefs.rollMoonDie ?? false, + destGaugeFull: this.destin.lvl >= 8, }) } } diff --git a/module/models/npc.mjs b/module/models/npc.mjs index cab25d9..fa9f0bc 100644 --- a/module/models/npc.mjs +++ b/module/models/npc.mjs @@ -52,8 +52,8 @@ export default class CelestopolNPC extends foundry.abstract.TypeDataModel { }) schema.prefs = new fields.SchemaField({ - moonPhase: new fields.StringField({ required: true, nullable: false, initial: "none" }), - difficulty: new fields.StringField({ required: true, nullable: false, initial: "normal" }), + rollMoonDie: new fields.BooleanField({ required: true, initial: false }), + difficulty: new fields.StringField({ required: true, nullable: false, initial: "normal" }), }) schema.description = new fields.HTMLField({ required: true, textSearch: true }) @@ -84,16 +84,16 @@ export default class CelestopolNPC extends foundry.abstract.TypeDataModel { if (!skill) return null return CelestopolRoll.prompt({ - actorId: this.parent.id, - actorName: this.parent.name, - actorImage: this.parent.img, + actorId: this.parent.id, + actorName: this.parent.name, + actorImage: this.parent.img, statId, skillId, - skillLabel: skill.label, - skillValue: skill.value, - woundMalus: this.getWoundMalus(), - moonPhase: this.prefs.moonPhase, - difficulty: this.prefs.difficulty, + skillLabel: skill.label, + skillValue: skill.value, + woundMalus: this.getWoundMalus(), + difficulty: this.prefs.difficulty, + rollMoonDie: this.prefs.rollMoonDie ?? false, }) } } diff --git a/styles/roll.less b/styles/roll.less index 371d298..db32694 100644 --- a/styles/roll.less +++ b/styles/roll.less @@ -82,52 +82,53 @@ } } - // ── Phases de lune : grille 3 colonnes ── - .moon-section { - display: flex; - flex-direction: column; - gap: 5px; - margin-bottom: 12px; + // ── Ligne Dé de la Lune ── + .form-moon-row { + border: 1px solid rgba(122,92,32,0.35); + border-radius: 4px; + background: rgba(255,255,255,0.3); + padding: 7px 10px; - .moon-section-label { - font-size: 0.72em; - text-transform: uppercase; - letter-spacing: 0.07em; - color: var(--cel-orange, #e07b00); - border-bottom: 1px solid rgba(122,92,32,0.3); - padding-bottom: 3px; - } + .moon-toggle { + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; - .moon-phases { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 4px; - - .moon-option { - display: flex; - flex-direction: column; - align-items: center; + input[type="checkbox"] { + width: 16px; + height: 16px; + flex-shrink: 0; + appearance: none; + -webkit-appearance: none; + border: 2px solid var(--cel-border, #7a5c20); + border-radius: 2px; + background: white; cursor: pointer; - padding: 5px 4px; - border-radius: 4px; - border: 1px solid rgba(122,92,32,0.25); - transition: all 0.15s; - background: rgba(255,255,255,0.4); + position: relative; - &:hover { - background: rgba(196,154,26,0.12); - border-color: var(--cel-border, #7a5c20); + &:checked { + background: var(--cel-orange, #e07b00); + border-color: var(--cel-orange, #e07b00); + &::after { + content: "✦"; + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.65em; + color: white; + } } + } - &.active { - background: linear-gradient(160deg, #f5ecd4, #e8d8a0); - border: 2px solid var(--cel-orange, #e07b00); - box-shadow: inset 0 0 6px rgba(196,154,26,0.3); - } + .moon-icon { font-size: 1.2em; flex-shrink: 0; } - .moon-symbol { font-size: 1.5em; line-height: 1; } - .moon-name { font-size: 0.58em; text-align: center; margin-top: 2px; color: #444; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; } - .moon-bonus { font-size: 0.68em; color: var(--cel-orange, #e07b00); font-weight: bold; margin-top: 1px; } + .moon-text { + font-family: var(--cel-font-title, "CopaseticNF", serif); + font-size: 0.88em; + color: var(--cel-green, #0c4c0c); } } } @@ -361,14 +362,7 @@ .wound-info { font-size: 0.7em; color: #f0a0a0; } } - .moon-badge { - display: flex; - flex-direction: column; - align-items: center; - gap: 1px; - .moon-sym { font-size: 1.35em; line-height: 1; } - .moon-bon { font-size: 0.72em; color: var(--cel-orange-light, #ddb84a); font-weight: bold; } - } + .moon-badge { display: none; } } // ── Zone dés ── @@ -432,7 +426,6 @@ font-weight: bold; line-height: 1; } - .fl-moon { color: #666; } .fl-mod { color: #444; font-weight: bold; } .fl-asp { color: var(--cel-orange, #e07b00); font-weight: bold; } .fl-sep { font-weight: bold; color: var(--cel-border, #7a5c20); margin: 0 2px; } @@ -492,6 +485,69 @@ .used-destin { font-weight: bold; } } + // ── Résultat dé de lune ── + .moon-die-result { + display: flex; + align-items: center; + gap: 10px; + padding: 6px 12px; + border-top: 1px solid rgba(122,92,32,0.2); + font-family: var(--cel-font-body, serif); + + .moon-die-face { + font-size: 1.8em; + line-height: 1; + flex-shrink: 0; + } + + .moon-die-info { + flex: 1; + display: flex; + flex-direction: column; + gap: 1px; + } + + .moon-die-phase { + font-size: 0.72em; + opacity: 0.75; + text-transform: uppercase; + letter-spacing: 0.05em; + } + + .moon-die-type { + font-family: var(--cel-font-title, "CopaseticNF", serif); + font-size: 1em; + font-weight: bold; + letter-spacing: 0.06em; + text-transform: uppercase; + } + + .moon-die-desc { + font-size: 0.72em; + font-style: italic; + opacity: 0.85; + line-height: 1.3; + } + + // Couleurs par type de résultat + &.moon-triomphe { + background: linear-gradient(90deg, rgba(12,76,12,0.12), rgba(12,76,12,0.05)); + .moon-die-type { color: var(--cel-green, #0c4c0c); } + } + &.moon-brio { + background: linear-gradient(90deg, rgba(196,154,26,0.12), rgba(196,154,26,0.04)); + .moon-die-type { color: var(--cel-border, #7a5c20); } + } + &.moon-contrecoup { + background: linear-gradient(90deg, rgba(120,80,0,0.1), rgba(120,80,0,0.03)); + .moon-die-type { color: #7a4a00; } + } + &.moon-catastrophe { + background: linear-gradient(90deg, rgba(107,30,40,0.15), rgba(107,30,40,0.05)); + .moon-die-type { color: #6b1e28; } + } + } + // ── Bandeau résultat ── .roll-result-banner { display: flex; diff --git a/templates/chat-message.hbs b/templates/chat-message.hbs index 04716af..6fb5638 100644 --- a/templates/chat-message.hbs +++ b/templates/chat-message.hbs @@ -13,29 +13,21 @@ {{#if woundLabel}}⚠ {{woundLabel}}{{/if}} -
- {{moonSymbol}} - {{#if moonBonus}}+{{moonBonus}}{{/if}} -
{{!-- Zone dés --}}
{{#each diceResults as |die|}} - {{die}} + {{die}} {{/each}}
{{!-- Formule détaillée --}}
{{localize "CELESTOPOL.Roll.formula"}} : - {{nbDice}}d6 + {{nbDice}}d8 = {{diceSum}} - {{#if moonBonus}} - + - {{moonSymbol}}{{moonBonus}} - {{/if}} {{#if modifier}} {{#if (gt modifier 0)}}+{{else}}−{{/if}} {{abs modifier}} @@ -69,6 +61,18 @@
{{/if}} + {{!-- Résultat du Dé de la Lune (narratif) --}} + {{#if hasMoonDie}} +
+ {{moonFaceSymbol}} +
+ {{moonFaceLabel}} + {{moonResultLabel}} + {{moonResultDesc}} +
+
+ {{/if}} + {{!-- Bandeau résultat --}}
{{#if isCriticalSuccess}} diff --git a/templates/roll-dialog.hbs b/templates/roll-dialog.hbs index 19bceec..8e3c9a5 100644 --- a/templates/roll-dialog.hbs +++ b/templates/roll-dialog.hbs @@ -1,6 +1,6 @@
- {{!-- En-tête : acteur + domaine + dés de base --}} + {{!-- En-tête : acteur + domaine + formule de base --}}
{{actorName}}
@@ -9,15 +9,12 @@
+ 2d8 + + {{skillValue}} - {{localize "CELESTOPOL.Roll.nbDiceBase"}} {{#if woundMalus}} − {{abs woundMalus}} - {{localize "CELESTOPOL.Roll.woundMalus"}} {{/if}} - = - {{nbDiceBase}} - d6
{{#if woundLabel}}
⚠ {{woundLabel}}
@@ -25,21 +22,6 @@
- {{!-- Phases de lune : grille 3 × 3 --}} -
- -
- {{#each moonPhaseChoices as |phase key|}} - - {{/each}} -
-
-
{{!-- Difficulté --}} @@ -66,19 +48,28 @@
- {{!-- Destin --}} -
+ {{!-- Dé de la Lune --}} +
+ +
+ + {{!-- Destin (3d8) — seulement si jauge pleine --}} +
@@ -98,48 +89,34 @@ {{!-- Prévisualisation formule --}}
{{localize "CELESTOPOL.Roll.formula"}} - {{nbDiceBase}}d6 + 2d8
+