slaywithfriends/src/render.js

141 lines
4.6 KiB
JavaScript

import { getCard } from "./cards.js";
import { resolveEnemyAction } from "./enemies.js";
export function render(state, revealed) {
renderEnemy(state);
renderInfoBar(state);
renderHand(state);
renderOverlay(state, revealed);
}
function renderEnemy(state) {
const { enemy, combat } = state;
document.getElementById("enemy-name").textContent = enemy.name;
document.getElementById("enemy-hp").textContent =
`${enemy.hp}/${enemy.maxHp}`;
document.getElementById("enemy-hp").style.width =
`${(enemy.hp / enemy.maxHp) * 100}%`;
document.getElementById("enemy-block").textContent =
enemy.block > 0 ? `block: ${enemy.block}` : "";
const statusEl = document.getElementById("enemy-status");
const tokens = [];
if (enemy.vulnerable > 0) tokens.push(`vuln ${enemy.vulnerable}`);
if (enemy.weak > 0) tokens.push(`weak ${enemy.weak}`);
if (enemy.strength > 0) tokens.push(`str ${enemy.strength}`);
if (enemy.poison > 0) tokens.push(`psn ${enemy.poison}`);
statusEl.textContent = tokens.join(" | ");
const intentEl = document.getElementById("enemy-intent");
if (combat.dieResult && combat.phase === "player_turn") {
const action = resolveEnemyAction(
enemy,
combat.dieResult,
enemy.trackPosition,
);
if (action) {
intentEl.textContent = formatIntent(action, enemy);
}
} else {
intentEl.textContent = "";
}
}
function formatIntent(action, enemy) {
if (!action?.effects) return "?";
const parts = action.effects.map((e) => {
if (e.type === "hit") {
const damage = e.value + (enemy.strength || 0);
return `attack ${damage}`;
}
if (e.type === "block") return `block ${e.value}`;
if (e.type === "strength") return `str +${e.value}`;
return e.type;
});
return parts.join(", ");
}
function renderInfoBar(state) {
const { player } = state;
document.getElementById("energy").textContent =
`energy: ${player.energy}/${player.maxEnergy}`;
document.getElementById("player-hp").textContent =
`${player.hp}/${player.maxHp}`;
document.getElementById("player-hp").style.width =
`${(player.hp / player.maxHp) * 100}%`;
document.getElementById("player-block").textContent =
player.block > 0 ? `block: ${player.block}` : "";
document.getElementById("player-strength").textContent =
player.strength > 0 ? `str: ${player.strength}` : "";
const playerStatus = document.getElementById("player-status");
if (playerStatus) {
const tokens = [];
if (player.vulnerable > 0) tokens.push(`vuln ${player.vulnerable}`);
if (player.weak > 0) tokens.push(`weak ${player.weak}`);
playerStatus.textContent = tokens.join(" | ");
}
document.getElementById("draw-count").textContent = player.drawPile.length;
document.getElementById("discard-count").textContent =
player.discardPile.length;
}
function renderHand(state) {
const handEl = document.getElementById("hand");
const { player, combat } = state;
handEl.innerHTML = "";
player.hand.forEach((cardId, index) => {
const card = getCard(cardId);
const img = document.createElement("img");
img.src = card.image || "";
img.alt = `${card.name} (${card.cost})`;
img.title = card.description;
img.className = "card";
img.dataset.index = index;
if (index === combat.selectedCard) {
img.classList.add("selected");
}
if (player.energy < card.cost) {
img.classList.add("no-energy");
}
handEl.appendChild(img);
});
}
function renderOverlay(state, revealed) {
const overlay = document.getElementById("overlay");
const overlayText = document.getElementById("overlay-text");
const rewardCards = document.getElementById("reward-cards");
const skipBtn = document.getElementById("skip-btn");
if (state.combat.phase === "rewards" && revealed) {
overlay.hidden = false;
overlayText.textContent = "card reward";
rewardCards.innerHTML = "";
for (const cardId of revealed) {
const card = getCard(cardId);
const img = document.createElement("img");
img.src = card.image || "";
img.alt = card.name;
img.title = `${card.name} (${card.cost}) - ${card.description}`;
img.dataset.cardId = cardId;
img.className = "reward-card";
rewardCards.appendChild(img);
}
skipBtn.hidden = false;
} else if (state.combat.phase === "ended") {
overlay.hidden = false;
overlayText.textContent =
state.combat.result === "defeat"
? "defeat — click to restart"
: "victory";
rewardCards.innerHTML = "";
skipBtn.hidden = true;
} else {
overlay.hidden = true;
rewardCards.innerHTML = "";
skipBtn.hidden = true;
}
}