1.7.1 : bonus d'équipement fixes sur les jets, jamais en dés

ATT/ESQ/DEG/REG d'équipement alimentent attFlat/esqFlat/degFlat/regFlat
dans effTroll (Gourdin = DEG +5 sur le jet, pas +5D3).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
perco
2026-06-12 00:02:27 +02:00
co-authored by Claude Fable 5
parent 2f21f867a5
commit 61a8cee0fc
6 changed files with 32 additions and 22 deletions
+4 -1
View File
@@ -152,9 +152,12 @@ non affilié au jeu original de Mountyhall SARL.
## Versions
- **1.7.1** (2026-06-12) — Les bonus ATT/ESQ/DEG/REG de l'équipement sont des bonus
**fixes** ajoutés aux jets, jamais des dés supplémentaires (un Gourdin donne
DEG +5 sur le jet, pas +5D3).
- **1.7.0** (2026-06-11) — Équipement Mountypedia complet : 6 emplacements (Arme,
Armure, Casque, Bouclier, Talisman, Bottes) et 55 objets dropables aux valeurs
de base officielles (ATT/ESQ/DEG/REG en dés, Armure/VUE/PV fixes, RM/MM en %).
de base officielles (bonus fixes, RM/MM en %).
Armes à 2 mains incompatibles avec un bouclier, PV max d'équipement, tiers de
drop par profondeur, pinceaux d'éditeur par emplacement, rétrocompatibilité des
anciens niveaux publiés (specs weapon/armor mappées). Section « Équipement »
+1 -1
View File
@@ -4,7 +4,7 @@
"use strict";
const APP_VERSION = "1.7.0";
const APP_VERSION = "1.7.1";
/* Alpha : maîtrise initiale haute pour les tests. Remettre 15 % / 15 % à la v1.0 officielle. */
const START_COMP_PCT = 90;
+5 -4
View File
@@ -1,7 +1,8 @@
/* Équipement MountyHall — 6 emplacements, objets dropables actuels de la Mountypedia :
* https://mountypedia.mountyhall.com/Mountyhall/{Arme,Armure,Casque,Bouclier,Talisman,Bottes}
* Valeurs de base (sans templates) : ATT/ESQ/DEG/REG modifient le nombre de dés,
* ARM/VUE/PV sont fixes, RM/MM en %. `tier` (1-5) borne la profondeur de drop.
* Valeurs de base (sans templates) : TOUS les bonus sont fixes — ATT/ESQ/DEG/REG
* s'ajoutent aux jets (jamais en dés), ARM/VUE/PV sont fixes, RM/MM en %.
* `tier` (1-5) borne la profondeur de drop.
* Les armes à deux mains (twoHanded) sont incompatibles avec un bouclier. */
"use strict";
@@ -90,8 +91,8 @@ const LEGACY_WEAPON_NAMES = ["Épée Courte", "Gourdin", "Épée Longue", "Lame
const LEGACY_ARMOR_NAMES = ["Armure de cuir", "Haubert de mailles", "Armure de plates"];
const GEAR_MOD_LABELS = [
["att", "ATT", " dé(s)"], ["esq", "ESQ", " dé(s)"], ["deg", "DEG", " dé(s)"],
["reg", "REG", " dé(s)"], ["arm", "Armure", ""], ["vue", "VUE", ""], ["pv", "PV", ""],
["att", "ATT", ""], ["esq", "ESQ", ""], ["deg", "DEG", ""],
["reg", "REG", ""], ["arm", "Armure", ""], ["vue", "VUE", ""], ["pv", "PV", ""],
["rmPct", "RM", " %"], ["mmPct", "MM", " %"],
];
+11 -9
View File
@@ -414,19 +414,21 @@ function fmtStatLine(base, eff, faces, flat = 0, extra = 0) {
}
/* Caractéristiques effectives : base + effets magiques (potions, parchemins)
* + équipement (troll.gearMods, recalculé par game.js à chaque équipement). */
* + équipement (troll.gearMods, recalculé par game.js à chaque équipement).
* Les bonus ATT/ESQ/DEG/REG de l'équipement sont des bonus FIXES sur les jets,
* jamais des dés supplémentaires. */
function effTroll(troll) {
const m = sumPotionMods(troll.potionEffects);
const g = troll.gearMods || {};
return {
att: Math.max(1, troll.att + m.att + (g.att || 0)),
attFlat: m.attFlat,
esq: Math.max(1, troll.esq + m.esq + (g.esq || 0)),
esqFlat: m.esqFlat,
deg: Math.max(1, troll.deg + m.deg + (g.deg || 0)),
degFlat: m.degFlat,
reg: Math.max(1, troll.reg + m.reg + (g.reg || 0)),
regFlat: m.regFlat,
att: Math.max(1, troll.att + m.att),
attFlat: m.attFlat + (g.att || 0),
esq: Math.max(1, troll.esq + m.esq),
esqFlat: m.esqFlat + (g.esq || 0),
deg: Math.max(1, troll.deg + m.deg),
degFlat: m.degFlat + (g.deg || 0),
reg: Math.max(1, troll.reg + m.reg),
regFlat: m.regFlat + (g.reg || 0),
vue: Math.max(1, troll.vue + m.vue + (g.vue || 0)),
armor: Math.max(0, troll.armor + m.armor + (g.arm || 0)),
armorDice: troll.armorDice,
+2 -1
View File
@@ -83,7 +83,8 @@ function treasuresRender() {
const gearCount = Object.values(GEAR).reduce((n, list) => n + list.length, 0);
html += `<h2 class="tz-section">⚔️ Équipement (${gearCount})</h2>
<p class="tz-intro">Six emplacements : ${Object.values(GEAR_SLOTS).map(s => s.label).join(", ")}.
Les bonus ATT/ESQ/DEG/REG s'ajoutent en <b>dés</b>, Armure/VUE/PV sont fixes, RM/MM en %.
Tous les bonus d'équipement sont <b>fixes</b> : ATT/ESQ/DEG/REG s'ajoutent aux jets
(jamais en dés), Armure/VUE/PV aussi, RM/MM en %.
Une arme <b>à 2 mains</b> est incompatible avec un bouclier. S'équiper coûte <b>2 PA</b>.
Valeurs de base de la Mountypedia (sans templates) ; les objets puissants ne se trouvent
qu'en profondeur.</p>`;
+9 -6
View File
@@ -271,12 +271,15 @@ assert.strictEqual(g.itemFromSpec({ x: 1, y: 1, kind: "armor", idx: 0 }).name, "
const t = { att: 3, esq: 3, deg: 3, reg: 1, vue: 3, armor: 0, armorDice: 0, degBonus: 0, pvMax: 30, pv: 20,
potionEffects: [], blockCamoTurns: 0, tour: 1, bag: [],
equip: { arme: null, armure: null, casque: null, bouclier: null, talisman: null, bottes: null }, gearMods: null };
g.equipGear(t, gear.gearItemByName("arme", "Gourdin")); // att +2, esq 2, deg +5
g.equipGear(t, gear.gearItemByName("arme", "Gourdin")); // att +2, esq 2, deg +5 (fixes)
g.equipGear(t, gear.gearItemByName("armure", "Armure de cuir")); // esq +3, arm +4, rm +40 %
let e = p.effTroll(t);
assert.strictEqual(e.att, 5, "Gourdin : ATT 3 + 2 dés");
assert.strictEqual(e.deg, 8, "Gourdin : DEG 3 + 5 dés");
assert.strictEqual(e.esq, 4, "ESQ 3 2 + 3");
assert.strictEqual(e.att, 3, "l'équipement n'ajoute jamais de dés");
assert.strictEqual(e.attFlat, 2, "Gourdin : ATT +2 fixe sur le jet");
assert.strictEqual(e.deg, 3, "DEG reste 3D3");
assert.strictEqual(e.degFlat, 5, "Gourdin : DEG +5 fixe");
assert.strictEqual(e.esq, 3, "ESQ reste 3D6");
assert.strictEqual(e.esqFlat, 1, "ESQ 2 (Gourdin) +3 (Armure de cuir) = +1 fixe");
assert.strictEqual(e.armor, 4, "Armure de cuir : armure +4");
assert.strictEqual(e.rmPct, 40, "Armure de cuir : RM +40 %");
// PV max d'équipement
@@ -289,8 +292,8 @@ assert.strictEqual(g.itemFromSpec({ x: 1, y: 1, kind: "armor", idx: 0 }).name, "
assert.strictEqual(t.pvMax, 30, "PV max retombé après déséquipement de la Rondache");
assert(t.bag.some(i => i.name === "Gourdin"), "l'ancienne arme est dans le sac");
e = p.effTroll(t);
assert.strictEqual(e.att, 1, "Hallebarde : ATT 3 5 → min 1");
assert.strictEqual(e.deg, 15, "Hallebarde : DEG 3 + 12");
assert.strictEqual(e.attFlat, -5, "Hallebarde : ATT 5 fixe");
assert.strictEqual(e.degFlat, 12, "Hallebarde : DEG +12 fixe");
// rééquiper un bouclier range l'arme à 2 mains
g.equipGear(t, gear.gearItemByName("bouclier", "Targe"));
assert.strictEqual(t.equip.arme, null, "Targe : la Hallebarde est rangée");