141 lines
4.6 KiB
JavaScript
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;
|
|
}
|
|
}
|