# Prestige Module Documentation ## Overview The `prestige/` subfolder implements the rebirth/reset system. Players can reset progress in exchange for a permanent multiplier that accelerates future runs. ## Files | File | Purpose | |------|---------| | `prestige_config.gd` | Configuration resource for prestige rules | | `prestige_manager.gd` | Core logic and state management | | `prestige_panel.gd` | UI panel for prestige interaction | | `TECH_SPEC.md` | Detailed technical specification | ## Architecture ``` PrestigeManager (autoload node) ├── Tracks prestige currency ├── Calculates pending gain ├── Applies multipliers to generators └── PrestigePanel (UI) ├── Shows current/pending prestige └── Trigger reset button ``` ## PrestigeConfig Resource defining prestige rules. ### Enums ```gdscript enum BasisType { LIFETIME_TOTAL, # All-time currency acquired (single currency) RUN_TOTAL, # Currency this run (single currency) RUN_MAX, # Peak currency this run (single currency) ALL_CURRENCIES # Sum of all currencies (multi-currency tracking) } enum FormulaType { POWER, # gain = scale * (ratio^exponent) TRIANGULAR_INVERSE # gain based on triangular number inverse } enum RoundingMode { FLOOR, ROUND, CEIL } enum MultiplierMode { ADDITIVE, # +X per prestige MULTIPLICATIVE_POWER # x^(multiplier_per_prestige) } ``` ### Key Properties ```gdscript @export var id: StringName = &"primary" @export var display_name: String = "Ascension" @export var prestige_currency_id: StringName = &"prestige" @export var source_currency_id: StringName = &"magic" # What to measure (ignored for ALL_CURRENCIES) @export var basis: BasisType = LIFETIME_TOTAL @export var formula: FormulaType = POWER # Currency tracking @export var include_currency_ids: Array[StringName] = [] # Empty = all currencies (for ALL_CURRENCIES basis) # Threshold: minimum source currency needed @export var threshold_mantissa: float = 1.0 @export var threshold_exponent: int = 4 # 1e4 = 10,000 # Formula parameters @export var scale: float = 1.0 @export var exponent: float = 0.5 # Square root # Multiplier growth @export var multiplier_per_prestige: float = 0.05 # +5% per prestige @export var multiplier_mode: MultiplierMode = ADDITIVE ``` ## PrestigeManager Autoload node managing prestige state. ### Signals ```gdscript signal prestige_state_changed(total_prestige, pending_gain) signal prestige_performed(gain, total_prestige) ``` ### State Variables ```gdscript var total_prestige_earned: BigNumber # Lifetime prestige var current_prestige_unspent: BigNumber # Available to spend var prestige_resets_count: int # How many resets var run_start_total_source_currency: BigNumber # Track run start var run_peak_source_currency: BigNumber # Peak this run ``` ### Key Methods ```gdscript # Query state func get_total_prestige() -> BigNumber func calculate_pending_gain() -> BigNumber func can_prestige() -> bool func get_total_multiplier() -> float # Perform prestige func perform_prestige() -> bool ``` ### Gain Calculation **Power Formula** (default): ```gdscript ratio = basis_value / threshold raw_gain = scale * (ratio^exponent) + flat_bonus # Cumulative basis subtracts already earned if basis == LIFETIME_TOTAL: gain = raw_gain - total_prestige_earned ``` **Triangular Inverse Formula**: ```gdscript # Based on inverse triangular number: n = (sqrt(1 + 8k) - 1) / 2 k = basis_value / threshold target_total = (sqrt(1 + 8k) - 1) * 0.5 if basis == LIFETIME_TOTAL: gain = target_total - total_prestige_earned ``` **Basis Value Calculation**: ```gdscript if basis == ALL_CURRENCIES: # Sum of all tracked currencies basis_value = sum(get_total_currency_acquired(currency_id) for currency_id in tracked_currencies) elif basis == RUN_TOTAL: # Currency earned since last reset basis_value = lifetime_total - run_start_total elif basis == RUN_MAX: # Peak currency reached this run basis_value = run_peak_currency else: # LIFETIME_TOTAL # All-time currency acquired basis_value = lifetime_total ``` ### Multiplier Application **Additive Mode**: ```gdscript multiplier = base_multiplier + (total_prestige * multiplier_per_prestige) # e.g., 1.0 + (5 * 0.05) = 1.25 (25% bonus) ``` **Multiplicative Power Mode**: ```gdscript growth_base = 1.0 + multiplier_per_prestige multiplier = base_multiplier * (growth_base ^ total_prestige) # e.g., 1.0 * (1.05 ^ 5) = 1.276 (27.6% bonus) ``` ### Prestige Reset Flow 1. Player clicks "Prestige" button 2. `perform_prestige()` called 3. Gain calculated and added to total: - For ALL_CURRENCIES: sum of all tracked currencies is used - For single-currency: source currency is used 4. `GameState.reset_for_prestige()` called: - Current currencies reset to 0 - Generator states cleared - Buff levels reset to 0 - Goal completion cleared and re-initialized - Lifetime totals preserved 5. Run tracking reinitialized: - For ALL_CURRENCIES: sum of all currencies at reset time - For single-currency: source currency at reset time 6. Generators reinitialized 7. Save triggered ## PrestigePanel UI component for prestige interaction. ### Displays ```gdscript _total_value.text = "123.45" # Total prestige earned _pending_value.text = "56.78" # Gain available now _multiplier_value.text = "x2.34" # Current multiplier _basis_label.text = "Total Currency (1.50e6)" # For ALL_CURRENCIES basis # Or: "Lifetime Total (1.50e6 Magic)" # For LIFETIME_TOTAL basis ``` ### Buttons - **Reset**: Triggers `perform_prestige()` after confirmation - **Save**: Manually saves game state ## Integration with Generators Generators apply prestige multipliers automatically: ```gdscript func get_effective_auto_run_multiplier() -> float: return run_multiplier * buff_multiplier * _get_prestige_multiplier() func _get_prestige_multiplier() -> float: var manager = get_node_or_null("/root/PrestigeManager") if manager: return manager.get_total_multiplier() return 1.0 ``` ## Save Integration Prestige state stored in `GameState` external save: ```json { "prestige": { "total_prestige_earned": {"m": 10.0, "e": 0}, "current_prestige_unspent": {"m": 5.0, "e": 0}, "prestige_resets_count": 3, "run_start_total_source_currency": {"m": 1000.0, "e": 0}, "run_peak_source_currency": {"m": 5000.0, "e": 0}, "last_reset_time": 1234567890 } } ``` ## Configuration Example For a typical idle game with single currency: ```gdscript # Primary prestige currency id = &"primary" display_name = "Ascension" source_currency_id = &"magic" # Based on lifetime total of Magic currency basis = LIFETIME_TOTAL # Need 1e6 Magic to get first prestige threshold_mantissa = 1.0 threshold_exponent = 6 # Square root scaling (diminishing returns) formula = POWER exponent = 0.5 # +10% multiplier per prestige point multiplier_mode = ADDITIVE multiplier_per_prestige = 0.10 ``` For multi-currency tracking (ALL_CURRENCIES): ```gdscript id = &"ascension" display_name = "Ascension" prestige_currency_id = &"ascension" # Track sum of ALL currencies (gold + wood + food + etc.) basis = ALL_CURRENCIES # Empty include_currency_ids means all currencies from catalog # Set specific IDs to track only those: include_currency_ids = [&"gold", &"wood"] include_currency_ids = [] # Need 1e4 total currency sum to get first prestige threshold_mantissa = 1.0 threshold_exponent = 4 # Square root scaling formula = POWER exponent = 0.5 # +5% multiplier per prestige point multiplier_mode = ADDITIVE multiplier_per_prestige = 0.05 ``` ## See Also - `core/level_game_state.gd` - State persistence - `core/generator/currency_generator.gd` - Multiplier application - `core/big_number.gd` - Large number math