Modificateur: select difficulté nommée (Évident→Malaisé→Très difficile…)

- Remplace le select -4..+4 par les niveaux Évident/Malaisé/Difficile/etc.
- 'Évident' = réussite automatique (valeur 'auto', pas de dé, force succès)
- Aspect garde son select numérique -4..+4
- Chat message affiche 'Réussite automatique' si autoSuccess
- Ajout CONTEXT_MODIFIER_CHOICES dans config + clés i18n Modifier.*

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-03-29 22:19:34 +02:00
parent 149bc4eb8b
commit 51206acac3
5 changed files with 49 additions and 8 deletions

View File

@@ -151,7 +151,16 @@
"usedFortune": "Fortune utilisée (1d8+8)",
"puiser": "Puiser dans ses ressources",
"puiserDesc": "Ignore tous les malus — coche 1 case de Spleen",
"usedPuiser": "Ressources puisées — malus ignorés, +1 Spleen"
"usedPuiser": "Ressources puisées — malus ignorés, +1 Spleen",
"autoSuccess": "Réussite automatique"
},
"Modifier": {
"evident": "Évident — Réussite automatique",
"malaise": "Malaisé (0)",
"difficile": "Difficile (2)",
"tres": "Très difficile (4)",
"extreme": "Extrêmement difficile (6)",
"incroyable": "Incroyablement difficile (8)"
},
"Moon": {
"none": "Aucune phase",

View File

@@ -111,6 +111,16 @@ export const DIFFICULTY_CHOICES = {
extreme: { id: "extreme", label: "CELESTOPOL.Difficulty.extreme", value: 13 },
}
/** Modificateurs contextuels (difficulté narrative) pour les jets. */
export const CONTEXT_MODIFIER_CHOICES = [
{ id: "evident", label: "CELESTOPOL.Modifier.evident", value: "auto" },
{ id: "malaise", label: "CELESTOPOL.Modifier.malaise", value: 0 },
{ id: "difficile", label: "CELESTOPOL.Modifier.difficile", value: -2 },
{ id: "tres", label: "CELESTOPOL.Modifier.tres", value: -4 },
{ id: "extreme", label: "CELESTOPOL.Modifier.extreme", value: -6 },
{ id: "incroyable", label: "CELESTOPOL.Modifier.incroyable", value: -8 },
]
/** 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é
@@ -172,6 +182,7 @@ export const SYSTEM = {
FACTIONS,
WOUND_LEVELS,
DIFFICULTY_CHOICES,
CONTEXT_MODIFIER_CHOICES,
MOON_DIE_FACES,
MOON_RESULT_TYPES,
EQUIPMENT_TYPES,

View File

@@ -43,7 +43,12 @@ export class CelestopolRoll extends Roll {
? game.i18n.localize(SYSTEM.WOUND_LEVELS[woundLevelId]?.label ?? "")
: null
const modifierChoices = [-4, -3, -2, -1, 0, 1, 2, 3, 4].map(v => ({
const modifierChoices = SYSTEM.CONTEXT_MODIFIER_CHOICES.map(c => ({
id: c.id,
value: c.value,
label: game.i18n.localize(c.label),
}))
const aspectChoices = [-4, -3, -2, -1, 0, 1, 2, 3, 4].map(v => ({
value: v,
label: v > 0 ? `+${v}` : `${v}`,
}))
@@ -60,6 +65,7 @@ export class CelestopolRoll extends Roll {
destGaugeFull,
defaultRollMoonDie: options.rollMoonDie ?? false,
modifierChoices,
aspectChoices,
fortuneValue,
}
@@ -85,7 +91,9 @@ export class CelestopolRoll extends Roll {
}
function update() {
const modifier = parseInt(wrap.querySelector('#modifier')?.value ?? 0) || 0
const rawMod = wrap.querySelector('#modifier')?.value
const autoSucc = rawMod === "auto"
const modifier = autoSucc ? 0 : (parseInt(rawMod ?? 0) || 0)
const aspectMod = parseInt(wrap.querySelector('#aspectModifier')?.value ?? 0) || 0
const useDestin = wrap.querySelector('#useDestin')?.checked
const useFort = wrap.querySelector('#useFortune')?.checked
@@ -110,7 +118,9 @@ export class CelestopolRoll extends Roll {
const totalMod = skillValue + effWound + effMod + effAspect
let formula
if (useFort) {
if (autoSucc) {
formula = game.i18n.localize("CELESTOPOL.Roll.autoSuccess")
} else if (useFort) {
const fm = totalMod + 8
formula = `1d8` + (fm > 0 ? ` + ${fm}` : fm < 0 ? ` ${Math.abs(fm)}` : ``)
} else {
@@ -151,7 +161,8 @@ export class CelestopolRoll extends Roll {
const difficulty = rollContext.difficulty ?? "normal"
const diffConfig = SYSTEM.DIFFICULTY_CHOICES[difficulty] ?? SYSTEM.DIFFICULTY_CHOICES.normal
const modifier = parseInt(rollContext.modifier ?? 0) || 0
const autoSuccess = rollContext.modifier === "auto"
const modifier = autoSuccess ? 0 : (parseInt(rollContext.modifier ?? 0) || 0)
const aspectMod = parseInt(rollContext.aspectModifier ?? 0) || 0
const useDestin = destGaugeFull && (rollContext.useDestin === true || rollContext.useDestin === "true")
const useFortune = fortuneValue > 0 && (rollContext.useFortune === true || rollContext.useFortune === "true")
@@ -188,6 +199,7 @@ export class CelestopolRoll extends Roll {
modifier: effectiveModifier,
aspectMod: effectiveAspectMod,
woundMalus: effectiveWoundMalus,
autoSuccess,
useDestin,
useFortune,
puiserRessources,
@@ -259,6 +271,11 @@ export class CelestopolRoll extends Roll {
* - Marge < 0 → échec
*/
computeResult() {
if (this.options.autoSuccess) {
this.options.resultType = "success"
this.options.margin = null
return
}
const threshold = SYSTEM.DIFFICULTY_CHOICES[this.options.difficulty]?.value ?? 0
if (threshold === 0) {
this.options.resultType = "unknown"
@@ -331,6 +348,7 @@ export class CelestopolRoll extends Roll {
marginAbs: margin !== null ? Math.abs(margin) : null,
marginAbove: margin !== null && margin >= 0,
modifier: this.options.modifier ?? 0,
autoSuccess: this.options.autoSuccess ?? false,
aspectMod: this.options.aspectMod ?? 0,
skillValue,
useDestin: this.options.useDestin ?? false,

View File

@@ -104,7 +104,10 @@
{{!-- Bandeau résultat --}}
<div class="roll-result-banner {{resultClass}}">
{{#if isCriticalSuccess}}
{{#if autoSuccess}}
<span class="result-icon">★</span>
<span class="result-label">{{localize "CELESTOPOL.Roll.autoSuccess"}}</span>
{{else if isCriticalSuccess}}
<span class="result-icon">✦✦</span>
<span class="result-label">{{localize "CELESTOPOL.Roll.criticalSuccess"}}</span>
<span class="result-desc">{{localize "CELESTOPOL.Roll.criticalSuccessDesc"}}</span>

View File

@@ -42,14 +42,14 @@
<label for="modifier">{{localize "CELESTOPOL.Roll.modifier"}}</label>
<select id="modifier" name="modifier">
{{#each modifierChoices as |choice|}}
<option value="{{choice.value}}" {{#if (eq choice.value 0)}}selected{{/if}}>{{choice.label}}</option>
<option value="{{choice.value}}" {{#if (eq choice.id "malaise")}}selected{{/if}}>{{choice.label}}</option>
{{/each}}
</select>
</div>
<div class="form-row-line">
<label for="aspectModifier">{{localize "CELESTOPOL.Roll.aspect"}}</label>
<select id="aspectModifier" name="aspectModifier">
{{#each modifierChoices as |choice|}}
{{#each aspectChoices as |choice|}}
<option value="{{choice.value}}" {{#if (eq choice.value 0)}}selected{{/if}}>{{choice.label}}</option>
{{/each}}
</select>