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:
2026-05-07 20:36:21 +00:00
parent 2743fd314a
commit 81a4058b04
242 changed files with 11226 additions and 2242 deletions

79
tests/test_runner.gd Normal file
View File

@@ -0,0 +1,79 @@
extends SceneTree
var test_scripts: Array[String] = []
var test_index: int = 0
var total_passed: int = 0
var total_failed: int = 0
func _init():
print("\n=== GODOT TEST RUNNER ===\n")
_discover_tests()
if test_scripts.is_empty():
print("[ERROR] No test scripts found in res://tests/")
print("[RESULT] FAIL")
quit(1)
return
print("Found %d test(s): %s\n" % [test_scripts.size(), str(test_scripts)])
await _run_next_test()
print("\n=== TEST SUMMARY ===")
print("Total passed: %d" % total_passed)
print("Total failed: %d" % total_failed)
if total_failed == 0:
print("[OVERALL_RESULT] PASS")
quit(0)
else:
print("[OVERALL_RESULT] FAIL")
quit(1)
func _discover_tests() -> void:
var dir = DirAccess.open("res://tests")
if dir:
dir.list_dir_begin()
var file_name = dir.get_next()
while file_name != "":
if file_name.ends_with(".gd") and file_name.begins_with("test_") and \
file_name != "test_runner.gd" and file_name != "test_utils.gd":
test_scripts.append("res://tests/%s" % file_name)
file_name = dir.get_next()
dir.list_dir_end()
test_scripts.sort()
func _run_next_test() -> void:
if test_index >= test_scripts.size():
return
var test_script = test_scripts[test_index]
print("--- Running test %d/%d: %s ---" % [test_index + 1, test_scripts.size(), test_script])
print("")
# Load and run test
var test_instance = load(test_script).new()
get_root().add_child(test_instance)
# Check if test has run() method (new pattern) or uses _ready() (old pattern)
if test_instance.has_method("run"):
await test_instance.run()
# Clean up test instance
test_instance.queue_free()
else:
# For old pattern, wait a bit for _ready() to complete
await create_timer(0.2).timeout
# Clean up test instance
test_instance.queue_free()
# Get results if available
if test_instance.has_method("get_passed"):
total_passed += test_instance.get_passed()
total_failed += test_instance.get_failed()
# Wait for cleanup
await create_timer(0.1).timeout
print("")
test_index += 1
await _run_next_test()