generated from nhcarrigan/template
feat: post-prestige automation (auto-adventurer) (#76)
## 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: #76 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #76.
This commit is contained in:
@@ -447,6 +447,11 @@ interface GameContextValue {
|
||||
*/
|
||||
toggleAutoBoss: ()=> void;
|
||||
|
||||
/**
|
||||
* Toggle the auto-adventurer setting on/off (requires auto_adventurer prestige upgrade).
|
||||
*/
|
||||
toggleAutoAdventurer: ()=> void;
|
||||
|
||||
/**
|
||||
* Queue of newly unlocked codex entry IDs (for toast notifications).
|
||||
*/
|
||||
@@ -1073,6 +1078,42 @@ export const GameProvider = ({
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-adventurer: buy one of the highest-tier affordable unlocked adventurer per tick
|
||||
if (
|
||||
next.autoAdventurer === true
|
||||
&& next.prestige.purchasedUpgradeIds.includes("auto_adventurer")
|
||||
) {
|
||||
const [ bestAdventurer ] = next.adventurers.
|
||||
filter((adventurer) => {
|
||||
const cost
|
||||
= adventurer.baseCost * Math.pow(1.15, adventurer.count);
|
||||
return adventurer.unlocked && next.resources.gold >= cost;
|
||||
}).
|
||||
sort((adventurerA, adventurerB) => {
|
||||
const costA
|
||||
= adventurerA.baseCost * Math.pow(1.15, adventurerA.count);
|
||||
const costB
|
||||
= adventurerB.baseCost * Math.pow(1.15, adventurerB.count);
|
||||
return costB - costA;
|
||||
});
|
||||
if (bestAdventurer !== undefined) {
|
||||
const purchaseCost
|
||||
= bestAdventurer.baseCost * Math.pow(1.15, bestAdventurer.count);
|
||||
next = {
|
||||
...next,
|
||||
adventurers: next.adventurers.map((adventurer) => {
|
||||
return adventurer.id === bestAdventurer.id
|
||||
? { ...adventurer, count: adventurer.count + 1 }
|
||||
: adventurer;
|
||||
}),
|
||||
resources: {
|
||||
...next.resources,
|
||||
gold: next.resources.gold - purchaseCost,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Detect newly unlocked achievements
|
||||
unlockedAchievementsReference.current = next.achievements.filter(
|
||||
(a, index) => {
|
||||
@@ -1858,6 +1899,18 @@ export const GameProvider = ({
|
||||
});
|
||||
}, []);
|
||||
|
||||
const toggleAutoAdventurer = useCallback(() => {
|
||||
setState((previous) => {
|
||||
if (previous === null) {
|
||||
return previous;
|
||||
}
|
||||
return {
|
||||
...previous,
|
||||
autoAdventurer: previous.autoAdventurer !== true,
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
const setActiveCompanion = useCallback((companionId: string | null) => {
|
||||
setState((previous) => {
|
||||
if (previous === null) {
|
||||
@@ -2169,6 +2222,7 @@ export const GameProvider = ({
|
||||
startQuest,
|
||||
state,
|
||||
syncError,
|
||||
toggleAutoAdventurer,
|
||||
toggleAutoBoss,
|
||||
toggleAutoPrestige,
|
||||
toggleAutoQuest,
|
||||
@@ -2240,6 +2294,7 @@ export const GameProvider = ({
|
||||
startQuest,
|
||||
state,
|
||||
syncError,
|
||||
toggleAutoAdventurer,
|
||||
toggleAutoBoss,
|
||||
toggleAutoPrestige,
|
||||
toggleAutoQuest,
|
||||
|
||||
Reference in New Issue
Block a user