Improve prestige
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?"
|
||||
|
||||
92
core/prestige/prestige_progress_bar.gd
Normal file
92
core/prestige/prestige_progress_bar.gd
Normal 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))
|
||||
1
core/prestige/prestige_progress_bar.gd.uid
Normal file
1
core/prestige/prestige_progress_bar.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dsq8yix7kkyaj
|
||||
22
core/prestige/prestige_progress_bar.tscn
Normal file
22
core/prestige/prestige_progress_bar.tscn
Normal 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"
|
||||
Reference in New Issue
Block a user