ui/stats-panel.js

import { events } from "../core/events.js";
import { MAX_HEALTH } from "../core/player.js";
import {
  MELEE_WEAPON,
  RANGED_WEAPON,
  AMMUNITION,
  description as flagDescription,
} from "../core/flags.js";

/**
 * Stats panel — keeps the HP bar, HP text, XP, gold, and flags display
 * in sync with the player model via the events bus.
 */
export function initStatsPanel() {
  const hpBarFill = document.getElementById("hp-bar-fill");
  const hpText = document.getElementById("hp-text");
  const flagsEl = document.getElementById("flags-display");
  const weaponEl = document.getElementById("eq-weapon");

  function updateBag(bag) {
    const selected = bag.getSelected();
    if (weaponEl) {
      if (
        selected &&
        (selected.is(MELEE_WEAPON) || selected.is(RANGED_WEAPON))
      ) {
        weaponEl.textContent = selected.name;
      } else {
        weaponEl.textContent = "Empty-handed";
      }
    }
  }

  function update(player) {
    const pct = Math.round((player.health / MAX_HEALTH) * 100);
    if (hpBarFill) {
      hpBarFill.style.width = `${pct}%`;
      // Color the bar: green → yellow → red as health drops
      const hue = Math.round((pct / 100) * 120);
      hpBarFill.style.backgroundColor = `hsl(${hue},80%,40%)`;
    }
    if (hpText) {
      hpText.textContent = `${player.health} / ${MAX_HEALTH}`;
    }
    if (flagsEl) {
      const desc = flagDescription(player.flags);
      flagsEl.textContent = desc || "None";
    }
    updateBag(player.bag);
  }

  events.onPlayerChanged(update);
  events.onFlagsChanged(update);
  events.onInventoryChanged(updateBag);
}