v2.4.2 : fiche du troll harmonisée solo/multi (panneau a onglets)
Le mode multi reprend exactement le panneau a onglets « Caracteristiques /
Effets » du solo : meme structure HTML, badge du nombre d'effets, et
l'onglet Effets passe par renderEffectsPanel (cartes buff/malus + total)
au lieu de la liste simplifiee. switchLeftTab generalise avec un prefixe
("" solo / "mp-" multi) ; le serveur renvoie potionEffects complets pour
alimenter le total des modificateurs. Reste seule la difference de fond
Tour (solo) vs DLA temps reel (multi).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -234,6 +234,15 @@ non affilié au jeu original de Mountyhall SARL.
|
|||||||
|
|
||||||
## Versions
|
## Versions
|
||||||
|
|
||||||
|
- **2.4.2** (2026-06-13) — **Fiche du troll harmonisée** entre le solo et le
|
||||||
|
monde partagé : le mode multi adopte le même **panneau à onglets**
|
||||||
|
« Caractéristiques / Effets » que le solo (avec le badge du nombre d'effets
|
||||||
|
actifs), et son onglet Effets utilise désormais le **même rendu**
|
||||||
|
(cartes buff/malus + « Total des modificateurs ») au lieu de la liste
|
||||||
|
simplifiée d'avant. Les deux modes partagent désormais strictement le même
|
||||||
|
code d'affichage (`fmtStatLine`, `renderEffectsPanel`, `switchLeftTab`) ;
|
||||||
|
seule subsiste la différence de fond entre les modes (compteur de **Tour**
|
||||||
|
en solo, compte à rebours **DLA** en temps réel en multi).
|
||||||
- **2.4.1** (2026-06-13) — Fiche du troll du monde partagé : les **bonus
|
- **2.4.1** (2026-06-13) — Fiche du troll du monde partagé : les **bonus
|
||||||
physiques et magiques** de chaque caractéristique (attaque, esquive, dégâts,
|
physiques et magiques** de chaque caractéristique (attaque, esquive, dégâts,
|
||||||
régénération) sont désormais **toujours détaillés** (`phy +X · mag +Y`),
|
régénération) sont désormais **toujours détaillés** (`phy +X · mag +Y`),
|
||||||
|
|||||||
+12
-5
@@ -159,11 +159,18 @@
|
|||||||
<div id="layout">
|
<div id="layout">
|
||||||
<aside id="panel-left">
|
<aside id="panel-left">
|
||||||
<h2 id="mp-troll-title"></h2>
|
<h2 id="mp-troll-title"></h2>
|
||||||
<div id="mp-stats"></div>
|
<div class="panel-tabs" role="tablist">
|
||||||
<h3>S'améliorer (PI)</h3>
|
<button type="button" id="mp-tab-stats" class="panel-tab active" role="tab" aria-selected="true">Caractéristiques</button>
|
||||||
<div id="mp-improve"></div>
|
<button type="button" id="mp-tab-effects" class="panel-tab" role="tab" aria-selected="false">Effets <span id="mp-fx-badge" class="fx-badge hidden"></span></button>
|
||||||
<h3>Effets actifs</h3>
|
</div>
|
||||||
<div id="mp-effects"></div>
|
<div id="mp-panel-tab-stats" role="tabpanel">
|
||||||
|
<div id="mp-stats"></div>
|
||||||
|
<h3>S'améliorer (PI)</h3>
|
||||||
|
<div id="mp-improve"></div>
|
||||||
|
</div>
|
||||||
|
<div id="mp-panel-tab-effects" class="hidden" role="tabpanel">
|
||||||
|
<div id="mp-effects"></div>
|
||||||
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
<main id="panel-center">
|
<main id="panel-center">
|
||||||
<canvas id="mp-map" width="960" height="672"></canvas>
|
<canvas id="mp-map" width="960" height="672"></canvas>
|
||||||
|
|||||||
+6
-4
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const APP_VERSION = "2.4.1";
|
const APP_VERSION = "2.4.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;
|
||||||
@@ -1532,10 +1532,12 @@ function showEnd(victory, killer) {
|
|||||||
let selectedRace = "Skrim";
|
let selectedRace = "Skrim";
|
||||||
let activeLeftTab = "stats";
|
let activeLeftTab = "stats";
|
||||||
|
|
||||||
function switchLeftTab(tab) {
|
// `prefix` = "" pour le solo, "mp-" pour le monde partagé : les deux modes
|
||||||
|
// partagent strictement le même panneau à onglets (Caractéristiques / Effets).
|
||||||
|
function switchLeftTab(tab, prefix = "") {
|
||||||
activeLeftTab = tab;
|
activeLeftTab = tab;
|
||||||
const statsBtn = $("tab-stats"), fxBtn = $("tab-effects");
|
const statsBtn = $(prefix + "tab-stats"), fxBtn = $(prefix + "tab-effects");
|
||||||
const statsPanel = $("panel-tab-stats"), fxPanel = $("panel-tab-effects");
|
const statsPanel = $(prefix + "panel-tab-stats"), fxPanel = $(prefix + "panel-tab-effects");
|
||||||
if (!statsBtn || !fxBtn) return;
|
if (!statsBtn || !fxBtn) return;
|
||||||
const isStats = tab === "stats";
|
const isStats = tab === "stats";
|
||||||
statsBtn.classList.toggle("active", isStats);
|
statsBtn.classList.toggle("active", isStats);
|
||||||
|
|||||||
+15
-4
@@ -100,6 +100,7 @@ function mpShowJoin(show) {
|
|||||||
async function mpEnter() {
|
async function mpEnter() {
|
||||||
document.getElementById("screen-create").classList.add("hidden");
|
document.getElementById("screen-create").classList.add("hidden");
|
||||||
document.getElementById("screen-mp").classList.remove("hidden");
|
document.getElementById("screen-mp").classList.remove("hidden");
|
||||||
|
switchLeftTab("stats", "mp-"); // ouvrir sur les caractéristiques
|
||||||
MP.seen = new Set();
|
MP.seen = new Set();
|
||||||
try {
|
try {
|
||||||
const saved = mpLoadIdentity();
|
const saved = mpLoadIdentity();
|
||||||
@@ -292,10 +293,16 @@ function mpRenderPanels(st) {
|
|||||||
improve.appendChild(btn);
|
improve.appendChild(btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
const fx = document.getElementById("mp-effects");
|
// Effets : on réutilise tel quel le panneau du solo (renderEffectsPanel +
|
||||||
fx.innerHTML = you.effects.length
|
// badge), pour que les deux modes soient strictement identiques.
|
||||||
? you.effects.map(ef => `<div class="eq-line">${ef.emoji} ${ef.name} <small>(${ef.turnsLeft} DLA)</small>${ef.modLines.length ? `<div class="eq-mods">${ef.modLines.join(" · ")}</div>` : ""}</div>`).join("")
|
const fxTroll = { potionEffects: you.potionEffects || [], blockCamoTurns: you.blockCamoTurns || 0 };
|
||||||
: '<p class="fx-empty">Aucun bonus ni malus magique actif.</p>';
|
document.getElementById("mp-effects").innerHTML = renderEffectsPanel(fxTroll);
|
||||||
|
const fxBadge = document.getElementById("mp-fx-badge");
|
||||||
|
if (fxBadge) {
|
||||||
|
const n = countActiveEffects(fxTroll);
|
||||||
|
fxBadge.textContent = n;
|
||||||
|
fxBadge.classList.toggle("hidden", n === 0);
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById("mp-pa-bar").textContent = "⚡".repeat(you.pa) + "▫️".repeat(Math.max(0, 6 - you.pa));
|
document.getElementById("mp-pa-bar").textContent = "⚡".repeat(you.pa) + "▫️".repeat(Math.max(0, 6 - you.pa));
|
||||||
|
|
||||||
@@ -362,6 +369,10 @@ if (typeof document !== "undefined") {
|
|||||||
document.getElementById("mp-join-create").onclick = () => mpJoinSubmit(false);
|
document.getElementById("mp-join-create").onclick = () => mpJoinSubmit(false);
|
||||||
document.getElementById("mp-join-login").onclick = () => mpJoinSubmit(true);
|
document.getElementById("mp-join-login").onclick = () => mpJoinSubmit(true);
|
||||||
|
|
||||||
|
// Onglets « Caractéristiques / Effets » — même mécanique que le solo
|
||||||
|
document.getElementById("mp-tab-stats")?.addEventListener("click", () => switchLeftTab("stats", "mp-"));
|
||||||
|
document.getElementById("mp-tab-effects")?.addEventListener("click", () => switchLeftTab("effects", "mp-"));
|
||||||
|
|
||||||
document.addEventListener("keydown", e => {
|
document.addEventListener("keydown", e => {
|
||||||
if (document.getElementById("screen-mp").classList.contains("hidden")) return;
|
if (document.getElementById("screen-mp").classList.contains("hidden")) return;
|
||||||
const k = e.key.toLowerCase();
|
const k = e.key.toLowerCase();
|
||||||
|
|||||||
@@ -810,7 +810,9 @@ function stateFor(world, t, now = Date.now()) {
|
|||||||
comp: { pct: t.comp.pct }, sort: { pct: t.sort.pct },
|
comp: { pct: t.comp.pct }, sort: { pct: t.sort.pct },
|
||||||
eff: te,
|
eff: te,
|
||||||
equip: t.equip, bag: t.bag,
|
equip: t.equip, bag: t.bag,
|
||||||
effects: (t.potionEffects || []).map(e => ({ name: e.name, emoji: e.emoji, turnsLeft: e.turnsLeft, modLines: e.modLines || [] })),
|
// effets bruts : le client réutilise renderEffectsPanel() du solo,
|
||||||
|
// qui a besoin des modificateurs chiffrés (total) en plus des modLines.
|
||||||
|
potionEffects: (t.potionEffects || []).map(e => ({ ...e, modLines: e.modLines || [] })),
|
||||||
blockCamoTurns: t.blockCamoTurns,
|
blockCamoTurns: t.blockCamoTurns,
|
||||||
},
|
},
|
||||||
trolls: Object.values(world.trolls)
|
trolls: Object.values(world.trolls)
|
||||||
|
|||||||
Reference in New Issue
Block a user