118 lines
3.7 KiB
JavaScript
118 lines
3.7 KiB
JavaScript
import { getCard } from "./cards.js";
|
|
import { resolveEnemyAction } from "./enemies.js";
|
|
|
|
export function render(state) {
|
|
renderEnemy(state);
|
|
renderInfoBar(state);
|
|
renderHand(state);
|
|
renderOverlay(state);
|
|
}
|
|
|
|
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}`);
|
|
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) {
|
|
const overlay = document.getElementById("overlay");
|
|
const result = state.combat.phase === "ended" ? state.combat.result : null;
|
|
if (result === "victory") {
|
|
overlay.hidden = false;
|
|
overlay.textContent = "victory";
|
|
} else if (result === "defeat") {
|
|
overlay.hidden = false;
|
|
overlay.textContent = "defeat";
|
|
} else {
|
|
overlay.hidden = true;
|
|
}
|
|
}
|