Fix research

This commit is contained in:
2026-04-15 12:01:28 +02:00
parent 0e8c682ae7
commit 45e1df5a46
37 changed files with 2848 additions and 20 deletions

View File

@@ -12,6 +12,8 @@ signal buff_level_changed(buff_id: StringName, new_level: int)
signal buff_unlocked_changed(buff_id: StringName, unlocked: bool)
signal goal_completed(goal_id: StringName)
signal goal_progress_changed(goal_id: StringName, progress: float)
signal research_xp_changed(research_id: StringName, new_xp: BigNumber)
signal research_level_up(research_id: StringName, old_level: int, new_level: int)
# ==========================================
# EXPORTED REFERENCES
@@ -19,6 +21,7 @@ signal goal_progress_changed(goal_id: StringName, progress: float)
@export var currency_catalogue: CurrencyCatalogue
@export var buff_catalogue: BuffCatalogue
@export var goal_catalogue: GoalCatalogue
@export var research_catalogue: ResearchCatalogue
@export var save_file_path: String = "user://level_save.json"
# ==========================================
@@ -41,13 +44,17 @@ var _buff_active: Dictionary = {}
var _goal_definitions: Dictionary = {}
var _goal_completed: Dictionary = {}
var research_xp: Dictionary = {}
var research_levels: Dictionary = {}
var research_tracker: Node = null
var last_save_time: int = 0
# ==========================================
# Save / Load
# ==========================================
const SAVE_FORMAT_VERSION_KEY: String = "save_format_version"
const CURRENT_SAVE_FORMAT_VERSION: int = 3
const CURRENT_SAVE_FORMAT_VERSION: int = 5
const GENERATOR_OWNED_KEY: String = "owned"
const GENERATOR_PURCHASED_COUNT_KEY: String = "purchased_count"
const GENERATOR_UNLOCKED_KEY: String = "unlocked"
@@ -66,6 +73,8 @@ const CURRENT_KEY: String = "current"
const TOTAL_KEY: String = "total"
const ALL_TIME_KEY: String = "all_time"
const LAST_SAVE_TIME_KEY: String = "last_save_time"
const RESEARCH_XP_KEY: String = "research_xp"
const RESEARCH_LEVELS_KEY: String = "research_levels"
var prestige_manager: PrestigeManager
@@ -76,6 +85,7 @@ func _ready() -> void:
_load_catalogue_goals()
load_game()
_try_unlock_all_buffs_from_goals()
_initialize_research()
# ==========================================
# STATE MODIFIERS
@@ -429,6 +439,19 @@ func get_effective_multiplier(generator_id: StringName, kind: int) -> float:
return multiplier
func _initialize_research() -> void:
research_tracker = Node.new()
research_tracker.set_script(load("res://core/research/research_xp_tracker.gd"))
add_child(research_tracker)
var tracker: ResearchXPTracker = research_tracker as ResearchXPTracker
if tracker:
tracker.game_state = self
if research_catalogue:
for research in research_catalogue.get_all_research():
register_research(research.id)
func _try_unlock_all_buffs_from_goals() -> void:
for buff in get_all_buffs():
if buff == null:
@@ -446,6 +469,60 @@ func _try_unlock_buff_from_goal(buff: GeneratorBuffData) -> void:
if not goal_id.is_empty() and is_goal_completed(goal_id):
set_buff_unlocked(buff.id, true)
func register_research(research_id: StringName) -> void:
if not research_xp.has(research_id):
research_xp[research_id] = BigNumber.new(0.0, 0)
if not research_levels.has(research_id):
research_levels[research_id] = 0
func get_research_xp(research_id: StringName) -> BigNumber:
var val: Variant = research_xp.get(research_id, BigNumber.new(0.0, 0))
return val as BigNumber
func get_research_level(research_id: StringName) -> int:
return research_levels.get(research_id, 0)
func get_research_multiplier(research_id: StringName) -> float:
var level: int = get_research_level(research_id)
var research: ResearchData = _get_research_data(research_id)
if research == null:
return 1.0
return research.get_multiplier_for_level(level)
func add_research_xp(research_id: StringName, xp: BigNumber) -> void:
var old_level: int = get_research_level(research_id)
var current_xp: BigNumber = get_research_xp(research_id)
research_xp[research_id] = current_xp.add(xp)
var research: ResearchData = _get_research_data(research_id)
if research != null:
var new_level: int = research.get_level_for_xp(research_xp[research_id])
if new_level > old_level:
research_levels[research_id] = new_level
research_level_up.emit(research_id, old_level, new_level)
research_xp_changed.emit(research_id, research_xp[research_id])
func get_research_xp_multiplier(research_id: StringName) -> float:
var multiplier: float = 1.0
var research: ResearchData = _get_research_data(research_id)
if research == null:
return 1.0
if not research.associated_buff_id.is_empty():
var buff: GeneratorBuffData = get_buff(research.associated_buff_id)
if buff != null and is_buff_active(buff.id):
var level: int = get_buff_level(buff.id)
multiplier *= buff.get_effect_multiplier(level)
return multiplier
func _get_research_data(research_id: StringName) -> ResearchData:
if research_catalogue == null:
return null
return research_catalogue.get_research_by_id(research_id)
func set_external_save_data(section_key: StringName, payload: Dictionary) -> void:
var key: String = String(section_key).strip_edges()
if key.is_empty():
@@ -473,12 +550,14 @@ func reset_for_prestige(reset_total_currency: bool = false, emit_currency_signal
if reset_total_currency:
_set_total_currency(currency_id, BigNumber.from_float(0.0))
generator_states.clear()
generator_buff_levels.clear()
generator_buff_unlocked.clear()
_goal_completed.clear()
for goal_id in _goal_definitions.keys():
_goal_completed[goal_id] = false
generator_states.clear()
generator_buff_levels.clear()
generator_buff_unlocked.clear()
_goal_completed.clear()
for goal_id in _goal_completed.keys():
_goal_completed[goal_id] = false
research_xp.clear()
research_levels.clear()
if not emit_currency_signals:
return
@@ -506,6 +585,8 @@ func save_game() -> void:
BUFF_UNLOCKED_KEY: _serialize_buff_unlocked(),
BUFF_ACTIVE_KEY: _serialize_buff_active(),
GOALS_KEY: _serialize_goals(),
RESEARCH_XP_KEY: _serialize_research_xp(),
RESEARCH_LEVELS_KEY: research_levels.duplicate(),
LAST_SAVE_TIME_KEY: Time.get_unix_time_from_system()
}
@@ -551,12 +632,18 @@ func load_game() -> void:
generator_states = _deserialize_generator_states(parsed_data.get(GENERATOR_STATES_KEY, {}))
_deserialize_buff_states(parsed_data)
_deserialize_goals(parsed_data.get(GOALS_KEY, {}))
if parsed_data.has(RESEARCH_XP_KEY):
research_xp = _deserialize_research_xp(parsed_data.get(RESEARCH_XP_KEY, {}))
if parsed_data.has(RESEARCH_LEVELS_KEY):
research_levels = parsed_data.get(RESEARCH_LEVELS_KEY, {})
last_save_time = parsed_data.get(LAST_SAVE_TIME_KEY, Time.get_unix_time_from_system())
for save_key_variant in parsed_data.keys():
var save_key: String = String(save_key_variant)
if save_key.is_empty():
continue
if save_key in [SAVE_FORMAT_VERSION_KEY, CURRENCIES_KEY, GENERATOR_STATES_KEY, BUFF_LEVELS_KEY, BUFF_UNLOCKED_KEY, BUFF_ACTIVE_KEY, GOALS_KEY, LAST_SAVE_TIME_KEY]:
if save_key in [SAVE_FORMAT_VERSION_KEY, CURRENCIES_KEY, GENERATOR_STATES_KEY, BUFF_LEVELS_KEY, BUFF_UNLOCKED_KEY, BUFF_ACTIVE_KEY, GOALS_KEY, RESEARCH_XP_KEY, RESEARCH_LEVELS_KEY, LAST_SAVE_TIME_KEY]:
continue
var section_payload: Variant = parsed_data.get(save_key_variant)
@@ -1294,3 +1381,19 @@ func _humanize_currency_id(currency_id: StringName) -> String:
if normalized.is_empty():
return "Unknown"
return normalized.replace("_", " ").capitalize()
func _serialize_research_xp() -> Dictionary:
var result: Dictionary = {}
for research_id in research_xp.keys():
var xp: BigNumber = research_xp[research_id]
result[research_id] = xp.serialize()
return result
func _deserialize_research_xp(raw: Variant) -> Dictionary:
var result: Dictionary = {}
if raw is Dictionary:
for research_id in raw.keys():
var serialized: Variant = raw[research_id]
if serialized is Dictionary:
result[research_id] = BigNumber.deserialize(serialized)
return result