generated from nhcarrigan/template
feat: another balance and bug fix pass (#238)
Working through open issues — fixes, balance changes, and features. ## Closed - Closes #161 - Closes #181 - Closes #191 - Closes #199 - Closes #201 - Closes #202 - Closes #203 - Closes #204 - Closes #205 - Closes #206 - Closes #208 - Closes #211 - Closes #212 - Closes #213 - Closes #214 - Closes #216 - Closes #219 - Closes #220 - Closes #221 - Closes #222 - Closes #224 - Closes #225 - Closes #226 - Closes #228 - Closes #229 - Closes #230 - Closes #231 - Closes #232 - Closes #233 - Closes #234 - Closes #235 - Closes #236 ✨ This PR was created with help from Hikari~ 🌸 Reviewed-on: #238 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #238.
This commit is contained in:
@@ -27,12 +27,12 @@ const baseThreshold = 1_000_000;
|
||||
|
||||
/**
|
||||
* Calculates the prestige threshold for a given prestige count.
|
||||
* Mirrors the server formula: BASE * (count + 1)^2.
|
||||
* Mirrors the server formula: BASE * (count + 1)^2.5.
|
||||
* @param prestigeCount - The current prestige count.
|
||||
* @returns The required gold to prestige.
|
||||
*/
|
||||
const calculateThreshold = (prestigeCount: number): number => {
|
||||
return baseThreshold * Math.pow(prestigeCount + 1, 2);
|
||||
return baseThreshold * Math.pow(prestigeCount + 1, 2.5);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -41,7 +41,7 @@ const calculateThreshold = (prestigeCount: number): number => {
|
||||
* @returns The compounding multiplier applied to all income sources.
|
||||
*/
|
||||
const calculateProductionMultiplier = (prestigeCount: number): number => {
|
||||
return Math.pow(1.15, prestigeCount);
|
||||
return Math.pow(1.3, prestigeCount);
|
||||
};
|
||||
|
||||
const categoryOrder: Array<PrestigeUpgradeCategory> = [
|
||||
@@ -61,12 +61,14 @@ const PrestigePanel = (): JSX.Element => {
|
||||
const {
|
||||
state,
|
||||
reloadSilent,
|
||||
formatInteger,
|
||||
formatNumber,
|
||||
buyPrestigeUpgrade,
|
||||
enableNotifications,
|
||||
enableSounds,
|
||||
toggleAutoAdventurer,
|
||||
toggleAutoPrestige,
|
||||
toggleAutoPrestigeMaxRunestones,
|
||||
triggerPrestigeToast,
|
||||
} = useGame();
|
||||
const [ isPending, setIsPending ] = useState(false);
|
||||
@@ -92,6 +94,11 @@ const PrestigePanel = (): JSX.Element => {
|
||||
const isEligible = player.totalGoldEarned >= threshold;
|
||||
const runestonePreview = computeProjectedRunestones(state);
|
||||
const nextMultiplier = calculateProductionMultiplier(prestigeData.count + 1);
|
||||
const baseRunestones = Math.min(
|
||||
Math.floor(Math.cbrt(player.totalGoldEarned / threshold)) * 15,
|
||||
200,
|
||||
);
|
||||
const isAtMaxRunestones = baseRunestones >= 200;
|
||||
|
||||
async function handlePrestige(): Promise<void> {
|
||||
setIsPending(true);
|
||||
@@ -154,6 +161,10 @@ const PrestigePanel = (): JSX.Element => {
|
||||
toggleAutoPrestige();
|
||||
}
|
||||
|
||||
function handleAutoPrestigeMaxRunestonesToggle(): void {
|
||||
toggleAutoPrestigeMaxRunestones();
|
||||
}
|
||||
|
||||
function handlePrestigeTabClick(): void {
|
||||
setActiveTab("prestige");
|
||||
}
|
||||
@@ -187,7 +198,7 @@ const PrestigePanel = (): JSX.Element => {
|
||||
type="button"
|
||||
>
|
||||
{"🔮 Runestone Shop ("}
|
||||
{formatNumber(prestigeData.runestones)}
|
||||
{formatInteger(prestigeData.runestones)}
|
||||
{" stones)"}
|
||||
</button>
|
||||
</div>
|
||||
@@ -198,7 +209,7 @@ const PrestigePanel = (): JSX.Element => {
|
||||
{"Prestige resets your progress but grants "}
|
||||
<strong>{"Runestones"}</strong>
|
||||
{"— permanent currency used for powerful upgrades."}
|
||||
{" Each prestige multiplies your global production by ×1.15"}
|
||||
{" Each prestige multiplies your global production by ×1.3"}
|
||||
{" (compounding each run)."}
|
||||
</p>
|
||||
|
||||
@@ -231,15 +242,25 @@ const PrestigePanel = (): JSX.Element => {
|
||||
</p>
|
||||
<p>
|
||||
{"Runestones: "}
|
||||
<strong>{formatNumber(prestigeData.runestones)}</strong>
|
||||
<strong>{formatInteger(prestigeData.runestones)}</strong>
|
||||
</p>
|
||||
{isEligible
|
||||
? <p className="runestone-preview">
|
||||
{"Runestones on prestige: "}
|
||||
<strong>
|
||||
{"+"}
|
||||
{formatNumber(runestonePreview)}
|
||||
{formatInteger(runestonePreview)}
|
||||
</strong>
|
||||
{isAtMaxRunestones
|
||||
? <span className="runestone-max-badge">{" ⚡ MAX"}</span>
|
||||
: null
|
||||
}
|
||||
</p>
|
||||
: null}
|
||||
{isEligible && !isAtMaxRunestones
|
||||
? <p className="runestone-progress-hint">
|
||||
{"Earn more gold to increase your runestone yield "
|
||||
+ "(capped at ×14³ the prestige threshold)."}
|
||||
</p>
|
||||
: null}
|
||||
{isEligible
|
||||
@@ -268,7 +289,7 @@ const PrestigePanel = (): JSX.Element => {
|
||||
>
|
||||
{isPending
|
||||
? "Ascending..."
|
||||
: `✨ Ascend (+${formatNumber(runestonePreview)} Runestones)`}
|
||||
: `✨ Ascend (+${formatInteger(runestonePreview)} Runestones)`}
|
||||
</button>
|
||||
{prestigeError === null
|
||||
? null
|
||||
@@ -280,12 +301,12 @@ const PrestigePanel = (): JSX.Element => {
|
||||
{"Ascended to Prestige "}
|
||||
{result.count}
|
||||
{"! Earned "}
|
||||
{formatNumber(result.runestones)}
|
||||
{formatInteger(result.runestones)}
|
||||
{" Runestones."}
|
||||
{result.milestoneRunestones > 0
|
||||
&& <>
|
||||
{" 🎉 Milestone bonus: +"}
|
||||
{formatNumber(result.milestoneRunestones)}
|
||||
{formatInteger(result.milestoneRunestones)}
|
||||
{" Runestones!"}
|
||||
</>
|
||||
}
|
||||
@@ -306,7 +327,7 @@ const PrestigePanel = (): JSX.Element => {
|
||||
<p className="shop-balance">
|
||||
{"Balance: "}
|
||||
<strong>
|
||||
{formatNumber(prestigeData.runestones)}
|
||||
{formatInteger(prestigeData.runestones)}
|
||||
{" Runestones"}
|
||||
</strong>
|
||||
</p>
|
||||
@@ -331,6 +352,8 @@ const PrestigePanel = (): JSX.Element => {
|
||||
= upgrade.id === "auto_prestige" && purchased;
|
||||
const autoPrestigeEnabled
|
||||
= prestigeData.autoPrestigeEnabled ?? false;
|
||||
const autoPrestigeMaxRunestonesOnly
|
||||
= prestigeData.autoPrestigeMaxRunestonesOnly ?? false;
|
||||
|
||||
function handleBuyClick(): void {
|
||||
void handleBuyUpgrade(upgrade.id);
|
||||
@@ -358,7 +381,7 @@ const PrestigePanel = (): JSX.Element => {
|
||||
<p className="upgrade-cost">
|
||||
{purchased
|
||||
? "✅ Purchased"
|
||||
: `🔮 ${formatNumber(upgrade.runestonesCost)} Runestones`}
|
||||
: `🔮 ${formatInteger(upgrade.runestonesCost)} Runestones`}
|
||||
</p>
|
||||
</div>
|
||||
{isAutoAdventurerToggle
|
||||
@@ -377,19 +400,37 @@ const PrestigePanel = (): JSX.Element => {
|
||||
</button>
|
||||
: null}
|
||||
{isAutoPrestigeToggle
|
||||
? <button
|
||||
className={`auto-prestige-toggle ${
|
||||
autoPrestigeEnabled
|
||||
? "enabled"
|
||||
: "disabled"
|
||||
}`}
|
||||
onClick={handleAutoPrestigeToggle}
|
||||
type="button"
|
||||
>
|
||||
? <>
|
||||
<button
|
||||
className={`auto-prestige-toggle ${
|
||||
autoPrestigeEnabled
|
||||
? "enabled"
|
||||
: "disabled"
|
||||
}`}
|
||||
onClick={handleAutoPrestigeToggle}
|
||||
type="button"
|
||||
>
|
||||
{autoPrestigeEnabled
|
||||
? "⚡ Auto ON"
|
||||
: "⏸ Auto OFF"}
|
||||
</button>
|
||||
{autoPrestigeEnabled
|
||||
? "⚡ Auto ON"
|
||||
: "⏸ Auto OFF"}
|
||||
</button>
|
||||
? <button
|
||||
className={`auto-prestige-toggle ${
|
||||
autoPrestigeMaxRunestonesOnly
|
||||
? "enabled"
|
||||
: "disabled"
|
||||
}`}
|
||||
onClick={handleAutoPrestigeMaxRunestonesToggle}
|
||||
title="Only fire at max runestone yield"
|
||||
type="button"
|
||||
>
|
||||
{autoPrestigeMaxRunestonesOnly
|
||||
? "⚡ Max Runes Only"
|
||||
: "⏸ Max Runes OFF"}
|
||||
</button>
|
||||
: null}
|
||||
</>
|
||||
: null}
|
||||
{purchased
|
||||
? null
|
||||
|
||||
Reference in New Issue
Block a user