Fix formule de dés : 2d8 de base (règles Célestopol)
Correction majeure de la mécanique de jet selon les règles : - Formule : 2d8 + Spécialisation + modificateurs (blessures/aspect/manual) (vs. ancienne formule erronée : Nd6 pool variable) - Dé de la Lune : 1d8 narratif optionnel (résultat 1-8 → Triomphe / Brio / Contrecoup / Catastrophe) — pas un bonus numérique - Destin : disponible uniquement jauge pleine (lvl=8), donne 3d8, vide la jauge entière après usage - system.mjs : MOON_DIE_FACES (tableau 1-8) + MOON_RESULT_TYPES - roll.mjs : logique complète réécrite (2d8, lune séparée, destin reset) - character/npc.mjs : prefs.rollMoonDie + destGaugeFull - roll-dialog.hbs : sans grille lune, checkbox dé lune, destin conditionnel - chat-message.hbs : résultat dé lune narratif (phase + type + desc), dés .d8, suppression moonSymbol/moonBonus header - roll.less : .form-moon-row, .moon-die-result avec couleurs Triomphe/ Brio/Contrecoup/Catastrophe - lang/fr.json : Moon.triomphe/brio/contrecoup/catastrophe + Full descs, Roll.rollMoonDie/destGaugeFull/destGaugeEmpty/baseDice Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
29
lang/fr.json
29
lang/fr.json
@@ -103,7 +103,6 @@
|
|||||||
},
|
},
|
||||||
"Roll": {
|
"Roll": {
|
||||||
"clickToRoll": "Cliquer pour lancer",
|
"clickToRoll": "Cliquer pour lancer",
|
||||||
"moonPhase": "Phase de lune",
|
|
||||||
"difficulty": "Difficulté",
|
"difficulty": "Difficulté",
|
||||||
"modifier": "Modificateur",
|
"modifier": "Modificateur",
|
||||||
"nbDice": "Nombre de dés",
|
"nbDice": "Nombre de dés",
|
||||||
@@ -112,29 +111,29 @@
|
|||||||
"failure": "ÉCHEC",
|
"failure": "ÉCHEC",
|
||||||
"criticalSuccess": "Succès critique !",
|
"criticalSuccess": "Succès critique !",
|
||||||
"criticalFailure": "Échec critique !",
|
"criticalFailure": "Échec critique !",
|
||||||
"moonBonus": "Bonus de lune",
|
|
||||||
"title": "Jet de dés",
|
"title": "Jet de dés",
|
||||||
"roll": "Lancer !",
|
"roll": "Lancer !",
|
||||||
"rollTitle": "Lancer les dés",
|
"rollTitle": "Lancer les dés",
|
||||||
"aspect": "Modificateur d'Aspect",
|
"aspect": "Aspect",
|
||||||
"woundMalus": "Malus de blessures",
|
"woundMalus": "Malus de blessures",
|
||||||
"diceSum": "Somme des dés",
|
"diceSum": "Somme des dés",
|
||||||
"margin": "Marge",
|
"margin": "Marge",
|
||||||
"above": "au-dessus du seuil",
|
"above": "au-dessus du seuil",
|
||||||
"below": "en dessous du seuil",
|
"below": "en dessous du seuil",
|
||||||
"destin": "Dépenser 1 Destin",
|
"destin": "Utiliser le Destin",
|
||||||
"destinBonus": "+2 dés",
|
"destinBonus": "3d8 au lieu de 2d8",
|
||||||
"destinAvailable": "disponible(s)",
|
"destGaugeFull": "Jauge pleine — vider pour 3d8",
|
||||||
"destinNone": "Aucun Destin disponible",
|
"destGaugeEmpty": "Jauge vide",
|
||||||
"usedAspect": "Aspect utilisé",
|
"usedAspect": "Aspect utilisé",
|
||||||
"usedDestin": "Destin dépensé",
|
"usedDestin": "Destin utilisé (jauge vidée)",
|
||||||
"criticalSuccessDesc": "Marge ≥ 5 — résultat exceptionnel !",
|
"criticalSuccessDesc": "Marge ≥ 5 — résultat exceptionnel !",
|
||||||
"criticalFailureDesc": "Marge ≤ −5 — résultat désastreux !",
|
"criticalFailureDesc": "Marge ≤ −5 — résultat désastreux !",
|
||||||
"woundLevel": "Niveau de blessures",
|
"woundLevel": "Niveau de blessures",
|
||||||
"diceBreakdown": "Détail du jet",
|
|
||||||
"threshold": "Seuil",
|
"threshold": "Seuil",
|
||||||
"nbDiceBase": "Dés de base",
|
"baseDice": "2d8 de base",
|
||||||
"formula": "Formule",
|
"formula": "Formule",
|
||||||
|
"rollMoonDie": "Lancer le Dé de la Lune",
|
||||||
|
"moonDieResult": "Dé de la Lune",
|
||||||
"visibility": "Visibilité",
|
"visibility": "Visibilité",
|
||||||
"visibilityPublic": "Public",
|
"visibilityPublic": "Public",
|
||||||
"visibilityGM": "MJ uniquement",
|
"visibilityGM": "MJ uniquement",
|
||||||
@@ -149,7 +148,15 @@
|
|||||||
"lunevoutee": "Lune Voûtée",
|
"lunevoutee": "Lune Voûtée",
|
||||||
"derniercroissant": "Dernier Croissant",
|
"derniercroissant": "Dernier Croissant",
|
||||||
"dernierquartier": "Dernier Quartier",
|
"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": {
|
"Difficulty": {
|
||||||
"unknown": "Aucun seuil",
|
"unknown": "Aucun seuil",
|
||||||
|
|||||||
@@ -111,17 +111,25 @@ export const DIFFICULTY_CHOICES = {
|
|||||||
extreme: { id: "extreme", label: "CELESTOPOL.Difficulty.extreme", value: 13 },
|
extreme: { id: "extreme", label: "CELESTOPOL.Difficulty.extreme", value: 13 },
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Phases de la lune (dé de lune). */
|
/** Phases de la lune (dé de lune d8). Index 1-8 = résultat du dé. */
|
||||||
export const MOON_DICE_PHASES = {
|
export const MOON_DIE_FACES = [
|
||||||
none: { id: "none", label: "CELESTOPOL.Moon.none", bonus: 0 },
|
null, // index 0 non utilisé
|
||||||
nouvellelune: { id: "nouvellelune", label: "CELESTOPOL.Moon.nouvellelune", bonus: 0 },
|
{ phase: "nouvellelune", label: "CELESTOPOL.Moon.nouvellelune", result: "triomphe", symbol: "🌑" },
|
||||||
premiercroissant: { id: "premiercroissant", label: "CELESTOPOL.Moon.premiercroissant", bonus: 1 },
|
{ phase: "premiercroissant", label: "CELESTOPOL.Moon.premiercroissant", result: "triomphe", symbol: "🌒" },
|
||||||
premierquartier: { id: "premierquartier", label: "CELESTOPOL.Moon.premierquartier", bonus: 1 },
|
{ phase: "premierquartier", label: "CELESTOPOL.Moon.premierquartier", result: "brio", symbol: "🌓" },
|
||||||
lunegibbeuse: { id: "lunegibbeuse", label: "CELESTOPOL.Moon.lunegibbeuse", bonus: 2 },
|
{ phase: "lunegibbeuse", label: "CELESTOPOL.Moon.lunegibbeuse", result: "brio", symbol: "🌔" },
|
||||||
lunevoutee: { id: "lunevoutee", label: "CELESTOPOL.Moon.lunevoutee", bonus: 2 },
|
{ phase: "lunevoutee", label: "CELESTOPOL.Moon.lunevoutee", result: "contrecoup", symbol: "🌕" },
|
||||||
derniercroissant: { id: "derniercroissant", label: "CELESTOPOL.Moon.derniercroissant", bonus: 1 },
|
{ phase: "dernierquartier", label: "CELESTOPOL.Moon.dernierquartier", result: "contrecoup", symbol: "🌖" },
|
||||||
dernierquartier: { id: "dernierquartier", label: "CELESTOPOL.Moon.dernierquartier", bonus: 1 },
|
{ phase: "derniercroissant", label: "CELESTOPOL.Moon.derniercroissant", result: "catastrophe", symbol: "🌗" },
|
||||||
pleinelune: { id: "pleinelune", label: "CELESTOPOL.Moon.pleinelune", bonus: 3 },
|
{ 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. */
|
/** Types d'équipements. */
|
||||||
@@ -143,6 +151,7 @@ export const SYSTEM = {
|
|||||||
FACTIONS,
|
FACTIONS,
|
||||||
WOUND_LEVELS,
|
WOUND_LEVELS,
|
||||||
DIFFICULTY_CHOICES,
|
DIFFICULTY_CHOICES,
|
||||||
MOON_DICE_PHASES,
|
MOON_DIE_FACES,
|
||||||
|
MOON_RESULT_TYPES,
|
||||||
EQUIPMENT_TYPES,
|
EQUIPMENT_TYPES,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,18 @@
|
|||||||
import { SYSTEM } from "../config/system.mjs"
|
import { SYSTEM } from "../config/system.mjs"
|
||||||
|
|
||||||
/** Symboles Unicode pour chaque phase de lune. */
|
/** Construit la formule de jet à partir du nombre de dés et du modificateur total. */
|
||||||
const MOON_SYMBOLS = {
|
function buildFormula(nbDice, totalModifier) {
|
||||||
none: "☽",
|
if (totalModifier > 0) return `${nbDice}d8 + ${totalModifier}`
|
||||||
nouvellelune: "🌑",
|
if (totalModifier < 0) return `${nbDice}d8 - ${Math.abs(totalModifier)}`
|
||||||
premiercroissant: "🌒",
|
return `${nbDice}d8`
|
||||||
premierquartier: "🌓",
|
|
||||||
lunegibbeuse: "🌔",
|
|
||||||
lunevoutee: "🌕",
|
|
||||||
derniercroissant: "🌖",
|
|
||||||
dernierquartier: "🌗",
|
|
||||||
pleinelune: "🌕",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Système de dés de Célestopol 1922.
|
* Système de dés de Célestopol 1922.
|
||||||
*
|
*
|
||||||
* Le jet de base est : (valeur domaine + malus blessures)d6 + bonus lune + modificateurs
|
* Formule de base : 2d8 + Spécialisation + modificateurs (aspect, blessures, manual)
|
||||||
* comparé à un seuil de difficulté.
|
* Destin (jauge pleine à 8) : 3d8 + modificateurs, puis reset de la jauge à 0
|
||||||
* - Succès critique : marge ≥ 5
|
* Dé de la Lune (optionnel) : 1d8 séparé → résultat narratif (Triomphe/Brio/Contrecoup/Catastrophe)
|
||||||
* - Échec critique : marge ≤ −5
|
|
||||||
*/
|
*/
|
||||||
export class CelestopolRoll extends Roll {
|
export class CelestopolRoll extends Roll {
|
||||||
static CHAT_TEMPLATE = "systems/fvtt-celestopol/templates/chat-message.hbs"
|
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 actorImage() { return this.options.actorImage }
|
||||||
get skillLabel() { return this.options.skillLabel }
|
get skillLabel() { return this.options.skillLabel }
|
||||||
get difficulty() { return this.options.difficulty }
|
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.
|
* 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 = {}) {
|
static async prompt(options = {}) {
|
||||||
const woundMalus = options.woundMalus ?? 0
|
const woundMalus = options.woundMalus ?? 0
|
||||||
const baseSkillVal = options.skillValue ?? 0
|
const skillValue = options.skillValue ?? 0
|
||||||
const nbDiceBase = Math.max(1, baseSkillVal + woundMalus)
|
|
||||||
const woundLevelId = options.woundLevel ?? 0
|
const woundLevelId = options.woundLevel ?? 0
|
||||||
|
const destGaugeFull = options.destGaugeFull ?? false
|
||||||
const woundLabel = woundLevelId > 0
|
const woundLabel = woundLevelId > 0
|
||||||
? game.i18n.localize(SYSTEM.WOUND_LEVELS[woundLevelId]?.label ?? "")
|
? game.i18n.localize(SYSTEM.WOUND_LEVELS[woundLevelId]?.label ?? "")
|
||||||
: null
|
: 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 = {
|
const dialogContext = {
|
||||||
actorName: options.actorName,
|
actorName: options.actorName,
|
||||||
statLabel: options.statLabel,
|
statLabel: options.statLabel,
|
||||||
skillLabel: options.skillLabel,
|
skillLabel: options.skillLabel,
|
||||||
skillValue: baseSkillVal,
|
skillValue,
|
||||||
woundMalus,
|
woundMalus,
|
||||||
woundLabel,
|
woundLabel,
|
||||||
nbDiceBase,
|
difficultyChoices: SYSTEM.DIFFICULTY_CHOICES,
|
||||||
difficultyChoices: SYSTEM.DIFFICULTY_CHOICES,
|
defaultDifficulty: options.difficulty ?? "normal",
|
||||||
moonPhaseChoices,
|
destGaugeFull,
|
||||||
defaultDifficulty: options.difficulty ?? "normal",
|
defaultRollMoonDie: options.rollMoonDie ?? false,
|
||||||
defaultMoonPhase: options.moonPhase ?? "none",
|
|
||||||
destActuel: options.destActuel ?? null,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = await foundry.applications.handlebars.renderTemplate(
|
const content = await foundry.applications.handlebars.renderTemplate(
|
||||||
@@ -79,9 +62,7 @@ export class CelestopolRoll extends Roll {
|
|||||||
|
|
||||||
const skillLocalized = game.i18n.localize(options.skillLabel ?? "")
|
const skillLocalized = game.i18n.localize(options.skillLabel ?? "")
|
||||||
const statLocalized = options.statLabel ? game.i18n.localize(options.statLabel) : null
|
const statLocalized = options.statLabel ? game.i18n.localize(options.statLabel) : null
|
||||||
const title = statLocalized
|
const title = statLocalized ? `${statLocalized} › ${skillLocalized}` : skillLocalized
|
||||||
? `${statLocalized} › ${skillLocalized}`
|
|
||||||
: skillLocalized
|
|
||||||
|
|
||||||
const rollContext = await foundry.applications.api.DialogV2.wait({
|
const rollContext = await foundry.applications.api.DialogV2.wait({
|
||||||
window: { title },
|
window: { title },
|
||||||
@@ -108,34 +89,39 @@ export class CelestopolRoll extends Roll {
|
|||||||
|
|
||||||
const difficulty = rollContext.difficulty ?? "normal"
|
const difficulty = rollContext.difficulty ?? "normal"
|
||||||
const diffConfig = SYSTEM.DIFFICULTY_CHOICES[difficulty] ?? SYSTEM.DIFFICULTY_CHOICES.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 modifier = parseInt(rollContext.modifier ?? 0) || 0
|
||||||
const aspectMod = parseInt(rollContext.aspectModifier ?? 0) || 0
|
const aspectMod = parseInt(rollContext.aspectModifier ?? 0) || 0
|
||||||
const useDestin = rollContext.useDestin === true || rollContext.useDestin === "true"
|
const useDestin = destGaugeFull && (rollContext.useDestin === true || rollContext.useDestin === "true")
|
||||||
const destinDice = useDestin ? 2 : 0
|
const rollMoonDie = rollContext.rollMoonDie === true || rollContext.rollMoonDie === "true"
|
||||||
const skillValue = Math.max(0, baseSkillVal + woundMalus)
|
const nbDice = useDestin ? 3 : 2
|
||||||
const nbDice = Math.max(1, skillValue) + destinDice
|
const totalModifier = skillValue + woundMalus + aspectMod + modifier
|
||||||
const moonBonus = moonConfig.bonus ?? 0
|
const formula = buildFormula(nbDice, totalModifier)
|
||||||
const totalModifier = moonBonus + modifier + aspectMod
|
|
||||||
|
|
||||||
const formula = totalModifier !== 0
|
// Jet du dé de lune séparé (narratif)
|
||||||
? `${nbDice}d6 + ${totalModifier}`
|
let moonDieResult = null
|
||||||
: `${nbDice}d6`
|
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 = {
|
const rollData = {
|
||||||
...options,
|
...options,
|
||||||
difficulty,
|
difficulty,
|
||||||
difficultyValue: diffConfig.value,
|
difficultyValue: diffConfig.value,
|
||||||
moonPhase,
|
|
||||||
moonBonus,
|
|
||||||
modifier,
|
modifier,
|
||||||
aspectMod,
|
aspectMod,
|
||||||
useDestin,
|
useDestin,
|
||||||
destinDice,
|
|
||||||
nbDice,
|
nbDice,
|
||||||
formula,
|
formula,
|
||||||
rollMode: rollContext.visibility ?? "publicroll",
|
rollMode: rollContext.visibility ?? "publicroll",
|
||||||
|
rollMoonDie,
|
||||||
|
moonDieResult,
|
||||||
|
moonFace,
|
||||||
|
moonResultType,
|
||||||
}
|
}
|
||||||
|
|
||||||
const roll = new this(formula, {}, rollData)
|
const roll = new this(formula, {}, rollData)
|
||||||
@@ -143,22 +129,27 @@ export class CelestopolRoll extends Roll {
|
|||||||
roll.computeResult()
|
roll.computeResult()
|
||||||
await roll.toMessage({}, { rollMode: rollData.rollMode })
|
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)
|
const actor = game.actors.get(options.actorId)
|
||||||
if (useDestin && actor && (options.destActuel ?? 1) > 0) {
|
if (useDestin && actor) {
|
||||||
const currentLvl = actor.system.destin?.lvl ?? 0
|
|
||||||
const newLvl = Math.min(8, currentLvl + 1)
|
|
||||||
await actor.update({
|
await actor.update({
|
||||||
"system.destin.lvl": newLvl,
|
"system.destin.lvl": 0,
|
||||||
[`system.destin.d${newLvl}.checked`]: true,
|
"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
|
// Mémoriser les préférences sur l'acteur
|
||||||
if (actor) {
|
if (actor) {
|
||||||
await actor.update({
|
await actor.update({
|
||||||
"system.prefs.moonPhase": moonPhase,
|
"system.prefs.rollMoonDie": rollMoonDie,
|
||||||
"system.prefs.difficulty": difficulty,
|
"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 ≥ 5 → succès critique
|
||||||
* - Marge ≥ 0 → succès
|
* - Marge ≥ 0 → succès
|
||||||
* - Marge ≤ −5 → échec critique
|
* - Marge ≤ −5 → échec critique
|
||||||
@@ -194,22 +185,24 @@ export class CelestopolRoll extends Roll {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _getChatCardData(isPrivate) {
|
async _getChatCardData(isPrivate) {
|
||||||
const statLabel = this.options.statLabel
|
const statLabel = this.options.statLabel
|
||||||
const skillLabel = this.options.skillLabel
|
const skillLabel = this.options.skillLabel
|
||||||
const resultType = this.resultType
|
const resultType = this.resultType
|
||||||
const diceResults = this.dice[0]?.results?.map(r => r.result) ?? []
|
const diceResults = this.dice[0]?.results?.map(r => r.result) ?? []
|
||||||
const diceSum = diceResults.reduce((a, b) => a + b, 0)
|
const diceSum = diceResults.reduce((a, b) => a + b, 0)
|
||||||
const threshold = SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.value ?? 0
|
const threshold = SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.value ?? 0
|
||||||
const margin = this.options.margin
|
const margin = this.options.margin
|
||||||
const moonPhase = this.options.moonPhase ?? "none"
|
const woundMalus = this.options.woundMalus ?? 0
|
||||||
const moonSymbol = MOON_SYMBOLS[moonPhase] ?? "☽"
|
const woundLevelId = this.options.woundLevel ?? 0
|
||||||
const woundMalus = this.options.woundMalus ?? 0
|
const woundLabel = woundLevelId > 0
|
||||||
const woundLevelId = this.options.woundLevel ?? 0
|
|
||||||
const woundLabel = woundLevelId > 0
|
|
||||||
? game.i18n.localize(SYSTEM.WOUND_LEVELS[woundLevelId]?.label ?? "")
|
? game.i18n.localize(SYSTEM.WOUND_LEVELS[woundLevelId]?.label ?? "")
|
||||||
: null
|
: 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 = {
|
const resultClassMap = {
|
||||||
"critical-success": "critical-success",
|
"critical-success": "critical-success",
|
||||||
"success": "success",
|
"success": "success",
|
||||||
@@ -219,41 +212,44 @@ export class CelestopolRoll extends Roll {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cssClass: [SYSTEM.id, "dice-roll"].join(" "),
|
cssClass: [SYSTEM.id, "dice-roll"].join(" "),
|
||||||
actorId: this.actorId,
|
actorId: this.actorId,
|
||||||
actorName: this.actorName,
|
actorName: this.actorName,
|
||||||
actorImg: this.actorImage,
|
actorImg: this.actorImage,
|
||||||
statLabel: statLabel ? game.i18n.localize(statLabel) : "",
|
statLabel: statLabel ? game.i18n.localize(statLabel) : "",
|
||||||
skillLabel: skillLabel ? game.i18n.localize(skillLabel) : "",
|
skillLabel: skillLabel ? game.i18n.localize(skillLabel) : "",
|
||||||
formula: this.formula,
|
formula: this.formula,
|
||||||
total: this.total,
|
total: this.total,
|
||||||
diceSum,
|
diceSum,
|
||||||
diceResults,
|
diceResults,
|
||||||
resultType,
|
resultType,
|
||||||
resultClass: resultClassMap[resultType] ?? "",
|
resultClass: resultClassMap[resultType] ?? "",
|
||||||
isSuccess: this.isSuccess,
|
isSuccess: this.isSuccess,
|
||||||
isFailure: this.isFailure,
|
isFailure: this.isFailure,
|
||||||
isCriticalSuccess: this.isCriticalSuccess,
|
isCriticalSuccess: this.isCriticalSuccess,
|
||||||
isCriticalFailure: this.isCriticalFailure,
|
isCriticalFailure: this.isCriticalFailure,
|
||||||
difficulty: this.options.difficulty,
|
difficulty: this.options.difficulty,
|
||||||
difficultyLabel: game.i18n.localize(SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.label ?? ""),
|
difficultyLabel: game.i18n.localize(SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.label ?? ""),
|
||||||
difficultyValue: threshold,
|
difficultyValue: threshold,
|
||||||
margin,
|
margin,
|
||||||
marginAbs: margin !== null ? Math.abs(margin) : null,
|
marginAbs: margin !== null ? Math.abs(margin) : null,
|
||||||
marginAbove: margin !== null && margin >= 0,
|
marginAbove: margin !== null && margin >= 0,
|
||||||
moonPhase,
|
modifier: this.options.modifier,
|
||||||
moonPhaseLabel: game.i18n.localize(SYSTEM.MOON_DICE_PHASES[moonPhase]?.label ?? ""),
|
aspectMod: this.options.aspectMod ?? 0,
|
||||||
moonSymbol,
|
useDestin: this.options.useDestin ?? false,
|
||||||
moonBonus: this.moonBonus,
|
nbDice: this.options.nbDice ?? diceResults.length,
|
||||||
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,
|
|
||||||
woundMalus,
|
woundMalus,
|
||||||
woundLabel,
|
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,
|
isPrivate,
|
||||||
tooltip: isPrivate ? "" : await this.getTooltip(),
|
tooltip: isPrivate ? "" : await this.getTooltip(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,8 +127,8 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel
|
|||||||
|
|
||||||
// Préférences de jet (mémorisé entre sessions)
|
// Préférences de jet (mémorisé entre sessions)
|
||||||
schema.prefs = new fields.SchemaField({
|
schema.prefs = new fields.SchemaField({
|
||||||
moonPhase: new fields.StringField({ required: true, nullable: false, initial: "none" }),
|
rollMoonDie: new fields.BooleanField({ required: true, initial: false }),
|
||||||
difficulty: new fields.StringField({ required: true, nullable: false, initial: "normal" }),
|
difficulty: new fields.StringField({ required: true, nullable: false, initial: "normal" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
// Description & notes
|
// Description & notes
|
||||||
@@ -177,19 +177,19 @@ export default class CelestopolCharacter extends foundry.abstract.TypeDataModel
|
|||||||
if (!skill) return null
|
if (!skill) return null
|
||||||
|
|
||||||
return CelestopolRoll.prompt({
|
return CelestopolRoll.prompt({
|
||||||
actorId: this.parent.id,
|
actorId: this.parent.id,
|
||||||
actorName: this.parent.name,
|
actorName: this.parent.name,
|
||||||
actorImage: this.parent.img,
|
actorImage: this.parent.img,
|
||||||
statId,
|
statId,
|
||||||
skillId,
|
skillId,
|
||||||
statLabel: SYSTEM.STATS[statId]?.label,
|
statLabel: SYSTEM.STATS[statId]?.label,
|
||||||
skillLabel: skill.label,
|
skillLabel: skill.label,
|
||||||
skillValue: skill.value,
|
skillValue: skill.value,
|
||||||
woundMalus: this.getWoundMalus(),
|
woundMalus: this.getWoundMalus(),
|
||||||
woundLevel: this.blessures.lvl,
|
woundLevel: this.blessures.lvl,
|
||||||
moonPhase: this.prefs.moonPhase,
|
difficulty: this.prefs.difficulty,
|
||||||
difficulty: this.prefs.difficulty,
|
rollMoonDie: this.prefs.rollMoonDie ?? false,
|
||||||
destActuel: Math.max(0, 8 - (this.destin.lvl ?? 0)),
|
destGaugeFull: this.destin.lvl >= 8,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ export default class CelestopolNPC extends foundry.abstract.TypeDataModel {
|
|||||||
})
|
})
|
||||||
|
|
||||||
schema.prefs = new fields.SchemaField({
|
schema.prefs = new fields.SchemaField({
|
||||||
moonPhase: new fields.StringField({ required: true, nullable: false, initial: "none" }),
|
rollMoonDie: new fields.BooleanField({ required: true, initial: false }),
|
||||||
difficulty: new fields.StringField({ required: true, nullable: false, initial: "normal" }),
|
difficulty: new fields.StringField({ required: true, nullable: false, initial: "normal" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
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
|
if (!skill) return null
|
||||||
|
|
||||||
return CelestopolRoll.prompt({
|
return CelestopolRoll.prompt({
|
||||||
actorId: this.parent.id,
|
actorId: this.parent.id,
|
||||||
actorName: this.parent.name,
|
actorName: this.parent.name,
|
||||||
actorImage: this.parent.img,
|
actorImage: this.parent.img,
|
||||||
statId,
|
statId,
|
||||||
skillId,
|
skillId,
|
||||||
skillLabel: skill.label,
|
skillLabel: skill.label,
|
||||||
skillValue: skill.value,
|
skillValue: skill.value,
|
||||||
woundMalus: this.getWoundMalus(),
|
woundMalus: this.getWoundMalus(),
|
||||||
moonPhase: this.prefs.moonPhase,
|
difficulty: this.prefs.difficulty,
|
||||||
difficulty: this.prefs.difficulty,
|
rollMoonDie: this.prefs.rollMoonDie ?? false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
152
styles/roll.less
152
styles/roll.less
@@ -82,52 +82,53 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Phases de lune : grille 3 colonnes ──
|
// ── Ligne Dé de la Lune ──
|
||||||
.moon-section {
|
.form-moon-row {
|
||||||
display: flex;
|
border: 1px solid rgba(122,92,32,0.35);
|
||||||
flex-direction: column;
|
border-radius: 4px;
|
||||||
gap: 5px;
|
background: rgba(255,255,255,0.3);
|
||||||
margin-bottom: 12px;
|
padding: 7px 10px;
|
||||||
|
|
||||||
.moon-section-label {
|
.moon-toggle {
|
||||||
font-size: 0.72em;
|
display: flex;
|
||||||
text-transform: uppercase;
|
align-items: center;
|
||||||
letter-spacing: 0.07em;
|
gap: 8px;
|
||||||
color: var(--cel-orange, #e07b00);
|
cursor: pointer;
|
||||||
border-bottom: 1px solid rgba(122,92,32,0.3);
|
|
||||||
padding-bottom: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.moon-phases {
|
input[type="checkbox"] {
|
||||||
display: grid;
|
width: 16px;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
height: 16px;
|
||||||
gap: 4px;
|
flex-shrink: 0;
|
||||||
|
appearance: none;
|
||||||
.moon-option {
|
-webkit-appearance: none;
|
||||||
display: flex;
|
border: 2px solid var(--cel-border, #7a5c20);
|
||||||
flex-direction: column;
|
border-radius: 2px;
|
||||||
align-items: center;
|
background: white;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 5px 4px;
|
position: relative;
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid rgba(122,92,32,0.25);
|
|
||||||
transition: all 0.15s;
|
|
||||||
background: rgba(255,255,255,0.4);
|
|
||||||
|
|
||||||
&:hover {
|
&:checked {
|
||||||
background: rgba(196,154,26,0.12);
|
background: var(--cel-orange, #e07b00);
|
||||||
border-color: var(--cel-border, #7a5c20);
|
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 {
|
.moon-icon { font-size: 1.2em; flex-shrink: 0; }
|
||||||
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-symbol { font-size: 1.5em; line-height: 1; }
|
.moon-text {
|
||||||
.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%; }
|
font-family: var(--cel-font-title, "CopaseticNF", serif);
|
||||||
.moon-bonus { font-size: 0.68em; color: var(--cel-orange, #e07b00); font-weight: bold; margin-top: 1px; }
|
font-size: 0.88em;
|
||||||
|
color: var(--cel-green, #0c4c0c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,14 +362,7 @@
|
|||||||
.wound-info { font-size: 0.7em; color: #f0a0a0; }
|
.wound-info { font-size: 0.7em; color: #f0a0a0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.moon-badge {
|
.moon-badge { display: none; }
|
||||||
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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Zone dés ──
|
// ── Zone dés ──
|
||||||
@@ -432,7 +426,6 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
.fl-moon { color: #666; }
|
|
||||||
.fl-mod { color: #444; font-weight: bold; }
|
.fl-mod { color: #444; font-weight: bold; }
|
||||||
.fl-asp { color: var(--cel-orange, #e07b00); 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; }
|
.fl-sep { font-weight: bold; color: var(--cel-border, #7a5c20); margin: 0 2px; }
|
||||||
@@ -492,6 +485,69 @@
|
|||||||
.used-destin { font-weight: bold; }
|
.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 ──
|
// ── Bandeau résultat ──
|
||||||
.roll-result-banner {
|
.roll-result-banner {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -13,29 +13,21 @@
|
|||||||
</span>
|
</span>
|
||||||
{{#if woundLabel}}<span class="wound-info">⚠ {{woundLabel}}</span>{{/if}}
|
{{#if woundLabel}}<span class="wound-info">⚠ {{woundLabel}}</span>{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="moon-badge" title="{{moonPhaseLabel}}">
|
|
||||||
<span class="moon-sym">{{moonSymbol}}</span>
|
|
||||||
{{#if moonBonus}}<span class="moon-bon">+{{moonBonus}}</span>{{/if}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{!-- Zone dés --}}
|
{{!-- Zone dés --}}
|
||||||
<div class="dice-zone">
|
<div class="dice-zone">
|
||||||
{{#each diceResults as |die|}}
|
{{#each diceResults as |die|}}
|
||||||
<span class="die-face d6 {{#if (eq die 6)}}max{{/if}}{{#if (eq die 1)}}min{{/if}}">{{die}}</span>
|
<span class="die-face d8 {{#if (eq die 8)}}max{{/if}}{{#if (eq die 1)}}min{{/if}}">{{die}}</span>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{!-- Formule détaillée --}}
|
{{!-- Formule détaillée --}}
|
||||||
<div class="formula-line">
|
<div class="formula-line">
|
||||||
<span class="fl-label">{{localize "CELESTOPOL.Roll.formula"}} :</span>
|
<span class="fl-label">{{localize "CELESTOPOL.Roll.formula"}} :</span>
|
||||||
<span class="fl-ndice">{{nbDice}}d6</span>
|
<span class="fl-ndice">{{nbDice}}d8</span>
|
||||||
<span class="fl-eq"> = </span>
|
<span class="fl-eq"> = </span>
|
||||||
<span class="fl-sum">{{diceSum}}</span>
|
<span class="fl-sum">{{diceSum}}</span>
|
||||||
{{#if moonBonus}}
|
|
||||||
<span class="fl-op">+</span>
|
|
||||||
<span class="fl-moon" title="{{moonPhaseLabel}}">{{moonSymbol}}{{moonBonus}}</span>
|
|
||||||
{{/if}}
|
|
||||||
{{#if modifier}}
|
{{#if modifier}}
|
||||||
<span class="fl-op">{{#if (gt modifier 0)}}+{{else}}−{{/if}}</span>
|
<span class="fl-op">{{#if (gt modifier 0)}}+{{else}}−{{/if}}</span>
|
||||||
<span class="fl-mod">{{abs modifier}}</span>
|
<span class="fl-mod">{{abs modifier}}</span>
|
||||||
@@ -69,6 +61,18 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{!-- Résultat du Dé de la Lune (narratif) --}}
|
||||||
|
{{#if hasMoonDie}}
|
||||||
|
<div class="moon-die-result {{moonResultClass}}">
|
||||||
|
<span class="moon-die-face">{{moonFaceSymbol}}</span>
|
||||||
|
<div class="moon-die-info">
|
||||||
|
<span class="moon-die-phase">{{moonFaceLabel}}</span>
|
||||||
|
<span class="moon-die-type">{{moonResultLabel}}</span>
|
||||||
|
<span class="moon-die-desc">{{moonResultDesc}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{!-- Bandeau résultat --}}
|
{{!-- Bandeau résultat --}}
|
||||||
<div class="roll-result-banner {{resultClass}}">
|
<div class="roll-result-banner {{resultClass}}">
|
||||||
{{#if isCriticalSuccess}}
|
{{#if isCriticalSuccess}}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<div class="roll-dialog-content">
|
<div class="roll-dialog-content">
|
||||||
|
|
||||||
{{!-- En-tête : acteur + domaine + dés de base --}}
|
{{!-- En-tête : acteur + domaine + formule de base --}}
|
||||||
<div class="roll-info-block">
|
<div class="roll-info-block">
|
||||||
<div class="roll-actor">{{actorName}}</div>
|
<div class="roll-actor">{{actorName}}</div>
|
||||||
<div class="roll-skill-line">
|
<div class="roll-skill-line">
|
||||||
@@ -9,15 +9,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="roll-dice-summary">
|
<div class="roll-dice-summary">
|
||||||
<div class="dice-breakdown">
|
<div class="dice-breakdown">
|
||||||
|
<span class="base-dice">2d8</span>
|
||||||
|
<span class="plus-sign"> + </span>
|
||||||
<span class="dval">{{skillValue}}</span>
|
<span class="dval">{{skillValue}}</span>
|
||||||
<span class="dlabel">{{localize "CELESTOPOL.Roll.nbDiceBase"}}</span>
|
|
||||||
{{#if woundMalus}}
|
{{#if woundMalus}}
|
||||||
<span class="dminus"> − {{abs woundMalus}}</span>
|
<span class="dminus"> − {{abs woundMalus}}</span>
|
||||||
<span class="dlabel">{{localize "CELESTOPOL.Roll.woundMalus"}}</span>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<span class="deq"> = </span>
|
|
||||||
<span class="nb-dice" id="preview-ndice">{{nbDiceBase}}</span>
|
|
||||||
<span class="ddice">d6</span>
|
|
||||||
</div>
|
</div>
|
||||||
{{#if woundLabel}}
|
{{#if woundLabel}}
|
||||||
<div class="wound-info">⚠ {{woundLabel}}</div>
|
<div class="wound-info">⚠ {{woundLabel}}</div>
|
||||||
@@ -25,21 +22,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{!-- Phases de lune : grille 3 × 3 --}}
|
|
||||||
<div class="moon-section">
|
|
||||||
<div class="moon-section-label">{{localize "CELESTOPOL.Roll.moonPhase"}}</div>
|
|
||||||
<div class="moon-phases" id="moon-phases">
|
|
||||||
{{#each moonPhaseChoices as |phase key|}}
|
|
||||||
<label class="moon-option {{#if (eq key ../defaultMoonPhase)}}active{{/if}}" data-moon="{{key}}" data-moon-bonus="{{#if phase.bonus}}{{phase.bonus}}{{else}}0{{/if}}" title="{{localize phase.label}}">
|
|
||||||
<input type="radio" name="moonPhase" value="{{key}}" {{#if (eq key ../defaultMoonPhase)}}checked{{/if}} hidden>
|
|
||||||
<span class="moon-symbol">{{phase.symbol}}</span>
|
|
||||||
<span class="moon-name">{{localize phase.label}}</span>
|
|
||||||
<span class="moon-bonus">{{#if phase.bonus}}+{{phase.bonus}}{{else}}+0{{/if}}</span>
|
|
||||||
</label>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="roll-form-rows">
|
<div class="roll-form-rows">
|
||||||
|
|
||||||
{{!-- Difficulté --}}
|
{{!-- Difficulté --}}
|
||||||
@@ -66,19 +48,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{!-- Destin --}}
|
{{!-- Dé de la Lune --}}
|
||||||
<div class="form-destin-row {{#unless destActuel}}destin-disabled{{/unless}}">
|
<div class="form-moon-row">
|
||||||
|
<label class="moon-toggle" for="rollMoonDie">
|
||||||
|
<input type="checkbox" id="rollMoonDie" name="rollMoonDie" {{#if defaultRollMoonDie}}checked{{/if}}>
|
||||||
|
<span class="moon-icon">🌑</span>
|
||||||
|
<span class="moon-text">{{localize "CELESTOPOL.Roll.rollMoonDie"}}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Destin (3d8) — seulement si jauge pleine --}}
|
||||||
|
<div class="form-destin-row {{#unless destGaugeFull}}destin-disabled{{/unless}}">
|
||||||
<label class="destin-toggle" for="useDestin">
|
<label class="destin-toggle" for="useDestin">
|
||||||
<input type="checkbox" id="useDestin" name="useDestin" {{#unless destActuel}}disabled{{/unless}}>
|
<input type="checkbox" id="useDestin" name="useDestin" {{#unless destGaugeFull}}disabled{{/unless}}>
|
||||||
<span class="destin-icon">✦</span>
|
<span class="destin-icon">✦</span>
|
||||||
<span class="destin-text">
|
<span class="destin-text">
|
||||||
<span class="destin-main">{{localize "CELESTOPOL.Roll.destin"}}</span>
|
<span class="destin-main">{{localize "CELESTOPOL.Roll.destin"}}</span>
|
||||||
<span class="destin-bonus">{{localize "CELESTOPOL.Roll.destinBonus"}}</span>
|
<span class="destin-bonus">{{localize "CELESTOPOL.Roll.destinBonus"}}</span>
|
||||||
</span>
|
</span>
|
||||||
{{#if destActuel}}
|
{{#if destGaugeFull}}
|
||||||
<span class="destin-count">{{destActuel}} {{localize "CELESTOPOL.Roll.destinAvailable"}}</span>
|
<span class="destin-badge full">{{localize "CELESTOPOL.Roll.destGaugeFull"}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="destin-count no-destin">{{localize "CELESTOPOL.Roll.destinNone"}}</span>
|
<span class="destin-badge empty">{{localize "CELESTOPOL.Roll.destGaugeEmpty"}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -98,48 +89,34 @@
|
|||||||
{{!-- Prévisualisation formule --}}
|
{{!-- Prévisualisation formule --}}
|
||||||
<div class="dice-preview">
|
<div class="dice-preview">
|
||||||
<span class="preview-label">{{localize "CELESTOPOL.Roll.formula"}}</span>
|
<span class="preview-label">{{localize "CELESTOPOL.Roll.formula"}}</span>
|
||||||
<span class="preview-formula" id="preview-formula">{{nbDiceBase}}d6</span>
|
<span class="preview-formula" id="preview-formula">2d8</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
const wrap = document.querySelector('.roll-dialog-content');
|
const wrap = document.querySelector('.roll-dialog-content');
|
||||||
if (!wrap) return;
|
if (!wrap) return;
|
||||||
|
|
||||||
const skillVal = {{skillValue}};
|
const skillVal = {{skillValue}};
|
||||||
const woundMalus = {{woundMalus}};
|
const woundMalus = {{woundMalus}};
|
||||||
const base = Math.max(1, skillVal + woundMalus);
|
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
const moonOpt = wrap.querySelector('input[name="moonPhase"]:checked')?.closest('[data-moon]');
|
const modifier = parseInt(wrap.querySelector('#modifier')?.value ?? 0) || 0;
|
||||||
const moonBonus = parseInt(moonOpt?.dataset.moonBonus ?? 0) || 0;
|
const aspectMod = parseInt(wrap.querySelector('#aspectModifier')?.value ?? 0) || 0;
|
||||||
const modifier = parseInt(wrap.querySelector('#modifier')?.value ?? 0) || 0;
|
const useDestin = wrap.querySelector('#useDestin')?.checked;
|
||||||
const aspectMod = parseInt(wrap.querySelector('#aspectModifier')?.value ?? 0) || 0;
|
const ndice = useDestin ? 3 : 2;
|
||||||
const useDestin = wrap.querySelector('#useDestin')?.checked ? 2 : 0;
|
const totalMod = skillVal + woundMalus + modifier + aspectMod;
|
||||||
const ndice = Math.max(1, base + useDestin);
|
|
||||||
const totalMod = moonBonus + modifier + aspectMod;
|
|
||||||
|
|
||||||
let formula = `${ndice}d6`;
|
let formula = `${ndice}d8`;
|
||||||
if (totalMod > 0) formula += ` + ${totalMod}`;
|
if (totalMod > 0) formula += ` + ${totalMod}`;
|
||||||
if (totalMod < 0) formula += ` − ${Math.abs(totalMod)}`;
|
if (totalMod < 0) formula += ` − ${Math.abs(totalMod)}`;
|
||||||
|
|
||||||
const previewEl = wrap.querySelector('#preview-formula');
|
const previewEl = wrap.querySelector('#preview-formula');
|
||||||
const ndiceEl = wrap.querySelector('#preview-ndice');
|
|
||||||
if (previewEl) previewEl.textContent = formula;
|
if (previewEl) previewEl.textContent = formula;
|
||||||
if (ndiceEl) ndiceEl.textContent = ndice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wrap.querySelectorAll('.moon-option').forEach(opt => {
|
|
||||||
const input = opt.querySelector('input[type="radio"]');
|
|
||||||
input.addEventListener('change', () => {
|
|
||||||
wrap.querySelectorAll('.moon-option').forEach(o => o.classList.remove('active'));
|
|
||||||
opt.classList.add('active');
|
|
||||||
update();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
wrap.querySelectorAll('#modifier, #aspectModifier, #useDestin').forEach(el => {
|
wrap.querySelectorAll('#modifier, #aspectModifier, #useDestin').forEach(el => {
|
||||||
el.addEventListener('change', update);
|
el.addEventListener('change', update);
|
||||||
el.addEventListener('input', update);
|
el.addEventListener('input', update);
|
||||||
@@ -148,3 +125,4 @@
|
|||||||
update();
|
update();
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user