Files
percoandClaude Fable 5 6039497e72 1.6.0 : parchemins standards + page « Trésors du Hall »
- js/scrolls.js : les 7 parchemins standards de Mountypedia (X 1-5),
  effets via le système d'effets magiques, un seul jet de D3 par parchemin
- Effets de zone (rayon 3 cases) : Rune Explosive (dégâts aux monstres),
  Yeu'Ki'Pic (VUE des monstres réduite, statut à durée)
- TOUR ±X*30 min converti en ±X PA par tour (PA min. 1)
- Drops : coffres (12 %), butin de monstres (25 %), pinceau éditeur,
  validation serveur du kind « scroll »
- js/treasures.js : page encyclopédie des 25 potions et 7 parchemins
  (niveau X, durée, formules), boutons accueil + en jeu

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 23:35:41 +02:00

172 lines
5.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Parchemins MountyHall — trésors à lire, effets et durée en tours (1 tour = 1 DLA).
* Source : https://mountypedia.mountyhall.com/Mountyhall/Parchemins
* Convention temps → PA : 30 min de TOUR = +1 PA au début du tour (comme le
* Jus de Chronomètre) ; 15 min = +1 PA par tranche de 2 niveaux (arrondi sup.).
* Les effets de zone touchent le lecteur et tout monstre dans un rayon de
* SCROLL_ZONE_RADIUS cases. */
"use strict";
/* potions.js est chargé avant ce fichier dans le navigateur ; en node, require explicite. */
if (typeof module !== "undefined" && module.exports && typeof sharedMod === "undefined") {
Object.assign(globalThis, require("./potions.js"));
}
const SCROLL_ZONE_RADIUS = 3;
const SCROLL_IDS = [
"runeCyclopes", "clairvoyance", "ideesConfuses", "runeExplosive",
"planGenial", "yeuKiPic", "runeFoins",
];
function scrollRand(min, max) {
return min + Math.floor(Math.random() * (max - min + 1));
}
const SCROLL_DEFS = {
runeCyclopes: {
name: "Rune des Cyclopes", emoji: "👁️", color: "#c89048",
duration: 4,
build(_t, p, rollDice) {
const attR = sharedMod(rollDice(p, 3).total, p, 3, false);
const lines = [`ATT ${attR.line}`, `DEG +${p}`, `VUE ${p}`];
return {
log: `Rune des Cyclopes : ${lines.join(", ")} pendant 4 tours.`,
effects: [makeEffect("Rune des Cyclopes", "👁️", 4, {
attFlat: attR.value, degFlat: p, vue: -p,
}, lines)],
};
},
},
clairvoyance: {
name: "Traité de Clairvoyance", emoji: "🔮", color: "#88a8e0",
duration: 4,
build(_t, p) {
const lines = [`VUE +${p}`, `DLA +${p} PA/tour`];
return {
log: `Traité de Clairvoyance : VUE +${p}, TOUR accéléré (+${p} PA) pendant 4 tours.`,
effects: [makeEffect("Traité de Clairvoyance", "🔮", 4, {
vue: p, dlaBonusPA: p,
}, lines)],
};
},
},
ideesConfuses: {
name: "Idées Confuses", emoji: "💫", color: "#b078b0",
duration: 3,
build(_t, p, rollDice) {
const attR = sharedMod(rollDice(p, 3).total, p, 3, true);
const lines = [`ATT ${attR.line}`, `DLA ${p} PA/tour`];
return {
log: `Idées Confuses : ATT ${attR.line}, TOUR ralenti (${p} PA) pendant 3 tours.`,
effects: [makeEffect("Idées Confuses", "💫", 3, {
attFlat: attR.value, dlaBonusPA: -p,
}, lines)],
};
},
},
runeExplosive: {
name: "Rune Explosive", emoji: "💥", color: "#e06030",
duration: 0, zone: true,
build(troll, p, rollDice) {
const dmg = rollDice(2 * p, 3).total;
troll.pv = Math.max(1, troll.pv - dmg);
return {
log: `Rune Explosive : ${dmg} PV (${2 * p}D3), l'explosion ravage la zone !`,
effects: [],
zone: { type: "damage", total: dmg, label: `${2 * p}D3` },
};
},
},
planGenial: {
name: "Plan Génial", emoji: "💡", color: "#e0c048",
duration: 3,
build(_t, p, rollDice) {
const pa = Math.ceil(p / 2);
const attR = sharedMod(rollDice(p, 3).total, p, 3, false);
const lines = [`ATT ${attR.line}`, `DEG +${p}`, `DLA +${pa} PA/tour`];
return {
log: `Plan Génial : ${lines.join(", ")} pendant 3 tours.`,
effects: [makeEffect("Plan Génial", "💡", 3, {
attFlat: attR.value, degFlat: p, dlaBonusPA: pa,
}, lines)],
};
},
},
yeuKiPic: {
name: "Yeu'Ki'Pic", emoji: "🌶️", color: "#c04040",
duration: 2, zone: true,
build(_t, p) {
const malus = 3 * p;
return {
log: `Yeu'Ki'Pic : un nuage piquant ! VUE ${malus} pour toute la zone pendant 2 tours.`,
effects: [makeEffect("Yeu'Ki'Pic", "🌶️", 2, { vue: -malus })],
zone: { type: "vue", malus, turns: 2 },
};
},
},
runeFoins: {
name: "Rune des Foins", emoji: "🌾", color: "#a8a048",
duration: 3,
build(troll, p, rollDice) {
// « PV : -2/4 D3 » (Mountypedia) : interprété comme 2D3 ou 4D3 au hasard
const dice = Math.random() < 0.5 ? 2 : 4;
const dmg = rollDice(dice, 3).total;
troll.pv = Math.max(1, troll.pv - dmg);
const lines = [`DEG ${p}`, "VUE 1"];
return {
log: `Rune des Foins : atchoum ! ${dmg} PV (${dice}D3), ${lines.join(", ")} pendant 3 tours.`,
effects: [makeEffect("Rune des Foins", "🌾", 3, { degFlat: -p, vue: -1 }, lines)],
};
},
},
};
function formatScrollItem(scrollId, power) {
const def = SCROLL_DEFS[scrollId];
if (!def) return null;
return {
kind: "scroll",
scrollId,
power,
name: `${def.name} (niv. ${power})`,
emoji: def.emoji,
color: def.color,
};
}
function makeRandomScroll() {
const id = SCROLL_IDS[Math.floor(Math.random() * SCROLL_IDS.length)];
return formatScrollItem(id, scrollRand(1, 5));
}
function makeScrollItem(scrollId, power) {
if (!SCROLL_DEFS[scrollId]) return makeRandomScroll();
return formatScrollItem(scrollId, power != null ? power : scrollRand(1, 5));
}
/* Lit un parchemin. Retourne null si inconnu, sinon { zone } — game.js applique
* l'éventuel effet de zone aux monstres alentour. */
function readScroll(troll, item, rollDice, logFn) {
const def = SCROLL_DEFS[item.scrollId];
if (!def) {
logFn("Ce parchemin est illisible.", "info");
return null;
}
const p = item.power != null ? item.power : scrollRand(1, 5);
const result = def.build(troll, p, rollDice);
if (result.effects.length) {
troll.potionEffects = troll.potionEffects || [];
troll.potionEffects.push(...result.effects);
}
logFn(`📜 ${result.log}`, "good");
return { zone: result.zone || null };
}
if (typeof module !== "undefined" && module.exports) {
module.exports = {
SCROLL_IDS, SCROLL_DEFS, SCROLL_ZONE_RADIUS,
formatScrollItem, makeRandomScroll, makeScrollItem, readScroll,
};
}