fix: apply cbrt and cap to runestone formula to prevent AFK windfalls
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m3s
CI / Lint, Build & Test (pull_request) Successful in 1m10s

This commit is contained in:
2026-03-24 20:01:22 -07:00
committed by Naomi Carrigan
parent 9926e7f639
commit 959b86fa8b
2 changed files with 27 additions and 10 deletions
+15 -4
View File
@@ -20,6 +20,13 @@ const runestonesPerPrestigeLevel = 10;
const milestoneInterval = 5;
const milestoneRunestonesPerInterval = 25;
/*
* Hard cap on the base runestone yield (before multipliers) to prevent
* extreme AFK accumulation from producing game-breaking runestone counts.
* With all upgrades (5.625× max) this caps out at ~281 per prestige.
*/
const maxBaseRunestones = 50;
/**
* Calculates the gold threshold required for the next prestige.
* Formula: BASE * SCALE_FACTOR^prestigeCount — each prestige makes the next threshold harder.
@@ -107,7 +114,9 @@ interface RunestoneParameters {
/**
* Calculates how many runestones the player earns from a prestige.
* Formula: floor(sqrt(totalGoldEarned / threshold)) * RUNESTONES_PER_PRESTIGE_LEVEL * runestoneMultiplier.
* Formula: min(floor(cbrt(totalGoldEarned / threshold)) * RUNESTONES_PER_PRESTIGE_LEVEL, MAX_BASE) * multipliers.
* Uses cube root for stronger diminishing returns than sqrt, and caps the base before multipliers
* to prevent extended AFK sessions from producing runestone windfalls.
* @param parameters - The parameters for the runestone calculation.
* @param parameters.totalGoldEarned - The total gold earned in the current run.
* @param parameters.prestigeCount - The current prestige count.
@@ -123,9 +132,11 @@ const calculateRunestones = (parameters: RunestoneParameters): number => {
echoRunestoneMultiplier = 1,
} = parameters;
const threshold = calculatePrestigeThreshold(prestigeCount);
const base
= Math.floor(Math.sqrt(totalGoldEarned / threshold))
* runestonesPerPrestigeLevel;
const base = Math.min(
Math.floor(Math.cbrt(totalGoldEarned / threshold))
* runestonesPerPrestigeLevel,
maxBaseRunestones,
);
const runestoneMult = getCategoryMultiplier(
purchasedUpgradeIds,
"runestones",