feat: vampire tick engine, auto systems, and full test suite

- vampire blood production tick with thrall bloodPerSecond + multipliers
- auto-quest and auto-thrall purchase in tick engine
- computeVampireBloodPerSecond helper exposed for ResourceBar display
- ResourceBar now shows blood/s and currency balances for vampire mode
- vampire quests and thralls panels gain auto-toggle buttons
- About page updated with vampire mode how-to-play entries
- vampireEquipmentSets data file added to web
- 100% test coverage across all API routes and services:
  - siring, awakening, vampireBoss, vampireCraft, vampireExplore, vampireUpgrade
  - debug route now covers grant-apotheosis endpoint
  - vampireMaterials excluded from coverage (ID-referenced only, same as goddessMaterials)
This commit is contained in:
2026-04-16 14:01:50 -07:00
committed by Naomi Carrigan
parent 1e0a7b142a
commit e02827dbb6
20 changed files with 3660 additions and 10 deletions
@@ -198,7 +198,7 @@ const ThrallCard = ({
* @returns The JSX element.
*/
const VampireThrallsPanel = (): JSX.Element => {
const { state, formatNumber } = useGame();
const { state, formatNumber, toggleVampireAutoThrall } = useGame();
const [ selectedBatch, setSelectedBatch ] = useState<BatchSize>(() => {
return parseBatchSize(localStorage.getItem("elysium_thrall_batch"));
});
@@ -221,7 +221,8 @@ const VampireThrallsPanel = (): JSX.Element => {
}
const blood = state.resources.blood ?? 0;
const { thralls } = vampireState;
const { thralls, autoThrall } = vampireState;
const autoThrallOn = autoThrall === true;
function handleBatchSelect(batch: BatchSize): void {
setSelectedBatch(batch);
@@ -230,7 +231,23 @@ const VampireThrallsPanel = (): JSX.Element => {
return (
<section className="panel disciples-panel">
<h2>{"Thralls"}</h2>
<div className="panel-header">
<h2>{"Thralls"}</h2>
<button
className={`auto-toggle ${autoThrallOn
? "auto-on"
: "auto-off"}`}
onClick={toggleVampireAutoThrall}
title={autoThrallOn
? "Auto-Thrall is ON — click to disable"
: "Auto-Thrall is OFF — click to enable"}
type="button"
>
{autoThrallOn
? "🤖 Auto-Thrall: ON"
: "🤖 Auto-Thrall: OFF"}
</button>
</div>
<div className="disciples-balance">
<span>
{"🩸 Blood: "}