Improve prestige

This commit is contained in:
2026-04-08 08:18:10 +02:00
parent ee374a3d74
commit 6c031aa381
7 changed files with 212 additions and 43 deletions

View File

@@ -21,8 +21,8 @@ PrestigeManager (autoload node)
├── Calculates pending gain
├── Applies multipliers to generators
└── PrestigePanel (UI)
├── Shows current/pending prestige
└── Trigger reset button
├── Shows current/pending prestige
└── Trigger reset button
```
## PrestigeConfig
@@ -33,23 +33,23 @@ Resource defining prestige rules.
```gdscript
enum BasisType {
LIFETIME_TOTAL, # All-time currency acquired
RUN_TOTAL, # Currency this run
RUN_MAX # Peak currency this run
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
POWER, # gain = scale * (ratio^exponent)
TRIANGULAR_INVERSE # gain based on triangular number inverse
}
enum RoundingMode {
FLOOR, ROUND, CEIL
FLOOR, ROUND, CEIL
}
enum MultiplierMode {
ADDITIVE, # +X per prestige
MULTIPLICATIVE_POWER # x^(multiplier_per_prestige)
ADDITIVE, # +X per prestige
MULTIPLICATIVE_POWER # x^(multiplier_per_prestige)
}
```
@@ -119,7 +119,7 @@ raw_gain = scale * (ratio^exponent) + flat_bonus
# Cumulative basis subtracts already earned
if basis == LIFETIME_TOTAL:
gain = raw_gain - total_prestige_earned
gain = raw_gain - total_prestige_earned
```
**Triangular Inverse Formula**:
@@ -129,7 +129,7 @@ k = basis_value / threshold
target_total = (sqrt(1 + 8k) - 1) * 0.5
if basis == LIFETIME_TOTAL:
gain = target_total - total_prestige_earned
gain = target_total - total_prestige_earned
```
### Multiplier Application
@@ -185,13 +185,13 @@ Generators apply prestige multipliers automatically:
```gdscript
func get_effective_auto_run_multiplier() -> float:
return run_multiplier * buff_multiplier * _get_prestige_multiplier()
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
var manager = get_node_or_null("/root/PrestigeManager")
if manager:
return manager.get_total_multiplier()
return 1.0
```
## Save Integration
@@ -201,12 +201,12 @@ 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
"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
}
}
```

View File

@@ -2,6 +2,7 @@ extends Node
signal prestige_state_changed(total_prestige: BigNumber, pending_gain: BigNumber)
signal prestige_performed(gain: BigNumber, total_prestige: BigNumber)
signal prestige_threshold_changed(next_threshold: BigNumber)
const SAVE_KEY: String = "prestige_state"
const TOTAL_PRESTIGE_KEY: String = "total_prestige_earned"
@@ -48,6 +49,10 @@ func _ready() -> void:
GameState.currency_changed.connect(_on_currency_changed)
prestige_state_changed.emit(get_total_prestige(), calculate_pending_gain())
prestige_threshold_changed.emit(get_next_prestige_threshold())
func get_config() -> Resource:
return config
func get_source_currency_id() -> StringName:
if not _is_config_valid():
@@ -138,10 +143,24 @@ func perform_prestige() -> bool:
GameState.save_game()
var total: BigNumber = get_total_prestige()
var next_threshold: BigNumber = get_next_prestige_threshold()
prestige_performed.emit(gain, total)
prestige_state_changed.emit(total, calculate_pending_gain())
prestige_threshold_changed.emit(next_threshold)
return true
func get_next_prestige_threshold() -> BigNumber:
if not _is_config_valid():
return BigNumber.from_float(0.0)
match _get_config_int("basis", BASIS_LIFETIME_TOTAL):
BASIS_RUN_TOTAL:
return _get_config_threshold()
_:
var current_total: float = _big_number_to_float(total_prestige_earned)
var next_target: float = _calculate_target_for_prestige(current_total + 1.0)
return BigNumber.from_float(next_target)
func get_basis_value_for_display() -> BigNumber:
return _get_basis_value()
@@ -171,7 +190,36 @@ func _on_currency_changed(changed_currency_id: StringName, new_amount: BigNumber
run_peak_source_currency = _copy_big_number(new_amount)
_save_state_to_game_state()
var next_threshold: BigNumber = get_next_prestige_threshold()
prestige_state_changed.emit(get_total_prestige(), calculate_pending_gain())
prestige_threshold_changed.emit(next_threshold)
func _calculate_target_for_prestige(prestige_level: float) -> float:
if config == null:
return 0.0
var threshold_value: float = _big_number_to_float(_get_config_threshold())
if threshold_value <= 0.0:
return 0.0
match _get_config_int("formula", FORMULA_POWER):
FORMULA_TRIANGULAR_INVERSE:
var target_total: float = prestige_level
var k: float = target_total * (target_total + 1.0) * 0.5
return k * threshold_value
_:
var scale: float = maxf(_get_config_float("scale", 1.0), 0.0001)
var exponent: float = maxf(_get_config_float("exponent", 1.0), 0.0001)
var flat_bonus: float = _get_config_float("flat_bonus", 0.0)
if scale <= 0.0:
scale = 0.0001
if exponent <= 0.0:
exponent = 0.0001
var ratio: float = pow((prestige_level - flat_bonus) / scale, 1.0 / exponent)
if ratio <= 0.0:
return threshold_value
return ratio * threshold_value
func _calculate_raw_gain_float(basis_value: BigNumber) -> float:
if config == null:

View File

@@ -5,6 +5,7 @@ extends PanelContainer
@onready var _pending_value: Label = $MarginContainer/VBoxContainer/StatsGrid/PendingValue
@onready var _multiplier_value: Label = $MarginContainer/VBoxContainer/StatsGrid/MultiplierValue
@onready var _basis_label: Label = $MarginContainer/VBoxContainer/StatsGrid/BasisValue
@onready var _progress_bar: Node = $MarginContainer/VBoxContainer/PrestigeProgressBar
@onready var _reset_button: Button = $MarginContainer/VBoxContainer/Buttons/ResetButton
@onready var _save_button: Button = $MarginContainer/VBoxContainer/Buttons/SaveButton
@onready var _confirm_dialog: ConfirmationDialog = $ConfirmDialog

View File

@@ -1,76 +1,81 @@
[gd_scene load_steps=2 format=3]
[gd_scene format=3 uid="uid://dlidx2x0otpjg"]
[ext_resource type="Script" path="res://core/prestige/prestige_panel.gd" id="1_7fdwq"]
[ext_resource type="Script" uid="uid://dmsmmgtbrul1t" path="res://core/prestige/prestige_panel.gd" id="1_panel"]
[ext_resource type="PackedScene" path="res://core/prestige/prestige_progress_bar.tscn" id="2_7b6yg"]
[node name="PrestigePanel" type="PanelContainer"]
[node name="PrestigePanel" type="PanelContainer" unique_id=789062217]
offset_right = 420.0
offset_bottom = 206.0
script = ExtResource("1_7fdwq")
script = ExtResource("1_panel")
[node name="MarginContainer" type="MarginContainer" parent="."]
[node name="MarginContainer" type="MarginContainer" parent="." unique_id=1133221945]
layout_mode = 2
theme_override_constants/margin_left = 10
theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 10
theme_override_constants/margin_bottom = 10
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer" unique_id=1014101412]
layout_mode = 2
theme_override_constants/separation = 8
[node name="Title" type="Label" parent="MarginContainer/VBoxContainer"]
[node name="Title" type="Label" parent="MarginContainer/VBoxContainer" unique_id=738033951]
layout_mode = 2
text = "Prestige"
[node name="StatsGrid" type="GridContainer" parent="MarginContainer/VBoxContainer"]
[node name="StatsGrid" type="GridContainer" parent="MarginContainer/VBoxContainer" unique_id=1121463897]
layout_mode = 2
columns = 2
[node name="TotalTitle" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid"]
[node name="TotalTitle" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid" unique_id=1462148351]
layout_mode = 2
text = "Total"
[node name="TotalValue" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid"]
[node name="TotalValue" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid" unique_id=1607797034]
layout_mode = 2
text = "0"
[node name="PendingTitle" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid"]
[node name="PendingTitle" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid" unique_id=1999999111]
layout_mode = 2
text = "Pending"
[node name="PendingValue" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid"]
[node name="PendingValue" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid" unique_id=1731674897]
layout_mode = 2
text = "0"
[node name="MultiplierTitle" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid"]
[node name="MultiplierTitle" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid" unique_id=1338227256]
layout_mode = 2
text = "Multiplier"
[node name="MultiplierValue" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid"]
[node name="MultiplierValue" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid" unique_id=1407185183]
layout_mode = 2
text = "x1.00"
[node name="BasisTitle" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid"]
[node name="BasisTitle" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid" unique_id=1092652344]
layout_mode = 2
text = "Basis"
[node name="BasisValue" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid"]
[node name="BasisValue" type="Label" parent="MarginContainer/VBoxContainer/StatsGrid" unique_id=1421212102]
layout_mode = 2
text = "-"
[node name="Buttons" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
[node name="PrestigeProgressBar" parent="MarginContainer/VBoxContainer" unique_id=619882824 instance=ExtResource("2_7b6yg")]
layout_mode = 2
[node name="Buttons" type="HBoxContainer" parent="MarginContainer/VBoxContainer" unique_id=634533362]
layout_mode = 2
theme_override_constants/separation = 8
[node name="ResetButton" type="Button" parent="MarginContainer/VBoxContainer/Buttons"]
[node name="ResetButton" type="Button" parent="MarginContainer/VBoxContainer/Buttons" unique_id=379577642]
layout_mode = 2
text = "Prestige Reset"
[node name="SaveButton" type="Button" parent="MarginContainer/VBoxContainer/Buttons"]
[node name="SaveButton" type="Button" parent="MarginContainer/VBoxContainer/Buttons" unique_id=1151017798]
layout_mode = 2
text = "Save"
[node name="ConfirmDialog" type="ConfirmationDialog" parent="."]
[node name="ConfirmDialog" type="ConfirmationDialog" parent="." unique_id=1893210048]
oversampling_override = 1.0
title = "Prestige Reset"
ok_button_text = "Prestige"
dialog_text = "Reset this run?"

View File

@@ -0,0 +1,92 @@
extends HBoxContainer
@export var config: PrestigeConfig
@onready var _label_start = $LabelStart
@onready var _label_end = $LabelEnd
@onready var _progress_bar = $ProgressBar
var _basis_value: BigNumber
var _next_threshold: BigNumber
var _manager: Node
var _connected: bool = false
func _ready() -> void:
_manager = get_node_or_null("/root/PrestigeManager")
if _manager == null:
push_warning("PrestigeProgressBar '%s' cannot find PrestigeManager; progress bar disabled." % String(name))
visible = false
return
if not _manager.has_signal("prestige_state_changed"):
push_warning("PrestigeManager does not have 'prestige_state_changed' signal; progress bar will not update.")
visible = false
return
if config == null:
if _manager.has_method("get_config"):
config = _manager.get_config()
if config == null:
push_warning("PrestigeProgressBar '%s' has no config; progress bar disabled." % String(name))
visible = false
return
if _manager.has_signal("prestige_threshold_changed"):
_manager.prestige_threshold_changed.connect(_on_prestige_threshold_changed)
_manager.prestige_state_changed.connect(_on_prestige_state_changed)
_connected = true
_update_progress()
func _on_prestige_state_changed(_total: BigNumber, _pending: BigNumber) -> void:
_update_progress()
func _on_prestige_threshold_changed(_threshold: BigNumber) -> void:
_update_progress()
func _update_progress() -> void:
if not _connected:
return
if _manager == null or config == null:
return
_basis_value = _manager.call("get_basis_value_for_display")
if _manager.has_method("get_next_prestige_threshold"):
_next_threshold = _manager.call("get_next_prestige_threshold")
else:
_next_threshold = _get_threshold_from_config()
var basis_float: float = _big_number_to_float(_basis_value)
var threshold_float: float = _big_number_to_float(_next_threshold)
if threshold_float > 0.0 and basis_float >= 0.0:
var ratio: float = minf(basis_float / threshold_float, 1.0)
_progress_bar.value = ratio * 100.0
else:
_progress_bar.value = 0.0
_label_start.text = _basis_value.to_string_suffix(2)
_label_end.text = _next_threshold.to_string_suffix(2)
func _get_threshold_from_config() -> BigNumber:
if config == null:
return BigNumber.from_float(0.0)
if not config.has_method("get_threshold"):
return BigNumber.from_float(0.0)
var threshold = config.call("get_threshold")
if threshold is BigNumber:
return threshold
return BigNumber.from_float(0.0)
func _big_number_to_float(value: BigNumber) -> float:
if value.mantissa <= 0.0:
return 0.0
if value.exponent > 308:
return INF
if value.exponent < -308:
return 0.0
return value.mantissa * pow(10.0, float(value.exponent))

View File

@@ -0,0 +1 @@
uid://dsq8yix7kkyaj

View File

@@ -0,0 +1,22 @@
[gd_scene format=3]
[ext_resource type="Script" path="res://core/prestige/prestige_progress_bar.gd" id="1_pbg"]
[node name="PrestigeProgressBar" type="HBoxContainer"]
offset_right = 298.0
offset_bottom = 49.0
alignment = 1
script = ExtResource("1_pbg")
[node name="LabelStart" type="Label" parent="."]
layout_mode = 2
text = "0"
[node name="ProgressBar" type="ProgressBar" parent="."]
custom_minimum_size = Vector2(200, 0)
layout_mode = 2
show_percentage = true
[node name="LabelEnd" type="Label" parent="."]
layout_mode = 2
text = "0"