v2.10.2 : bestiaire etape 3 - encyclopedie (150 monstres par famille + blasons)
treasures.js : section 'Bestiaire' (fetch /api/reference/bestiary, BESTIARY_DB), monsterCard (blason image lazy + plages de stats + fourchette d'ages via BESTIARY_AGE_NAMES + drapeaux/capacites), groupee par famille, + lien de nav. CSS .tz-blason. Reste : integration spawn (en attente du choix profondeur->niveaux de Perco). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -234,6 +234,12 @@ non affilié au jeu original de Mountyhall SARL.
|
|||||||
|
|
||||||
## Versions
|
## Versions
|
||||||
|
|
||||||
|
- **2.10.2** (2026-06-15) — Bestiaire, étape 3 : **encyclopédie**. Nouvelle
|
||||||
|
section « 🐲 Bestiaire » dans « Trésors du Hall » (accessible par le menu) qui
|
||||||
|
liste les 150 monstres **groupés par famille**, avec leur **blason**, leurs
|
||||||
|
plages de stats, leur fourchette d'âges (noms par famille) et leurs
|
||||||
|
drapeaux/capacités. *Reste : la bascule des apparitions du jeu sur ce
|
||||||
|
bestiaire (en attente du choix d'équilibrage profondeur → niveaux).*
|
||||||
- **2.10.1** (2026-06-15) — Bestiaire, étape 2 : **éditeur admin**. Nouvelle
|
- **2.10.1** (2026-06-15) — Bestiaire, étape 2 : **éditeur admin**. Nouvelle
|
||||||
section « 🐲 Bestiaire » dans la page admin pour régler les **multiplicateurs
|
section « 🐲 Bestiaire » dans la page admin pour régler les **multiplicateurs
|
||||||
d'âge** (les 8 âges) et **éditer chaque monstre** (filtre par famille +
|
d'âge** (les 8 âges) et **éditer chaque monstre** (filtre par famille +
|
||||||
|
|||||||
@@ -640,6 +640,8 @@ header h1 { font-size: 1.3em; color: #FFFFCC; text-shadow: 1px 1px 2px #000; }
|
|||||||
font-size: .92em;
|
font-size: .92em;
|
||||||
}
|
}
|
||||||
.tz-name { color: #000000; font-weight: bold; }
|
.tz-name { color: #000000; font-weight: bold; }
|
||||||
|
.tz-blason { width: 34px; height: 34px; object-fit: contain; vertical-align: middle; margin-right: 6px; border: 1px solid #000; background: #fff; }
|
||||||
|
.tz-head { display: flex; align-items: center; }
|
||||||
.tz-meta { color: #666633; font-size: .88em; margin: 4px 0 8px; }
|
.tz-meta { color: #666633; font-size: .88em; margin: 4px 0 8px; }
|
||||||
.tz-meta b { color: #000000; }
|
.tz-meta b { color: #000000; }
|
||||||
.tz-fx-list { display: flex; flex-wrap: wrap; gap: 4px; }
|
.tz-fx-list { display: flex; flex-wrap: wrap; gap: 4px; }
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const APP_VERSION = "2.10.1";
|
const APP_VERSION = "2.10.2";
|
||||||
|
|
||||||
/* Alpha : maîtrise initiale haute pour les tests. Remettre 15 % / 15 % à la v1.0 officielle. */
|
/* Alpha : maîtrise initiale haute pour les tests. Remettre 15 % / 15 % à la v1.0 officielle. */
|
||||||
const START_COMP_PCT = 90;
|
const START_COMP_PCT = 90;
|
||||||
|
|||||||
+68
-3
@@ -61,6 +61,42 @@ function templateCard(t) {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Carte d'un monstre du bestiaire : blason + stats (plages) + âges + capacités. */
|
||||||
|
function monsterCard(m) {
|
||||||
|
const rg = (a, b, s = "") => (a === b ? `${a}${s}` : `${a}-${b}${s}`);
|
||||||
|
const ages = BESTIARY_AGE_NAMES[m.family] || [];
|
||||||
|
const ageTxt = m.minAge === m.maxAge ? (ages[m.minAge] || "—")
|
||||||
|
: `${ages[m.minAge] || m.minAge} → ${ages[m.maxAge] || m.maxAge}`;
|
||||||
|
const fx = [
|
||||||
|
`<span class="tz-fx">PV ${rg(m.pvMin, m.pvMax)}</span>`,
|
||||||
|
`<span class="tz-fx">ATT ${rg(m.attMin, m.attMax, "D6")}</span>`,
|
||||||
|
`<span class="tz-fx">ESQ ${rg(m.esqMin, m.esqMax, "D6")}</span>`,
|
||||||
|
`<span class="tz-fx">DEG ${rg(m.degMin, m.degMax, "D3")}</span>`,
|
||||||
|
`<span class="tz-fx">REG ${rg(m.regMin, m.regMax, "D3")}</span>`,
|
||||||
|
`<span class="tz-fx">Arm.phy ${rg(m.armPhysMin, m.armPhysMax)}</span>`,
|
||||||
|
];
|
||||||
|
if (m.armMagMax) fx.push(`<span class="tz-fx">Arm.mag ${rg(m.armMagMin, m.armMagMax)}</span>`);
|
||||||
|
fx.push(`<span class="tz-fx">Vue ${rg(m.vueMin, m.vueMax)}</span>`,
|
||||||
|
`<span class="tz-fx">MM ${rg(m.mmMin, m.mmMax)}</span>`,
|
||||||
|
`<span class="tz-fx">RM ${rg(m.rmMin, m.rmMax)}</span>`);
|
||||||
|
const tags = [];
|
||||||
|
if (m.fly) tags.push("Vole");
|
||||||
|
if (m.ranged) tags.push("À distance");
|
||||||
|
if (m.magic) tags.push("Att. magique");
|
||||||
|
if (m.seesHidden) tags.push("Voit le caché");
|
||||||
|
if (m.nbAtt > 1) tags.push(m.nbAtt + " att./tour");
|
||||||
|
if (m.speed && m.speed !== "Normale") tags.push("Vitesse " + m.speed);
|
||||||
|
for (const t of tags) fx.push(`<span class="tz-fx tz-good">${t}</span>`);
|
||||||
|
if (m.capacities) fx.push(`<span class="tz-fx tz-bad">${m.capacities}</span>`);
|
||||||
|
const img = m.blason ? `<img class="tz-blason" src="${m.blason}" alt="" loading="lazy" onerror="this.style.display='none'">` : "";
|
||||||
|
return `
|
||||||
|
<div class="tz-card" style="--tz-color:#8a3030">
|
||||||
|
<div class="tz-head">${img}<span class="tz-name">${m.name}</span></div>
|
||||||
|
<div class="tz-meta">Niveau <b>${rg(m.levelMin, m.levelMax)}</b> · Âge : <b>${ageTxt}</b></div>
|
||||||
|
<div class="tz-fx-list">${fx.join("")}</div>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
function treasureCard(def, x, duration, fx) {
|
function treasureCard(def, x, duration, fx) {
|
||||||
const fxHtml = fx.map(f => {
|
const fxHtml = fx.map(f => {
|
||||||
const neg = f.includes("−");
|
const neg = f.includes("−");
|
||||||
@@ -93,6 +129,7 @@ function treasuresRender() {
|
|||||||
<a href="#tz-sec-scrolls">📜 Parchemins</a>
|
<a href="#tz-sec-scrolls">📜 Parchemins</a>
|
||||||
<a href="#tz-sec-gear">⚔️ Équipement</a>
|
<a href="#tz-sec-gear">⚔️ Équipement</a>
|
||||||
<a href="#tz-sec-templates">✨ Templates</a>
|
<a href="#tz-sec-templates">✨ Templates</a>
|
||||||
|
<a href="#tz-sec-bestiary">🐲 Bestiaire</a>
|
||||||
</nav>`;
|
</nav>`;
|
||||||
|
|
||||||
html += `<h2 class="tz-section" id="tz-sec-potions">🧪 Potions (${TREASURE_POTIONS.length})</h2><div class="tz-grid">`;
|
html += `<h2 class="tz-section" id="tz-sec-potions">🧪 Potions (${TREASURE_POTIONS.length})</h2><div class="tz-grid">`;
|
||||||
@@ -155,6 +192,22 @@ function treasuresRender() {
|
|||||||
html += `<p class="tz-note">Liste indisponible (base non joignable).</p>`;
|
html += `<p class="tz-note">Liste indisponible (base non joignable).</p>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bestiary = BESTIARY_DB || [];
|
||||||
|
html += `<h2 class="tz-section" id="tz-sec-bestiary">🐲 Bestiaire (${bestiary.length})</h2>
|
||||||
|
<p class="tz-intro">Les créatures du Hall. Chaque monstre est défini par ses
|
||||||
|
<b>stats de base</b> (l'âge le plus jeune, en plages) ; en vieillissant il gagne
|
||||||
|
en puissance (multiplicateurs d'âge réglables côté admin). Les stats affichées
|
||||||
|
sont des <b>plages</b> tirées au hasard à chaque apparition.</p>`;
|
||||||
|
if (bestiary.length) {
|
||||||
|
const fams = [...new Set(bestiary.map(m => m.family))].sort();
|
||||||
|
for (const fam of fams) {
|
||||||
|
const list = bestiary.filter(m => m.family === fam);
|
||||||
|
html += `<h3 class="tz-subsection">${FAMILY_EMOJI[fam] || "🐾"} ${fam} (${list.length})</h3><div class="tz-grid">${list.map(monsterCard).join("")}</div>`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
html += `<p class="tz-note">Bestiaire indisponible (base non joignable).</p>`;
|
||||||
|
}
|
||||||
|
|
||||||
html += `<p class="tz-note">Effet de Zone : touche le lecteur et tous les monstres à 3 cases
|
html += `<p class="tz-note">Effet de Zone : touche le lecteur et tous les monstres à 3 cases
|
||||||
ou moins. « PV −2D3 ou −4D3 » (Rune des Foins) : la Mountypedia note « -2/4 D3 », interprété
|
ou moins. « PV −2D3 ou −4D3 » (Rune des Foins) : la Mountypedia note « -2/4 D3 », interprété
|
||||||
ici comme un tirage au sort entre 2D3 et 4D3.</p>`;
|
ici comme un tirage au sort entre 2D3 et 4D3.</p>`;
|
||||||
@@ -167,7 +220,18 @@ let treasuresReturnTo = "create";
|
|||||||
// Données de la base de référence (BDD), rechargées à chaque ouverture pour
|
// Données de la base de référence (BDD), rechargées à chaque ouverture pour
|
||||||
// refléter les éditions (admin OU sqlite-web) ; null tant qu'on n'a pas (ou pas
|
// refléter les éditions (admin OU sqlite-web) ; null tant qu'on n'a pas (ou pas
|
||||||
// pu) charger → repli sur les valeurs statiques du code.
|
// pu) charger → repli sur les valeurs statiques du code.
|
||||||
let GEAR_DB = null, POTIONS_DB = null, SCROLLS_DB = null, TEMPLATES_DB = null;
|
let GEAR_DB = null, POTIONS_DB = null, SCROLLS_DB = null, TEMPLATES_DB = null, BESTIARY_DB = null;
|
||||||
|
|
||||||
|
// Noms d'âge par famille (table de Perco) — pour afficher la fourchette d'âges.
|
||||||
|
const BESTIARY_AGE_NAMES = {
|
||||||
|
Insecte: ["Larve", "Immature", "Juvénile", "Imago", "Développé", "Mûr", "Accompli", "Achevé"],
|
||||||
|
Animal: ["Bébé", "Enfançon", "Jeune", "Adulte", "Mature", "Chef de harde", "Ancien", "Ancêtre"],
|
||||||
|
"Démon": ["Initial", "Novice", "Mineur", "Favori", "Majeur", "Supérieur", "Suprême", "Ultime"],
|
||||||
|
Humanoide: ["Nouveau", "Jeune", "Adulte", "Vétéran", "Briscard", "Doyen", "Légendaire", "Mythique"],
|
||||||
|
Monstre: ["Nouveau", "Jeune", "Adulte", "Vétéran", "Briscard", "Doyen", "Légendaire", "Mythique"],
|
||||||
|
"Mort-Vivant": ["Naissant", "Récent", "Ancien", "Vénérable", "Séculaire", "Antique", "Ancestral", "Antédiluvien"],
|
||||||
|
};
|
||||||
|
const FAMILY_EMOJI = { Insecte: "🐛", Animal: "🐾", "Démon": "👿", Humanoide: "🧝", Monstre: "👹", "Mort-Vivant": "💀" };
|
||||||
|
|
||||||
async function fetchRef(cat) {
|
async function fetchRef(cat) {
|
||||||
try {
|
try {
|
||||||
@@ -181,9 +245,10 @@ async function fetchRef(cat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadReference() {
|
async function loadReference() {
|
||||||
const [gear, potions, scrolls, templates] = await Promise.all([
|
const [gear, potions, scrolls, templates, bestiary] = await Promise.all([
|
||||||
fetchRef("gear"), fetchRef("potions"), fetchRef("scrolls"), fetchRef("templates"),
|
fetchRef("gear"), fetchRef("potions"), fetchRef("scrolls"), fetchRef("templates"), fetchRef("bestiary"),
|
||||||
]);
|
]);
|
||||||
|
BESTIARY_DB = bestiary;
|
||||||
GEAR_DB = gear ? gearBySlotFromRows(gear) : null;
|
GEAR_DB = gear ? gearBySlotFromRows(gear) : null;
|
||||||
POTIONS_DB = potions ? indexPowerById(potions) : null;
|
POTIONS_DB = potions ? indexPowerById(potions) : null;
|
||||||
SCROLLS_DB = scrolls ? indexPowerById(scrolls) : null;
|
SCROLLS_DB = scrolls ? indexPowerById(scrolls) : null;
|
||||||
|
|||||||
Reference in New Issue
Block a user