From 3d114f63d7f5a320b4c1c8c63dd0c2a97f31fefd Mon Sep 17 00:00:00 2001
From: Hikari
Date: Thu, 19 Mar 2026 13:38:25 -0700
Subject: [PATCH] feat: post-prestige automation (auto-adventurer) (#76)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
Closes #61
- Adds the **Autonomous Recruitment** prestige upgrade (50 runestones) to both the API and web data files
- Adds `autoAdventurer?: boolean` to the `GameState` type for backwards-compatible saves
- Adds tick-loop logic in GameContext that automatically purchases the highest-tier unlocked adventurer the player can afford each frame when the toggle is enabled
- Adds `toggleAutoAdventurer` callback and exposes it through the context
- Adds toggle UI in the Prestige Shop (mirrors the existing Auto-Prestige toggle pattern)
- Updates the How to Play guide in the About panel to document the new automation feature
✨ This issue was created with help from Hikari~ 🌸
Reviewed-on: https://git.nhcarrigan.com/nhcarrigan/elysium/pulls/76
Co-authored-by: Hikari
Co-committed-by: Hikari
---
apps/api/src/data/prestigeUpgrades.ts | 9 +++
apps/web/src/components/game/aboutPanel.tsx | 18 +++---
.../web/src/components/game/prestigePanel.tsx | 25 ++++++++-
apps/web/src/context/gameContext.tsx | 55 +++++++++++++++++++
apps/web/src/data/prestigeUpgrades.ts | 9 +++
packages/types/src/interfaces/gameState.ts | 5 ++
6 files changed, 112 insertions(+), 9 deletions(-)
diff --git a/apps/api/src/data/prestigeUpgrades.ts b/apps/api/src/data/prestigeUpgrades.ts
index 48524df..3d8c047 100644
--- a/apps/api/src/data/prestigeUpgrades.ts
+++ b/apps/api/src/data/prestigeUpgrades.ts
@@ -210,6 +210,15 @@ export const defaultPrestigeUpgrades: Array = [
runestonesCost: 1200,
},
// ── Utility Unlocks ───────────────────────────────────────────────────────
+ {
+ category: "utility",
+ description:
+ "Unlock the Auto-Adventurer toggle. When enabled, the tick engine will automatically purchase the highest-tier adventurer you can currently afford.",
+ id: "auto_adventurer",
+ multiplier: 1,
+ name: "Autonomous Recruitment",
+ runestonesCost: 50,
+ },
{
category: "utility",
description:
diff --git a/apps/web/src/components/game/aboutPanel.tsx b/apps/web/src/components/game/aboutPanel.tsx
index 8b63dfb..c159b37 100644
--- a/apps/web/src/components/game/aboutPanel.tsx
+++ b/apps/web/src/components/game/aboutPanel.tsx
@@ -188,14 +188,16 @@ const howToPlay = [
},
{
body:
- "Toggle automation in the Quests and Boss Encounters panels! Auto-Quest"
- + " automatically sends your party on the highest-zone available quest"
- + " as soon as one completes, skipping quests whose combat power"
- + " requirement isn't met. Auto-Boss automatically challenges the"
- + " highest available boss as soon as one is ready. Both can be toggled"
- + " on or off at any time using the 🤖 Auto button in each panel"
- + " header.",
- title: "🤖 Auto-Quest & Auto-Boss",
+ "Toggle automation in the Quests, Boss Encounters, and Prestige Shop"
+ + " panels! Auto-Quest automatically sends your party on the"
+ + " highest-zone available quest as soon as one completes, skipping"
+ + " quests whose combat power requirement isn't met. Auto-Boss"
+ + " automatically challenges the highest available boss as soon as one"
+ + " is ready. Auto-Adventurer (unlocked via the Prestige Shop for 50"
+ + " runestones) automatically purchases the highest-tier adventurer you"
+ + " can currently afford each tick, keeping your income growing after a"
+ + " prestige without any manual clicks.",
+ title: "🤖 Auto-Quest, Auto-Boss & Auto-Adventurer",
},
{
body:
diff --git a/apps/web/src/components/game/prestigePanel.tsx b/apps/web/src/components/game/prestigePanel.tsx
index 8bfdf0f..9addb63 100644
--- a/apps/web/src/components/game/prestigePanel.tsx
+++ b/apps/web/src/components/game/prestigePanel.tsx
@@ -89,6 +89,7 @@ const PrestigePanel = (): JSX.Element => {
buyPrestigeUpgrade,
enableNotifications,
enableSounds,
+ toggleAutoAdventurer,
toggleAutoPrestige,
triggerPrestigeToast,
} = useGame();
@@ -110,7 +111,7 @@ const PrestigePanel = (): JSX.Element => {
);
}
- const { prestige: prestigeData, player } = state;
+ const { autoAdventurer, prestige: prestigeData, player } = state;
const threshold = calculateThreshold(prestigeData.count);
const isEligible = player.totalGoldEarned >= threshold;
const runestonePreview = calculateRunestonePreview(
@@ -173,6 +174,10 @@ const PrestigePanel = (): JSX.Element => {
void handlePrestige();
}
+ function handleAutoAdventurerToggle(): void {
+ toggleAutoAdventurer();
+ }
+
function handleAutoPrestigeToggle(): void {
toggleAutoPrestige();
}
@@ -347,6 +352,9 @@ const PrestigePanel = (): JSX.Element => {
= prestigeData.runestones >= upgrade.runestonesCost;
const isLoading = buyingId === upgrade.id;
+ const isAutoAdventurerToggle
+ = upgrade.id === "auto_adventurer" && purchased;
+ const autoAdventurerEnabled = autoAdventurer ?? false;
const isAutoPrestigeToggle
= upgrade.id === "auto_prestige" && purchased;
const autoPrestigeEnabled
@@ -381,6 +389,21 @@ const PrestigePanel = (): JSX.Element => {
: `🔮 ${formatNumber(upgrade.runestonesCost)} Runestones`}
+ {isAutoAdventurerToggle
+ ?
+ : null}
{isAutoPrestigeToggle
?