fix(reliability): corrections suite au review
- min: 0 sur reliability (l'update à 0 était clippé à 1 par le schéma — l'état 'détruit' était inatteignable) - réparation de fortune (règles p. 39) : +1D si le personnage possède la Compétence requise, sinon Handicap de Rareté de cette Compétence (rarity du skill de l'acteur) ; select toujours visible (compétence requise) et pré-rempli depuis needSkill/skill de l'item - dés marqués 'dommage' uniquement pour les Dommages réellement comptés (Étanche/Coque absorbe → dés non marqués) - destruction : damages.value réel conservé (difficulté de réparation honnête au lieu de 5 forcé) - états de panne localisés (VERMINE.damages_state_N), aussi dans panneState() - ReliabilityDialog invoqué via .create() (convention du codebase)
This commit is contained in:
@@ -237,6 +237,14 @@
|
||||
"reliability_coque_lost": "Hull: trait exhausted and lost",
|
||||
"reliability_cassant": "Fragile: reliability losses increased by 1 point",
|
||||
"reliability_etanche": "Watertight: immersion damage ignored",
|
||||
"reliability_fortune_skill_bonus": "+1D — the character has the required skill ({skill})",
|
||||
"reliability_fortune_skill_missing": "Required skill ({skill}) not mastered: rarity Handicap +{rarity}",
|
||||
"reliability_fortune_hint": "Field repair: +1D if the character has the required skill, otherwise the rarity Handicap of that skill applies.",
|
||||
"damages_state_1": "Damaged",
|
||||
"damages_state_2": "Damaged",
|
||||
"damages_state_3": "Faulty",
|
||||
"damages_state_4": "Faulty",
|
||||
"damages_state_5": "Out of service",
|
||||
"wounds": {
|
||||
"name": "Wounds",
|
||||
"threshold": "Threshold",
|
||||
|
||||
@@ -318,6 +318,14 @@
|
||||
"reliability_coque_lost": "Coque : Trait épuisé et perdu",
|
||||
"reliability_cassant": "Cassant : pertes de Fiabilité majorées d'1 point",
|
||||
"reliability_etanche": "Étanche : Dommages d'immersion ignorés",
|
||||
"reliability_fortune_skill_bonus": "+1D — le personnage possède la Compétence requise ({skill})",
|
||||
"reliability_fortune_skill_missing": "Compétence requise ({skill}) non maîtrisée : Handicap de Rareté +{rarity}",
|
||||
"reliability_fortune_hint": "Réparation de fortune : +1D si le personnage possède la Compétence requise, sinon Handicap de Rareté de cette Compétence.",
|
||||
"damages_state_1": "Endommagé",
|
||||
"damages_state_2": "Endommagé",
|
||||
"damages_state_3": "Défectueux",
|
||||
"damages_state_4": "Défectueux",
|
||||
"damages_state_5": "Hors d'usage",
|
||||
"choose_ability": "Choisissez une caractéristique",
|
||||
"choose_skill": "Choisissez une compétence",
|
||||
"none": "Aucun",
|
||||
|
||||
@@ -125,13 +125,13 @@ export class VermineBaseItemSheet extends HandlebarsApplicationMixin(foundry.app
|
||||
|
||||
static async #onReliabilityTest() {
|
||||
const { ReliabilityDialog } = await import("../../system/dialogs/reliabilityDialog.mjs")
|
||||
const dialog = new ReliabilityDialog({ item: this.document, mode: "test" })
|
||||
const dialog = await ReliabilityDialog.create({ item: this.document, mode: "test" })
|
||||
await dialog.render(true)
|
||||
}
|
||||
|
||||
static async #onReliabilityRepair() {
|
||||
const { ReliabilityDialog } = await import("../../system/dialogs/reliabilityDialog.mjs")
|
||||
const dialog = new ReliabilityDialog({ item: this.document, mode: "repair" })
|
||||
const dialog = await ReliabilityDialog.create({ item: this.document, mode: "repair" })
|
||||
await dialog.render(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ export function baseItemSchema() {
|
||||
return {
|
||||
description: new fields.HTMLField({ required: true, initial: "", textSearch: true }),
|
||||
rarity: raritySchema(),
|
||||
reliability: new fields.NumberField({ ...reqInt, initial: 3, min: 1, max: 10 }),
|
||||
reliability: new fields.NumberField({ ...reqInt, initial: 3, min: 0, max: 10 }),
|
||||
handicap: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
||||
quantity: new fields.NumberField({ ...reqInt, initial: 1, min: 1 }),
|
||||
weight: new fields.NumberField({ ...reqInt, initial: 0, min: 0 }),
|
||||
|
||||
@@ -50,6 +50,8 @@ export default class ReliabilityDialog extends HandlebarsApplicationMixin(foundr
|
||||
async _prepareContext() {
|
||||
const hasEtanche = !!this.#item.system?.traits?.etanche;
|
||||
const hasActor = !!this.#item.actor;
|
||||
const storedSkill = (this.#item.system?.needSkill?.value && this.#item.system?.needSkill?.skill)
|
||||
|| this.#item.system?.skill || '';
|
||||
const severities = ['mineurs', 'graves', 'critiques'].map((key) => ({
|
||||
key,
|
||||
label: game.i18n.localize(`VERMINE.reliability_severity_${key}`),
|
||||
@@ -58,6 +60,7 @@ export default class ReliabilityDialog extends HandlebarsApplicationMixin(foundr
|
||||
const skills = VermineReliability.REPAIR_SKILLS.map((key) => ({
|
||||
key,
|
||||
label: game.i18n.localize(`SKILLS.${key}.name`),
|
||||
selected: key === storedSkill && VermineReliability.REPAIR_SKILLS.includes(storedSkill),
|
||||
}));
|
||||
return {
|
||||
mode: this.#mode,
|
||||
@@ -70,20 +73,6 @@ export default class ReliabilityDialog extends HandlebarsApplicationMixin(foundr
|
||||
};
|
||||
}
|
||||
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options);
|
||||
if (this.#mode !== 'repair') return;
|
||||
const select = this.element.querySelector('#reliability-skill');
|
||||
const radios = this.element.querySelectorAll('input[name="repairMode"]');
|
||||
if (!select || !radios.length) return;
|
||||
const refresh = () => {
|
||||
const fortune = this.element.querySelector('input[name="repairMode"]:checked')?.value === 'fortune';
|
||||
select.closest('.form-group')?.classList.toggle('hidden', fortune);
|
||||
};
|
||||
radios.forEach((r) => r.addEventListener('change', refresh));
|
||||
refresh();
|
||||
}
|
||||
|
||||
#getOptions() {
|
||||
const el = this.element;
|
||||
if (this.#mode === 'test') {
|
||||
|
||||
@@ -40,8 +40,9 @@ export class VermineReliability {
|
||||
*/
|
||||
static panneState(item) {
|
||||
const damages = item.system?.damages;
|
||||
const idx = (parseInt(damages?.value ?? 0, 10) || 0) - 1;
|
||||
return idx >= 0 ? damages.state?.[idx] ?? '' : '';
|
||||
const value = parseInt(damages?.value ?? 0, 10) || 0;
|
||||
if (value <= 0 || !damages?.state?.[value - 1]) return '';
|
||||
return game.i18n.localize(`VERMINE.damages_state_${value}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +109,7 @@ export class VermineReliability {
|
||||
const destroyed = newReliability === 0;
|
||||
|
||||
updates['system.reliability'] = newReliability;
|
||||
updates['system.damages.value'] = destroyed ? 5 : newDamagesValue;
|
||||
updates['system.damages.value'] = newDamagesValue;
|
||||
await item.update(updates);
|
||||
|
||||
// État final affiché sur la carte.
|
||||
@@ -116,12 +117,17 @@ export class VermineReliability {
|
||||
if (destroyed) {
|
||||
state = game.i18n.localize('VERMINE.reliability_destroyed');
|
||||
} else if (newDamagesValue > 0) {
|
||||
const idx = newDamagesValue - 1;
|
||||
state = item.system.damages.state?.[idx] ?? '';
|
||||
state = game.i18n.localize(`VERMINE.damages_state_${newDamagesValue}`);
|
||||
} else {
|
||||
state = '';
|
||||
}
|
||||
|
||||
// Ne marque comme Dommage que les dés réellement comptés (après
|
||||
// absorption Étanche/Coque) : les dés absorbés restent affichés mais
|
||||
// sans le style "damage".
|
||||
const candidates = results.map((v, i) => ({ v, i })).filter((o) => o.v >= current);
|
||||
const damageIdx = new Set(candidates.slice(0, Math.max(0, dommages)).map((o) => o.i));
|
||||
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/vermine2047/templates/reliability-test.hbs',
|
||||
{
|
||||
@@ -131,7 +137,7 @@ export class VermineReliability {
|
||||
oldReliability: current,
|
||||
newReliability,
|
||||
dommages,
|
||||
results: results.map((v) => ({ value: v, isDamage: v >= current })),
|
||||
results: results.map((v, i) => ({ value: v, isDamage: damageIdx.has(i) })),
|
||||
state,
|
||||
destroyed,
|
||||
traitsNotes,
|
||||
@@ -176,7 +182,23 @@ export class VermineReliability {
|
||||
: parseInt(actor.system?.skills?.[skill]?.value ?? 0, 10) || 0;
|
||||
const NoD = Math.max(0, precision + skillValue);
|
||||
|
||||
const roll = new Roll(`${NoD}d10cs>=${difficulty}`);
|
||||
// Réparation de fortune (p. 39) : si le personnage possède la Compétence
|
||||
// requise, +1D sur le jet ; sinon, Handicap de Rareté de cette Compétence
|
||||
// (le Bonus de Bricolage s'applique dans les deux cas).
|
||||
const skillRarity = parseInt(actor.system?.skills?.[skill]?.rarity ?? 0, 10) || 0;
|
||||
const hasSkill = (parseInt(actor.system?.skills?.[skill]?.value ?? 0, 10) || 0) > 0;
|
||||
const fortuneBonus = mode === 'fortune' && hasSkill ? 1 : 0;
|
||||
const fortuneHandicap = mode === 'fortune' && !hasSkill ? skillRarity : 0;
|
||||
let fortuneNote = '';
|
||||
if (mode === 'fortune') {
|
||||
if (hasSkill) {
|
||||
fortuneNote = game.i18n.format('VERMINE.reliability_fortune_skill_bonus', { skill: game.i18n.localize(`SKILLS.${skill}.name`) });
|
||||
} else if (skillRarity > 0) {
|
||||
fortuneNote = game.i18n.format('VERMINE.reliability_fortune_skill_missing', { skill: game.i18n.localize(`SKILLS.${skill}.name`), rarity: skillRarity });
|
||||
}
|
||||
}
|
||||
|
||||
const roll = new Roll(`${NoD + fortuneBonus}d10cs>=${difficulty}`);
|
||||
await roll.evaluate();
|
||||
await VermineUtils.showDiceSoNice(roll);
|
||||
|
||||
@@ -185,7 +207,7 @@ export class VermineReliability {
|
||||
isSuccess: r.success,
|
||||
})));
|
||||
const successes = roll._total ?? 0;
|
||||
const required = 1 + handicap;
|
||||
const required = 1 + handicap + fortuneHandicap;
|
||||
const success = successes >= required;
|
||||
|
||||
let gained = 0;
|
||||
@@ -228,6 +250,7 @@ export class VermineReliability {
|
||||
successes,
|
||||
required,
|
||||
resultLabel,
|
||||
fortuneNote,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -37,10 +37,11 @@
|
||||
<label for="reliability-skill">{{ localize "VERMINE.reliability_skill" }}</label>
|
||||
<select id="reliability-skill" name="skill">
|
||||
{{#each skills}}
|
||||
<option value="{{this.key}}">{{this.label}}</option>
|
||||
<option value="{{this.key}}" {{#if this.selected}}selected{{/if}}>{{this.label}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<p class="reliability-hint">{{ localize "VERMINE.reliability_fortune_hint" }}</p>
|
||||
{{#unless hasActor}}
|
||||
<p class="reliability-hint">{{ localize "VERMINE.reliability_need_actor" }}</p>
|
||||
{{/unless}}
|
||||
|
||||
@@ -18,4 +18,5 @@
|
||||
<span><strong>{{ localize "VERMINE.reliability_successes" }}:</strong> {{successes}} / {{required}}</span>
|
||||
<span><strong>{{ localize "VERMINE.reliability_result" }}:</strong> {{resultLabel}}</span>
|
||||
</div>
|
||||
{{#if fortuneNote}}<p class="reliability-note">{{fortuneNote}}</p>{{/if}}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user