From 6c031aa381d30b6d159f2d083855d1163e84eee4 Mon Sep 17 00:00:00 2001 From: Michele Rossi Date: Wed, 8 Apr 2026 08:18:10 +0200 Subject: [PATCH] Improve prestige --- core/prestige/README.md | 46 +++++------ core/prestige/prestige_manager.gd | 48 +++++++++++ core/prestige/prestige_panel.gd | 1 + core/prestige/prestige_panel.tscn | 45 ++++++----- core/prestige/prestige_progress_bar.gd | 92 ++++++++++++++++++++++ core/prestige/prestige_progress_bar.gd.uid | 1 + core/prestige/prestige_progress_bar.tscn | 22 ++++++ 7 files changed, 212 insertions(+), 43 deletions(-) create mode 100644 core/prestige/prestige_progress_bar.gd create mode 100644 core/prestige/prestige_progress_bar.gd.uid create mode 100644 core/prestige/prestige_progress_bar.tscn diff --git a/core/prestige/README.md b/core/prestige/README.md index 48b8779..9042721 100644 --- a/core/prestige/README.md +++ b/core/prestige/README.md @@ -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 } } ``` diff --git a/core/prestige/prestige_manager.gd b/core/prestige/prestige_manager.gd index c5ab3bb..a6ceea2 100644 --- a/core/prestige/prestige_manager.gd +++ b/core/prestige/prestige_manager.gd @@ -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: diff --git a/core/prestige/prestige_panel.gd b/core/prestige/prestige_panel.gd index 2994d04..ebb497a 100644 --- a/core/prestige/prestige_panel.gd +++ b/core/prestige/prestige_panel.gd @@ -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 diff --git a/core/prestige/prestige_panel.tscn b/core/prestige/prestige_panel.tscn index 57aecd1..01fbe87 100644 --- a/core/prestige/prestige_panel.tscn +++ b/core/prestige/prestige_panel.tscn @@ -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?" diff --git a/core/prestige/prestige_progress_bar.gd b/core/prestige/prestige_progress_bar.gd new file mode 100644 index 0000000..b1bcbd6 --- /dev/null +++ b/core/prestige/prestige_progress_bar.gd @@ -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)) diff --git a/core/prestige/prestige_progress_bar.gd.uid b/core/prestige/prestige_progress_bar.gd.uid new file mode 100644 index 0000000..0b9e974 --- /dev/null +++ b/core/prestige/prestige_progress_bar.gd.uid @@ -0,0 +1 @@ +uid://dsq8yix7kkyaj diff --git a/core/prestige/prestige_progress_bar.tscn b/core/prestige/prestige_progress_bar.tscn new file mode 100644 index 0000000..f10dfd3 --- /dev/null +++ b/core/prestige/prestige_progress_bar.tscn @@ -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"