diff --git a/README.md b/README.md index ac3b6b0..0756d2f 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,11 @@ non affilié au jeu original de Mountyhall SARL. ## Versions +- **2.7.1** (2026-06-14) — Encyclopédie « Trésors du Hall » : nouvelle section + **✨ Templates** (les 19 templates de drop, lus dans la base), un **menu de + navigation** collant en haut pour sauter directement à chaque section (Potions, + Parchemins, Équipement, Templates) et un bouton flottant **« remonter en + haut »** qui apparaît dès qu'on a défilé — la page étant devenue longue. - **2.7.0** (2026-06-14) — **Templates de drop** façon MountyHall. 19 suffixes (« de l'Aigle », « des Mages », « des Béhémoths »…) stockés dans une nouvelle table `templates` de la base (seedés au démarrage, éditables comme le reste via diff --git a/css/style.css b/css/style.css index f8993d1..dd22d24 100644 --- a/css/style.css +++ b/css/style.css @@ -569,7 +569,49 @@ header h1 { font-size: 1.3em; color: #FFFFCC; text-shadow: 1px 1px 2px #000; } border-bottom: 2px solid #000000; margin: 24px 0 12px; font-size: 1.3em; + scroll-margin-top: 64px; /* pour que l'ancre ne passe pas sous le menu collant */ } +/* Menu de navigation entre sections (collant en haut). */ +.tz-nav { + position: sticky; + top: 0; + z-index: 5; + display: flex; + flex-wrap: wrap; + gap: 6px; + padding: 8px 0; + margin: 8px 0 4px; + background: #FFFFEE url("../img/mh/tableau1.jpg"); + border-bottom: 1px solid #000000; +} +.tz-nav a { + padding: 5px 10px; + font-size: .9em; + text-decoration: none; + color: #333300; + background: #EBEDAB url("../img/mh/tableau2.jpg"); + border: 1px solid #666633; +} +.tz-nav a:hover { border-color: #990000; color: #990000; } +/* Bouton « remonter en haut » flottant. */ +.tz-top { + position: fixed; + right: 18px; + bottom: 18px; + z-index: 6; + width: 44px; + height: 44px; + font-size: 1.4em; + line-height: 1; + color: #FFFFCC; + background: #666633; + border: 1px solid #000000; + border-radius: 50%; + cursor: pointer; + box-shadow: 1px 1px 4px rgba(0, 0, 0, .4); +} +.tz-top:hover { background: #990000; } +.tz-top.hidden { display: none; } .tz-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); diff --git a/index.html b/index.html index 1c1a569..26f1e68 100644 --- a/index.html +++ b/index.html @@ -214,6 +214,7 @@
+ diff --git a/js/game.js b/js/game.js index a594bcd..dc9a71c 100644 --- a/js/game.js +++ b/js/game.js @@ -4,7 +4,7 @@ "use strict"; -const APP_VERSION = "2.7.0"; +const APP_VERSION = "2.7.1"; /* Alpha : maîtrise initiale haute pour les tests. Remettre 15 % / 15 % à la v1.0 officielle. */ const START_COMP_PCT = 90; diff --git a/js/treasures.js b/js/treasures.js index afd96f5..e0f2153 100644 --- a/js/treasures.js +++ b/js/treasures.js @@ -44,6 +44,23 @@ const TREASURE_SCROLLS = [ ["runeFoins", "1 à 5", "3 tours", ["DEG −X", "VUE −1", "PV −2D3 ou −4D3 (immédiat)"]], ]; +/* Carte d'un template de drop : ses bonus, lus directement sur la ligne BDD + * (mêmes clés que les mods d'équipement, donc on réutilise GEAR_MOD_LABELS). */ +function templateCard(t) { + const fx = []; + for (const [key, label, unit] of GEAR_MOD_LABELS) { + const v = t[key]; + if (!v) continue; + fx.push(`${label} ${v > 0 ? "+" : "−"}${Math.abs(v)}${unit}`); + } + if (!fx.length) fx.push('aucun bonus (titre honorifique)'); + return ` +
+
✨ ${t.name}
+
${fx.join("")}
+
`; +} + function treasureCard(def, x, duration, fx) { const fxHtml = fx.map(f => { const neg = f.includes("−"); @@ -70,13 +87,21 @@ function treasuresRender() { l'armure magique, seule à réduire les dégâts magiques. 1 tour = 1 DLA. Boire une potion ou lire un parchemin coûte 1 PA.

`; - html += `

🧪 Potions (${TREASURE_POTIONS.length})

`; + const templates = TEMPLATES_DB || []; + html += ``; + + html += `

🧪 Potions (${TREASURE_POTIONS.length})

`; for (const [id, x, duration, fx] of TREASURE_POTIONS) { html += treasureCard(POTION_DEFS[id], powerLabel(x, POTIONS_DB && POTIONS_DB[id]), duration, fx); } html += "
"; - html += `

📜 Parchemins standards (${TREASURE_SCROLLS.length})

`; + html += `

📜 Parchemins standards (${TREASURE_SCROLLS.length})

`; for (const [id, x, duration, fx] of TREASURE_SCROLLS) { html += treasureCard(SCROLL_DEFS[id], powerLabel(x, SCROLLS_DB && SCROLLS_DB[id]), duration, fx); } @@ -86,7 +111,7 @@ function treasuresRender() { // a pu être chargée, sinon les valeurs statiques de gear.js (ex. hors-ligne). const gearSource = GEAR_DB || GEAR; const gearCount = Object.values(gearSource).reduce((n, list) => n + list.length, 0); - html += `

⚔️ Équipement (${gearCount})

+ html += `

⚔️ Équipement (${gearCount})

Six emplacements : ${Object.values(GEAR_SLOTS).map(s => s.label).join(", ")}. Les bonus d'équipement sont fixes (jamais en dés) et s'ajoutent toujours aux jets. La plupart sont physiques ; certains objets portent aussi des bonus magiques @@ -117,6 +142,19 @@ function treasuresRender() { html += "

"; } + html += `

✨ Templates de drop (${templates.length})

+

Suffixes à la MountyHall ajoutés aux objets qui tombent dans le + monde partagé : un objet reçoit jusqu'à 3 templates (6 pour une arme à + 2 mains), chacun tiré au hasard selon une probabilité réglable sur la page admin. Leurs + bonus s'ajoutent à ceux de l'objet (le mod TOUR est en minutes de DLA), et leur + nom s'accole à celui de l'objet (« Épée Courte de l'Aigle des Mages »). + Valeurs lues dans la base de référence (modifiables côté admin).

`; + if (templates.length) { + html += `
${templates.map(templateCard).join("")}
`; + } else { + html += `

Liste indisponible (base non joignable).

`; + } + html += `

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é ici comme un tirage au sort entre 2D3 et 4D3.

`; @@ -129,7 +167,7 @@ let treasuresReturnTo = "create"; // 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 // pu) charger → repli sur les valeurs statiques du code. -let GEAR_DB = null, POTIONS_DB = null, SCROLLS_DB = null; +let GEAR_DB = null, POTIONS_DB = null, SCROLLS_DB = null, TEMPLATES_DB = null; async function fetchRef(cat) { try { @@ -143,12 +181,13 @@ async function fetchRef(cat) { } async function loadReference() { - const [gear, potions, scrolls] = await Promise.all([ - fetchRef("gear"), fetchRef("potions"), fetchRef("scrolls"), + const [gear, potions, scrolls, templates] = await Promise.all([ + fetchRef("gear"), fetchRef("potions"), fetchRef("scrolls"), fetchRef("templates"), ]); GEAR_DB = gear ? gearBySlotFromRows(gear) : null; POTIONS_DB = potions ? indexPowerById(potions) : null; SCROLLS_DB = scrolls ? indexPowerById(scrolls) : null; + TEMPLATES_DB = templates; } function gearBySlotFromRows(rows) { @@ -184,7 +223,7 @@ async function treasuresShow(from) { treasuresReturnTo = from; document.getElementById("screen-" + from).classList.add("hidden"); document.getElementById("screen-treasures").classList.remove("hidden"); - document.getElementById("screen-treasures").scrollTop = 0; + window.scrollTo(0, 0); await loadReference(); treasuresRender(); } @@ -197,6 +236,15 @@ if (typeof document !== "undefined") { document.getElementById("screen-treasures").classList.add("hidden"); document.getElementById("screen-" + treasuresReturnTo).classList.remove("hidden"); }; + // Bouton « remonter en haut » : visible dès qu'on a un peu défilé. + const topBtn = document.getElementById("tz-top"); + if (topBtn) { + topBtn.onclick = () => window.scrollTo({ top: 0, behavior: "smooth" }); + window.addEventListener("scroll", () => { + const onTz = !document.getElementById("screen-treasures").classList.contains("hidden"); + topBtn.classList.toggle("hidden", !onTz || window.scrollY < 400); + }); + } if (new URLSearchParams(location.search).get("screen") === "treasures") { treasuresShow("create"); }