6.6 KiB
6.6 KiB
TODO
Ascension Buff Tree — Needs Review Before Implementation
Goal
Add a permanent buff tree system:
- Separate from existing
GeneratorBuffData(which resets on prestige). - Permanent — prestige does NOT reset ascension buff state.
- Unlocked by spending ascension currency (earned during prestige).
- Tree/DAG-structured — nodes have prerequisites (parent_ids) that must be met before a node can be purchased.
- Multi-level — nodes can be one-shot unlocks (
max_level=1) or repeatable upgrades (max_level>1or-1for infinite).
Data Structure
AscensionBuffNode (Resource)
Single node in the tree.
| Field | Type | Notes |
|---|---|---|
id |
StringName |
Unique node ID |
display_name |
String |
UI label |
description |
String (multiline) |
Tooltip |
icon |
Texture2D |
Visual |
parent_ids |
Array[StringName] |
Prerequisites (DAG, not strict tree — multiple parents allowed) |
effect_type |
enum EffectType |
What this buff does |
effect_value |
float |
Base effect magnitude |
effect_per_level |
float |
Extra effect per level beyond first (default 0.0) |
target_id |
StringName |
Target generator/currency for type-specific effects (empty = global) |
cost_mantissa |
float |
Ascension currency cost base |
cost_exponent |
int |
|
cost_multiplier |
float |
Cost scaling per level |
max_level |
int |
How many times it can be upgraded (1 = one-time, -1 = infinite) |
tier |
int |
Row in tree UI (visual grouping) |
x_position |
float |
Column in tree UI |
Effect types (extensible enum):
GLOBAL_PRODUCTION_MULTIPLIER → multiply all generator output
GENERATOR_PRODUCTION_MULTIPLIER → multiply one generator's output
CURRENCY_PER_RUN → start each prestige with this currency
COST_REDUCTION → reduce all generator purchase costs
PRESTIGE_GAIN_MULTIPLIER → earn more ascension currency per prestige
GENERATOR_COUNT_MULTIPLIER → scaling based on owned generator count
RESEARCH_XP_MULTIPLIER → faster research leveling
AscensionBuffCatalogue (Resource)
Flat list of nodes. The tree emerges from parent_ids. Follows existing catalogue pattern (BuffCatalogue, GoalCatalogue, etc.).
| Field | Type |
|---|---|
nodes |
Array[AscensionBuffNode] |
State in LevelGameState
@export var ascension_buff_catalogue: AscensionBuffCatalogue
var _ascension_buff_levels: Dictionary = {} # {StringName: int} — node_id → unlock count
- Never cleared by
reset_for_prestige()(unlike_buff_levelsfor generator buffs, which IS cleared). - Normalized/sanitized on load (like generator states).
Save Format
- Bump
CURRENT_SAVE_FORMAT_VERSIONfrom 7 → 8. - New key:
"ascension_buff_levels"→{ "node_id": level_int, ... }.
API on LevelGameState
| Method | Purpose |
|---|---|
purchase_ascension_buff(buff_id) → bool |
Spend ascension currency, increment level, emit signal, save |
can_purchase_ascension_buff(buff_id) → bool |
All parent_ids met? Under max_level? Enough currency? |
get_ascension_buff_cost(buff_id) → BigNumber |
Cost for the NEXT level (scaled by cost_multiplier) |
get_ascension_buff_level(buff_id) → int |
Current unlock count |
get_ascension_buff_multiplier(effect_type, target_id) → float |
Walk tree, compute combined effect |
get_available_ascension_buffs() → Array[AscensionBuffNode] |
Nodes with prerequisites met |
Signals
signal ascension_buff_changed(buff_id: StringName, new_level: int)
signal ascension_currency_changed(new_unspent: BigNumber)
Prestige Integration
No changes needed to PrestigeManager._reset_all_buff_levels() — it only touches _buff_levels (generator buffs), not _ascension_buff_levels. The new dictionary naturally survives the reset.
Purchase Flow
Player clicks upgrade node
→ can_purchase_ascension_buff(node_id)
→ All parent_ids at required level? (max_level for prerequisite, or just ≥1)
→ Current level < max_level?
→ Enough ascension currency?
→ YES: spend_currency_by_id(ascension_currency, cost)
→ _ascension_buff_levels[node_id] += 1
→ emit ascension_buff_changed
→ save_game()
Example Tree Content (Illustrative)
Tier 0 (roots):
strong_start → +10 gold/run cost: 1 parents: []
efficiency → +10% global prod cost: 1 parents: []
thrifty → -5% gen costs cost: 2 parents: []
Tier 1:
better_start → +100 gold/run cost: 3 parents: [strong_start]
enhanced_efficiency → +25% global prod cost: 3 parents: [efficiency]
double_dip → +50% gold from forestry cost: 5 parents: [strong_start, efficiency]
Tier 2:
power_surge → +100% global prod cost: 10 parents: [better_start, enhanced_efficiency]
Files to Create/Modify
| File | Action | Purpose |
|---|---|---|
core/ascension/ascension_buff_node.gd |
Create | Node resource |
core/ascension/ascension_buff_catalogue.gd |
Create | Catalogue resource |
core/ascension/ascension_buff_tree_panel.gd |
Create | UI panel (or integrate into prestige panel) |
core/level_game_state.gd |
Modify | Add catalogue ref, _ascension_buff_levels, purchase/query methods, save/load, signals |
core/prestige/prestige_manager.gd |
Modify (light) | Emit ascension_currency_changed on spend/earn |
docs/gyms/tiny_sword/ascension/*.tres |
Create | .tres resources for actual tree content |
Open Questions for Review
- Prerequisite level requirement: Should a parent need to be at
max_level, or is level 1 sufficient? (Leaning:max_levelis required, otherwise the tree loses structural meaning.) - Effect stacking: For
GLOBAL_PRODUCTION_MULTIPLIER, should separate nodes multiply together or add? (Leaning: multiply — consistent with the existing generator buff multiplier pattern.) - UI placement: Should the tree panel be a tab in the prestige panel, a separate screen, or inlined somewhere?
- Ascension currency unspent tracking: Currently
PrestigeManager.current_prestige_unspenttracks unspent prestige currency. Should the buff tree consume from this directly, or should ascension currency be a properCurrencyin the catalogue that the tree spends viaLevelGameState.spend_currency_by_id()? (Leaning: usespend_currency_by_id()for consistency — ascension currency is already added to the currency catalogue.) - Content: What actual buffs and tree shape should the first version ship with?