Files
elysium/apps/api/src/services/offlineProgress.ts
T
hikari 5b4661b398 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
2026-03-06 21:55:42 -08:00

67 lines
1.9 KiB
TypeScript

import type { GameState } from "@elysium/types";
const MAX_OFFLINE_SECONDS = 8 * 60 * 60; // 8 hours
/**
* 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 calculateOfflineEarnings = (
state: GameState,
nowMs: number,
): { offlineGold: number; offlineEssence: number; offlineSeconds: number } => {
const elapsedSeconds = Math.min(
(nowMs - state.lastTickAt) / 1000,
MAX_OFFLINE_SECONDS,
);
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) {
continue;
}
const upgradeMultiplier = state.upgrades
.filter(
(u) =>
u.purchased &&
(u.target === "global" ||
(u.target === "adventurer" && u.adventurerId === adventurer.id)),
)
.reduce((mult, u) => mult * u.multiplier, 1);
const prestige = state.prestige.productionMultiplier;
goldPerSecond +=
adventurer.goldPerSecond *
adventurer.count *
upgradeMultiplier *
prestige *
runestonesIncome *
equipmentGoldMultiplier;
essencePerSecond +=
adventurer.essencePerSecond *
adventurer.count *
upgradeMultiplier *
prestige *
runestonesEssence;
}
return {
offlineGold: goldPerSecond * elapsedSeconds,
offlineEssence: essencePerSecond * elapsedSeconds,
offlineSeconds: elapsedSeconds,
};
};