diff --git a/assets/img/cards/medusa.png b/assets/img/cards/medusa.png new file mode 100644 index 0000000..e736fef Binary files /dev/null and b/assets/img/cards/medusa.png differ diff --git a/public/game.html b/public/game.html index 49ce036..17e36ae 100644 --- a/public/game.html +++ b/public/game.html @@ -46,6 +46,20 @@ #log { display: none; } + /* effects feed for user-facing logs (card plays) */ + #effectsFeed { + max-height: 140px; + overflow: auto; + padding: 8px; + background: #fff; + border: 1px solid #eee; + border-radius: 6px; + font-size: 14px; + color: #222; + } + #log { + display: none; + } @@ -139,10 +153,14 @@ logs... -
-
Activité
-
- Aucune activité pour l'instant. +
+
+
Activité
+
Aucune activité pour l'instant.
+
+
+
Effets actifs
+
Aucun effet actif pour l'instant.
@@ -183,6 +201,54 @@ logs... e && e.type === "brouillard", + ); + if (!effects || !effects.length) { + dest.textContent = "Aucun effet actif pour l'instant."; + return; + } + dest.innerHTML = ""; + effects.forEach((e) => { + try { + const row = document.createElement("div"); + row.style.padding = "4px 6px"; + row.style.borderBottom = "1px solid #f3f3f3"; + const rem = typeof e.remainingTurns !== "undefined" ? e.remainingTurns : "?"; + row.textContent = `${e.title} — ${rem+1} tour(s) restant(s)`; + dest.appendChild(row); + } catch (_) {} + }); + } catch (_) {} + } + // Apply a local visual tick when any player plays a card or moves. + // This updates the displayed remainingTurns immediately for UX, but + // does not replace server authority — incoming card:effect:updated or + // room:update will resync the true values. + function applyLocalPlayTick() { + try { + let changed = false; + Object.keys(activeEffects).forEach((id) => { + try { + const e = activeEffects[id]; + if (e && typeof e.remainingTurns === "number") { + // decrement visually by one (but never below zero) + e.remainingTurns = Math.max(0, (e.remainingTurns || 0) - 1); + changed = true; + } + } catch (_) {} + }); + if (changed) refreshEffectsFeed(); + } catch (_) {} + } const boardEl = document.getElementById("board"); const myColorEl = document.getElementById("myColor"); let socket = null; @@ -490,6 +556,29 @@ logs... { + try { + if (eff && eff.type === "brouillard" && eff.id) { + activeEffects[eff.id] = eff; + seen.add(eff.id); + } + } catch (_) {} + }); + // remove stale brouillard entries not present in server list + Object.keys(activeEffects).forEach((id) => { + try { + if (!seen.has(id) && activeEffects[id] && activeEffects[id].type === "brouillard") { + delete activeEffects[id]; + } + } catch (_) {} + }); + refreshEffectsFeed(); + } + } catch (_) {} try { myMines = data.minesOwn || []; } catch (e) { @@ -564,10 +653,11 @@ logs... { @@ -607,8 +697,6 @@ logs... { + try { + const eff = data && (data.effect || data); + if (!eff || !eff.id) return; + try { + activeEffects[eff.id] = eff; + } catch (_) {} + try { + refreshEffectsFeed(); + } catch (_) {} + } catch (e) { + console.warn("card:effect:updated handler error", e); + } + }); + // toucher / medusa removals socket.on("card:effect:removed", (data) => { try { @@ -763,6 +877,17 @@ logs... { handCounts[p.id] = @@ -440,7 +439,7 @@ function checkAndHandleVictory(room) { function buildDefaultDeck() { const cards = [ [ - 'médusa', + 'Médusa', 'La pièce désignée ne peut plus bouger pendant 4 tours', 'medusa', ], @@ -1841,11 +1840,12 @@ io.on("connection", (socket) => { // Update brouillard play counts try { - room.activeCardEffects = room.activeCardEffects || []; for (let ei = room.activeCardEffects.length - 1; ei >= 0; ei--) { const ev = room.activeCardEffects[ei]; if (!ev || ev.type !== "brouillard") continue; try { + // only consider play-count based expiry if the effect explicitly enabled it + if (!ev.countByPlay) continue; ev.playCounts = ev.playCounts || {}; ev.playCounts[senderId] = (ev.playCounts[senderId] || 0) + 1; try { @@ -4403,20 +4403,18 @@ io.on("connection", (socket) => { } } room.activeCardEffects = room.activeCardEffects || []; - const playCounts = {}; - try { - (room.players || []).forEach((pl) => { - if (pl && pl.id) playCounts[pl.id] = 0; - }); - } catch (_) {} + // legacy: optionally expire brouillard by play-counts. Default: disabled. + const countByPlay = !!(payload && payload.countByPlay); const effect = { id: played.id, + title: "Brouillard de guerre", type: "brouillard", playerId: targetPlayer.id, ts: Date.now(), remainingTurns: (payload && payload.turns) || 6, + decrementOn: "both", veiledSquares: all, - playCounts, + countByPlay, }; room.activeCardEffects.push(effect); try {