systems rework: buffs, prestige graph, research, modular architecture
Decouples core systems from centralized globals in favor of catalogue-based architecture and data-driven content. Key changes: - Prestige: node-based buff tech tree, graph panel, progress bar - Research: multi-worker system, per-generator research, xp generation - Ascension: meta-currency layer via multi-currency prestige resets - Buffs: refactored as generator-independent via catalogues - UI: currency panel, edge-scrolling camera + zoom, current-goal panel - Alchemy Tower: crafting building with recipe/cost system - Testing: 7 test suites (ascension, prestige, research, goals) - Content: migrated from hardcoded idles/ to gym format (tiny_sword)
This commit was merged in pull request #1.
This commit is contained in:
167
core/generator/generator_container.gd
Normal file
167
core/generator/generator_container.gd
Normal file
@@ -0,0 +1,167 @@
|
||||
class_name GeneratorPanel
|
||||
extends Container
|
||||
|
||||
const GENERATOR_BUFF_TILE_SCENE: PackedScene = preload("res://generator_buff_tile.tscn")
|
||||
|
||||
class BuffRow extends RefCounted:
|
||||
var buff: GeneratorBuffData
|
||||
var tile: GeneratorBuffTile
|
||||
|
||||
func _init(row_buff: GeneratorBuffData, row_tile: GeneratorBuffTile) -> void:
|
||||
buff = row_buff
|
||||
tile = row_tile
|
||||
|
||||
@export var _generator: CurrencyGenerator
|
||||
|
||||
@onready var _buy_button: Button = $PanelContainer/VBoxContainer/HBoxContainerGenerators/BuyOneButton
|
||||
@onready var _buy_max_button: Button = $PanelContainer/VBoxContainer/HBoxContainerGenerators/BuyMaxButton
|
||||
@onready var _name_label: Label = $PanelContainer/VBoxContainer/Label
|
||||
@onready var _owned_value: Label = $PanelContainer/VBoxContainer/GeneratorStatsGrid/OwnedValue
|
||||
@onready var _next_cost_value: Label = $PanelContainer/VBoxContainer/GeneratorStatsGrid/NextCostValue
|
||||
@onready var _production_value: Label = $PanelContainer/VBoxContainer/GeneratorStatsGrid/ProductionValue
|
||||
@onready var _buffs_section: VBoxContainer = $PanelContainer/VBoxContainer/BuffsSection
|
||||
@onready var _buffs_list: VBoxContainer = $PanelContainer/VBoxContainer/BuffsSection/BuffsList
|
||||
|
||||
var _buff_rows: Array[BuffRow] = []
|
||||
var _generator_id: StringName = &""
|
||||
|
||||
func _ready() -> void:
|
||||
if _generator == null:
|
||||
push_warning("GeneratorContainer '%s' has no generator assigned." % String(name))
|
||||
return
|
||||
|
||||
_generator_id = _generator.get_generator_id()
|
||||
|
||||
_generator.purchase_completed.connect(_on_generator_updated)
|
||||
_generator.production_tick.connect(_on_generator_updated)
|
||||
_generator.purchase_failed.connect(_on_generator_updated)
|
||||
_generator.buff_purchased.connect(_on_generator_updated)
|
||||
_generator.buff_purchase_failed.connect(_on_generator_updated)
|
||||
|
||||
if _generator.game_state:
|
||||
_generator.game_state.currency_changed.connect(_on_currency_changed)
|
||||
_generator.game_state.generator_state_changed.connect(_on_generator_state_changed)
|
||||
|
||||
_name_label.text = _generator.data.name if _generator.data != null else "Generator"
|
||||
_build_buff_rows()
|
||||
_refresh_generator_ui()
|
||||
|
||||
func _on_buy_pressed() -> void:
|
||||
_generator.buy(1)
|
||||
_refresh_generator_ui()
|
||||
|
||||
func _on_buy_max_pressed() -> void:
|
||||
_generator.buy_max()
|
||||
_refresh_generator_ui()
|
||||
|
||||
func _on_debug_income_pressed() -> void:
|
||||
_generator.grant_currency(BigNumber.from_float(100.0))
|
||||
_refresh_generator_ui()
|
||||
|
||||
func _on_currency_changed(_changed_currency_id: StringName, _new_value: BigNumber) -> void:
|
||||
_refresh_generator_ui()
|
||||
|
||||
func _on_generator_updated(_a = null, _b = null, _c = null, _d = null) -> void:
|
||||
_refresh_generator_ui()
|
||||
|
||||
func _on_generator_state_changed(generator_id: StringName, _state: Dictionary) -> void:
|
||||
if generator_id == _generator_id:
|
||||
visible = true
|
||||
_refresh_generator_ui()
|
||||
|
||||
func _on_buy_buff_pressed(buff_id: StringName) -> void:
|
||||
_generator.buy_buff(buff_id)
|
||||
_refresh_generator_ui()
|
||||
|
||||
func _build_buff_rows() -> void:
|
||||
_buff_rows.clear()
|
||||
for child in _buffs_list.get_children():
|
||||
child.queue_free()
|
||||
|
||||
for buff in _generator.get_buffs():
|
||||
if buff == null:
|
||||
continue
|
||||
|
||||
var buff_id_text: String = String(buff.id).strip_edges()
|
||||
if buff_id_text.is_empty():
|
||||
continue
|
||||
|
||||
var tile: GeneratorBuffTile = GENERATOR_BUFF_TILE_SCENE.instantiate() as GeneratorBuffTile
|
||||
if tile == null:
|
||||
push_warning("Failed to instantiate GeneratorBuffTile for buff '%s'." % buff_id_text)
|
||||
continue
|
||||
|
||||
_buffs_list.add_child(tile)
|
||||
tile.set_buff(buff)
|
||||
tile.buy_pressed.connect(_on_buy_buff_pressed)
|
||||
_buff_rows.append(BuffRow.new(buff, tile))
|
||||
|
||||
func _refresh_buff_rows(can_interact: bool) -> void:
|
||||
_buffs_section.visible = not _buff_rows.is_empty()
|
||||
if _buff_rows.is_empty():
|
||||
return
|
||||
|
||||
for row in _buff_rows:
|
||||
if row == null or row.buff == null or row.tile == null:
|
||||
continue
|
||||
|
||||
var buff: GeneratorBuffData = row.buff
|
||||
var buff_unlocked: bool = _generator.is_buff_unlocked(buff.id)
|
||||
if not buff_unlocked:
|
||||
var locked_hint: String = "Locked"
|
||||
var unlock_goal_currency: Currency = buff.get_unlock_goal_currency()
|
||||
if buff.has_unlock_goal() and unlock_goal_currency != null and _generator.game_state:
|
||||
var goal_currency_id: StringName = _generator.game_state.get_currency_id(unlock_goal_currency)
|
||||
var currency_name: String = _generator.game_state.get_currency_name(goal_currency_id)
|
||||
var required_text: String = buff.get_unlock_goal_amount().to_string_suffix(2)
|
||||
locked_hint = "Unlock at %s %s" % [required_text, currency_name]
|
||||
|
||||
row.tile.set_runtime(0, "Locked", locked_hint, false, false)
|
||||
continue
|
||||
|
||||
var level: int = _generator.get_buff_level(buff.id)
|
||||
var effect_text: String = buff.get_effect_description(level)
|
||||
|
||||
if _generator.is_buff_maxed(buff.id):
|
||||
row.tile.set_runtime(level, effect_text, "", false, true)
|
||||
continue
|
||||
|
||||
var cost: BigNumber = _generator.get_buff_cost(buff.id)
|
||||
var cost_currency_id: StringName = _generator.get_buff_cost_currency_id(buff.id)
|
||||
var currency_label: String = _generator.game_state.get_currency_name(cost_currency_id) if _generator.game_state else "Unknown"
|
||||
var cost_text: String = "%s %s" % [cost.to_string_suffix(2), currency_label]
|
||||
var can_buy: bool = can_interact and _generator.can_buy_buff(buff.id)
|
||||
row.tile.set_runtime(level, effect_text, cost_text, can_buy, false)
|
||||
|
||||
func _refresh_generator_ui() -> void:
|
||||
if _buy_button == null or _buy_max_button == null:
|
||||
return
|
||||
|
||||
if _generator == null:
|
||||
return
|
||||
|
||||
var can_interact: bool = _generator.is_available_to_player()
|
||||
|
||||
_buy_button.disabled = not can_interact
|
||||
_buy_max_button.disabled = not can_interact
|
||||
|
||||
_owned_value.text = str(_generator.owned)
|
||||
if can_interact:
|
||||
var purchase_currency_id: StringName = _generator.get_purchase_currency_id()
|
||||
var purchase_currency_name: String = _generator.game_state.get_currency_name(purchase_currency_id) if _generator.game_state else "Unknown"
|
||||
if purchase_currency_name.is_empty():
|
||||
purchase_currency_name = "Unconfigured"
|
||||
_next_cost_value.text = "%s %s" % [_generator.get_next_cost().to_string_suffix(2), purchase_currency_name]
|
||||
else:
|
||||
_next_cost_value.text = "-"
|
||||
|
||||
var production_per_second: float = 0.0
|
||||
if _generator.data != null and can_interact:
|
||||
production_per_second = _generator.data.production_per_second(
|
||||
_generator.owned,
|
||||
_generator.get_effective_auto_run_multiplier(),
|
||||
_generator.purchased_count
|
||||
)
|
||||
|
||||
_production_value.text = BigNumber.from_float(production_per_second).to_string_suffix(2)
|
||||
_refresh_buff_rows(can_interact)
|
||||
Reference in New Issue
Block a user