8.9 KiB
8.9 KiB
Prestige System - Technical Specification
Document Status
- Version: 1.0
- Date: 2026-03-21
- Scope: Add a configurable prestige reset loop with editor-authored curve math and permanent run multipliers.
Problem Statement
The prototype currently has growth, buffs, and unlock goals, but no reset loop that converts late-run progress into long-term power. Without prestige, the economy has no designed "ladder climb" cycle and balancing eventually relies only on direct cost/production tuning.
Design Goals
- Support a prestige reset that grants a permanent currency based on player progress.
- Keep prestige math data-driven and editable in the Godot inspector for balancing iteration.
- Support both major prestige archetypes from Kongregate's analysis:
- Lifetime or max-stat based curves (diminishing gains when resetting at the same point repeatedly).
- Since-reset/run-only curves (same run depth gives similar rewards each reset).
- Integrate with existing systems (
GameState,BigNumber, generator/buff runtime) without hardcoding one formula. - Persist all prestige state in
user://idle_save.jsonalongside existing runtime data.
Non-Goals (For First Iteration)
- Multiple prestige currencies.
- Prestige skill tree/shop UI.
- Offline simulation changes beyond applying the resulting permanent multiplier.
Kongregate-Informed Curve Model
From "The Math of Idle Games, Part III", prestige formulas can be modeled as transformed progress stats with fractional exponents.
Core variables:
delta_p: prestige currency gained on reset.p: total prestige currency owned.c_L: lifetime currency earned.c_M: max currency reached in a run.c_R: currency earned since last reset.
Supported formula families for this system:
- Power curve (generic):
f(x) = scale * (x / threshold)^exponent. - Triangular inverse sqrt (Realm Grinder style): solve
x = threshold * p(p+1)/2forp. - Log-like compression (future option, disabled by default).
Behavior groups:
- Cumulative-stat formulas (
c_L,c_M) compute target total prestige then granttarget_total - current_total. - Run-only formulas (
c_R) compute direct gain per run.
Proposed Runtime Architecture
- Add
PrestigeManagerautoload (core/prestige/prestige_manager.gd) as the single authority for prestige state and reset flow. - Add
PrestigeConfigresource (core/prestige/prestige_config.gd) authored in inspector and loaded from data assets. GameStateremains owner of currencies/generator state;PrestigeManagerorchestrates reset and applies permanent multiplier.- Generators read the active prestige multiplier through one accessor (
PrestigeManager.get_total_multiplier()), then multiply existingrun_multiplierbehavior.
Data Model
PrestigeConfig (Resource)
Editor-authored resource fields (all exported):
id: StringName.display_name: String.prestige_currency_id: StringName(logical id, not regular wallet currency).source_currency_id: StringName(which gameplay currency powers prestige calculation).basis: BasisTypeenum:LIFETIME_TOTALRUN_TOTALRUN_MAX
formula: FormulaTypeenum:POWERTRIANGULAR_INVERSE
threshold_mantissa: floatandthreshold_exponent: int(BigNumber-like threshold).scale: float.exponent: float(used byPOWER).flat_bonus: float.minimum_gain: int.rounding_mode: RoundingModeenum (FLOOR,ROUND,CEIL).allow_prestige_without_gain: bool.- Multiplier tuning:
multiplier_mode: MultiplierModeenum (ADDITIVE,MULTIPLICATIVE_POWER).base_multiplier: float.multiplier_per_prestige: float.multiplier_exponent: float.
Prestige Runtime State
Persisted by PrestigeManager:
total_prestige_earned: BigNumber.current_prestige_unspent: BigNumber.prestige_resets_count: int.run_start_total_source_currency: BigNumber.run_peak_source_currency: BigNumber.last_reset_time: int.
Formula Specification
1) Basis Value Extraction
Given configured source_currency_id:
LIFETIME_TOTAL:basis_value = GameState.get_total_currency_acquired_by_id(source_currency_id).RUN_TOTAL:basis_value = lifetime_now - run_start_total_source_currency.RUN_MAX:basis_value = run_peak_source_currency.
2) Raw Gain
- POWER:
raw = scale * pow(basis_value / threshold, exponent) + flat_bonus. - TRIANGULAR_INVERSE:
k = basis_value / thresholdtarget = (sqrt(1 + 8k) - 1) / 2- if basis is cumulative (
LIFETIME_TOTAL,RUN_MAXinterpreted as cumulative target),raw = target - total_prestige_earned - if basis is run-only,
raw = target
3) Post-Processing
- Clamp negative to zero.
- Apply configured rounding.
- Enforce
minimum_gainwhen basis passed threshold and gain > 0.
4) Multiplier Application
get_total_multiplier() returns one of:
- Additive mode:
base_multiplier + total_prestige_earned * multiplier_per_prestige. - Multiplicative power mode:
base_multiplier * pow(1 + multiplier_per_prestige, pow(total_prestige_earned, multiplier_exponent)).
Implementation note: compute large-number powers via log10 transforms against BigNumber to avoid float overflow.
Reset Flow
- Player presses prestige button.
PrestigeManager.calculate_pending_gain()computes gain from configured curve.- If gain is zero and
allow_prestige_without_gainis false, block reset. - On confirm:
- Add gain to
total_prestige_earnedandcurrent_prestige_unspent. - Increment
prestige_resets_count. - Reset runtime progression (
GameStatecurrencies, generator owned counts, generator availability that should restart locked). - Preserve permanent unlocks only if explicitly marked as persistent in future extensions.
- Reinitialize run-tracking values (
run_start_total_source_currency,run_peak_source_currency). - Emit
prestige_performed(gain, total_prestige)signal.
- Add gain to
GameState Integration
- Add APIs for reset-safe state initialization (single call from
PrestigeManagerinstead of duplicating clear logic). - Keep total-acquired currency behavior explicit:
- Option A (recommended): reset current currencies and generator ownership, keep lifetime totals for
LIFETIME_TOTALbasis. - Option B: clear totals too and rely on dedicated lifetime accumulator in prestige state.
- Option A (recommended): reset current currencies and generator ownership, keep lifetime totals for
- Ensure generator/buff registrations are idempotent after reset (
_ensure_registeredpaths already support this pattern).
Editor Authoring And Balancing Workflow
- Create
idles/prestige/primary_prestige.tresusingPrestigeConfig. - Designers tune only exported fields in inspector (no code edits).
- Provide presets matching Kongregate article examples:
- Realm Grinder-like:
basis=RUN_MAX,formula=TRIANGULAR_INVERSE,threshold=1e12. - AdCap-like:
basis=LIFETIME_TOTAL,formula=POWER,scale=150,threshold=1e15,exponent=0.5. - Cookie Clicker-like:
basis=LIFETIME_TOTAL,formula=POWER,threshold=1e12,exponent=0.333333. - Egg Inc-like:
basis=RUN_TOTAL,formula=POWER,threshold=1e6,exponent=0.14.
- Realm Grinder-like:
- Balance target guidance:
- For sqrt-like curves, doubling prestige generally needs roughly 3x-4x deeper runs.
- For cube-root curves, doubling prestige tends toward ~8x deeper runs.
- For ~1/7 exponent run curves, doubling prestige needs ~128x deeper runs.
UI Requirements
- Prestige panel must display:
- current prestige total
- pending gain (
delta_p) - resulting multiplier after reset
- basis stat currently used (
c_L,c_R, orc_Mequivalent)
- Reset CTA disabled when pending gain is zero and config disallows zero-gain resets.
- Confirmation dialog explicitly lists what resets and what is kept.
Persistence
- Extend save payload with
prestige_stateobject. - Serialize all
BigNumbervalues with existingBigNumber.serialize()pattern. - During load, validate dictionaries and apply defaults if fields are missing.
- Maintain backward compatibility with pre-prestige saves by creating default prestige state when absent.
Validation Plan
- Headless parse:
"$GODOT_BIN" --headless --path . --quit. - Script checks once implemented:
"$GODOT_BIN" --headless --check-only --script res://core/prestige/prestige_manager.gd"$GODOT_BIN" --headless --check-only --script res://core/prestige/prestige_config.gd
- Manual smoke cases:
- same reset point in cumulative mode yields reduced/zero incremental gain.
- same reset point in run-only mode yields roughly same gain.
- multiplier updates production immediately after reset.
- prestige state survives save/load.
Implementation Milestones
- Introduce data classes (
PrestigeConfig) and one authored.tresprofile. - Implement
PrestigeManagerwith gain math + persistence. - Add reset integration entrypoint in
GameState. - Wire generator production multiplier to prestige.
- Add initial prestige UI panel and confirmation flow.