Add docs
This commit is contained in:
244
core/prestige/README.md
Normal file
244
core/prestige/README.md
Normal file
@@ -0,0 +1,244 @@
|
||||
# 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
|
||||
RUN_TOTAL, # Currency this run
|
||||
RUN_MAX # Peak currency this run
|
||||
}
|
||||
|
||||
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
|
||||
@export var basis: BasisType = LIFETIME_TOTAL
|
||||
@export var formula: FormulaType = POWER
|
||||
|
||||
# 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
|
||||
```
|
||||
|
||||
### 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
|
||||
4. `GameState.reset_for_prestige()` called:
|
||||
- Current currencies reset to 0
|
||||
- Generator states cleared
|
||||
- Buff levels reset to 0
|
||||
- Goal completion cleared
|
||||
- Lifetime totals preserved
|
||||
5. Generators reinitialized
|
||||
6. 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 = "Lifetime Total (1.50e6 Magic)"
|
||||
```
|
||||
|
||||
### 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:
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- `core/game_state.gd` - State persistence
|
||||
- `generator/currency_generator.gd` - Multiplier application
|
||||
- `core/big_number.gd` - Large number math
|
||||
Reference in New Issue
Block a user