feat: content expansion, prestige shop, and offline earnings improvements

- Expand content to 18 zones, 72 bosses, 95 quests, 32 adventurer tiers
- Add prestige shop with 24 runestone upgrades across 5 categories
- Add PrestigeUpgrade type, data files, API routes, and frontend panel
- Fix offline earnings to include equipment and runestone multipliers
- Add offline essence calculation alongside offline gold
- Update OfflineModal to display both gold and essence earned
- Add IDEAS.md for tracking planned features
This commit is contained in:
2026-03-06 21:55:42 -08:00
committed by Naomi Carrigan
parent 6bc116a86a
commit 5b4661b398
23 changed files with 2288 additions and 91 deletions
+33 -12
View File
@@ -3,21 +3,32 @@ import type { GameState } from "@elysium/types";
const MAX_OFFLINE_SECONDS = 8 * 60 * 60; // 8 hours
/**
* Calculates the gold earned whilst the player was offline.
* Calculates the gold and essence earned whilst the player was offline.
* Capped at 8 hours to prevent exploit via system clock manipulation.
* Applies the same multipliers as the client-side tick engine.
*/
export const calculateOfflineGold = (
export const calculateOfflineEarnings = (
state: GameState,
nowMs: number,
): { offlineGold: number; offlineSeconds: number } => {
): { offlineGold: number; offlineEssence: number; offlineSeconds: number } => {
const elapsedSeconds = Math.min(
(nowMs - state.lastTickAt) / 1000,
MAX_OFFLINE_SECONDS,
);
const goldPerSecond = state.adventurers.reduce((total, adventurer) => {
const equipmentGoldMultiplier = (state.equipment ?? [])
.filter((e) => e.equipped)
.reduce((mult, e) => mult * (e.bonus.goldMultiplier ?? 1), 1);
const runestonesIncome = state.prestige.runestonesIncomeMultiplier ?? 1;
const runestonesEssence = state.prestige.runestonesEssenceMultiplier ?? 1;
let goldPerSecond = 0;
let essencePerSecond = 0;
for (const adventurer of state.adventurers) {
if (!adventurer.unlocked || adventurer.count === 0) {
return total;
continue;
}
const upgradeMultiplier = state.upgrades
@@ -29,17 +40,27 @@ export const calculateOfflineGold = (
)
.reduce((mult, u) => mult * u.multiplier, 1);
return (
total +
const prestige = state.prestige.productionMultiplier;
goldPerSecond +=
adventurer.goldPerSecond *
adventurer.count *
upgradeMultiplier *
state.prestige.productionMultiplier
);
}, 0);
adventurer.count *
upgradeMultiplier *
prestige *
runestonesIncome *
equipmentGoldMultiplier;
essencePerSecond +=
adventurer.essencePerSecond *
adventurer.count *
upgradeMultiplier *
prestige *
runestonesEssence;
}
return {
offlineGold: goldPerSecond * elapsedSeconds,
offlineEssence: essencePerSecond * elapsedSeconds,
offlineSeconds: elapsedSeconds,
};
};