Fix research xp generation

This commit is contained in:
2026-04-18 00:56:44 +02:00
parent 2bc81a73fd
commit dfb1161854
29 changed files with 485 additions and 47 deletions

View File

@@ -2,7 +2,9 @@
## Overview
The `research/` subfolder implements a production-based research system where generator output earns research XP, automatically leveling up to provide production multipliers. Research tracks are tied to specific generators and can be enhanced with purchasable buffs that increase XP gain.
The `research/` subfolder implements a production-based research system where generator output earns
research XP, automatically leveling up to provide production multipliers. Research tracks are tied to
specific generators and can be enhanced with purchasable buffs that increase XP gain.
## Files

View File

@@ -8,6 +8,7 @@ const RESEARCH_ROW_SCENE: PackedScene = preload("res://core/research/research_ro
var _game_state: LevelGameState
var _research_rows: Dictionary = {}
var _active_research_id: StringName = &""
func _ready() -> void:
_game_state = find_parent("LevelGameState")
@@ -25,13 +26,17 @@ func _build_research_rows() -> void:
for child in _research_rows_container.get_children():
child.queue_free()
_research_rows.clear()
_active_research_id = &""
if _game_state.research_catalogue:
for research in _game_state.research_catalogue.get_all_research():
var row: ResearchRow = RESEARCH_ROW_SCENE.instantiate()
_research_rows_container.add_child(row)
row.setup(research)
row.active_changed.connect(_on_research_active_changed.bind(research.id))
_research_rows[research.id] = row
_load_active_research_state()
func _refresh_all() -> void:
for row in _research_rows.values():
@@ -58,3 +63,49 @@ func _on_research_xp_changed(research_id: StringName, _new_xp: BigNumber) -> voi
func _on_research_level_up(research_id: StringName, _old_level: int, _new_level: int) -> void:
if _research_rows.has(research_id):
_refresh_row(_research_rows[research_id])
func _on_research_active_changed(is_active: bool, research_id: StringName) -> void:
if is_active:
if _active_research_id != &"" and _active_research_id != research_id:
var existing_row: ResearchRow = _research_rows.get(_active_research_id)
if existing_row != null:
existing_row.set_active(false, false)
_active_research_id = research_id
_save_active_research_state()
else:
if _active_research_id == research_id:
_active_research_id = &""
_save_active_research_state()
func _load_active_research_state() -> void:
if _game_state == null:
return
var save_data: Dictionary = _game_state.get_external_save_data("research_active")
if save_data.has("active_research_id"):
var loaded_id: String = String(save_data.get("active_research_id", ""))
if not loaded_id.is_empty():
_active_research_id = StringName(loaded_id)
var row: ResearchRow = _research_rows.get(_active_research_id)
if row != null:
row.set_active(true, false)
func _save_active_research_state() -> void:
if _game_state == null:
return
var save_data: Dictionary = {}
if _active_research_id != &"":
save_data["active_research_id"] = String(_active_research_id)
_game_state.set_external_save_data("research_active", save_data)
func get_active_research_id() -> StringName:
return _active_research_id
func is_research_active(research_id: StringName) -> bool:
return _active_research_id == research_id
func activate_research(research_id: StringName) -> void:
if _research_rows.has(research_id):
var row: ResearchRow = _research_rows[research_id]
row.set_active(true)

View File

@@ -1,14 +1,18 @@
class_name ResearchRow
extends HBoxContainer
signal active_changed(is_active: bool)
@onready var _name_label: Label = $VBoxContainer/NameLabel
@onready var _level_label: Label = $VBoxContainer/HBoxContainer/LevelLabel
@onready var _progress_bar: ProgressBar = $VBoxContainer/HBoxContainer/ProgressBar
@onready var _multiplier_label: Label = $VBoxContainer/HBoxContainer/MultiplierLabel
@onready var _buff_label: Label = $VBoxContainer/HBoxContainer/BuffLabel
@onready var _check_button: CheckButton = $CheckButton
var _research: ResearchData
var _game_state: LevelGameState
var _is_active: bool = false
func _ready() -> void:
_game_state = find_parent("LevelGameState")
@@ -18,6 +22,7 @@ func _ready() -> void:
_game_state.research_xp_changed.connect(_on_research_xp_changed)
_game_state.research_level_up.connect(_on_research_level_up)
_check_button.toggled.connect(_on_check_button_toggled)
func setup(research: ResearchData) -> void:
_research = research
@@ -72,3 +77,22 @@ func _update_from_state() -> void:
var xp_needed: BigNumber = _research.get_xp_required_for_level_big(level + 1)
update_display(level, progress, multiplier, xp_current, xp_needed)
func _on_check_button_toggled(toggled_on: bool) -> void:
if toggled_on != _is_active:
_is_active = toggled_on
active_changed.emit(_is_active)
func set_active(is_active: bool, emit_signal: bool = true) -> void:
_is_active = is_active
_check_button.button_pressed = is_active
if emit_signal:
active_changed.emit(is_active)
func is_research_active() -> bool:
return _is_active
func get_research_id_public() -> StringName:
if _research == null:
return &""
return _research.id

View File

@@ -36,3 +36,7 @@ text = "+0%"
[node name="BuffLabel" type="Label" parent="VBoxContainer/HBoxContainer" unique_id=2124734446]
layout_mode = 2
[node name="CheckButton" type="CheckButton" parent="." unique_id=3456789012]
layout_mode = 2
text = "Active"

View File

@@ -31,6 +31,9 @@ func _on_generator_produced(generator_id: StringName, _amount: Variant) -> void:
if research == null:
return
if not _is_research_active(research.id):
return
var amount_big: BigNumber = _amount
var amount_float: float = amount_big.mantissa * pow(10.0, float(amount_big.exponent))
if amount_float <= 0.0:
@@ -46,3 +49,24 @@ func _get_research_for_generator(generator_id: StringName) -> ResearchData:
if game_state == null or game_state.research_catalogue == null:
return null
return game_state.research_catalogue.get_research_by_generator_id(generator_id)
func _is_research_active(research_id: StringName) -> bool:
if game_state == null:
return false
var research_panel: Node = game_state.find_child("ResearchPanel", true, false)
if research_panel == null:
return true
if research_panel.has_method("is_research_active"):
return research_panel.is_research_active(research_id)
return true
func activate_research(research_id: StringName) -> void:
if game_state == null:
return
var research_panel: Node = game_state.find_child("ResearchPanel", true, false)
if research_panel != null and research_panel.has_method("activate_research"):
research_panel.activate_research(research_id)