Files
idle/README.md
2026-03-21 09:14:38 +01:00

14 KiB

Idles - Systems Architecture Report

Scope Covered

This report covers all tracked files in the repository (62 total at time of analysis), including:

  1. Project configuration.
  2. Core runtime scripts.
  3. Gameplay/economy systems.
  4. Goal/unlock systems.
  5. UI adapter scripts and scenes.
  6. Data resources (.tres).
  7. Technical docs and metadata/import files.

The focus below is on behavior-bearing files and how they interact.

Architecture Summary

  1. Global startup and singleton wiring is defined in project.godot.
  2. Two autoload services power the runtime: CurrencyDatabase and GameState.
  3. BigNumber is the numeric backbone used by currency amounts, costs, goals, production, and persistence.
  4. Generator behavior is runtime-driven by CurrencyGenerator, parameterized by CurrencyGeneratorData and GeneratorBuffData resources.
  5. Goal-based progression uses reusable goal primitives (GoalData, GoalRequirementData) plus unlock bindings (GeneratorUnlockGoalData) and runtime evaluator (generator_unlock_system.gd).
  6. UI scripts are thin adapters listening to GameState signals.

Core Systems

1) Numeric System (BigNumber)

File: core/big_number.gd

BigNumber stores values as mantissa + exponent (scientific notation style), normalizes them, and provides:

  1. Arithmetic operations (add, subtract, multiply, divide).
  2. In-place fast accumulation (add_in_place) for frame-loop performance.
  3. Safe comparisons (compare_to, is_greater_than, etc.).
  4. Ratio conversion for progress UI (get_ratio).
  5. Display formatting (to_string_sci, to_string_suffix).
  6. JSON-friendly serialization/deserialization.

This class is used everywhere currency values move.

2) Currency Catalog System

Files: core/currency/currency.gd, core/currency_database.gd, idles/currencies/*.tres

CurrencyDatabase scans res://idles/currencies, loads typed Currency resources, normalizes IDs, and resolves names/icons.

Current data assets:

  1. idles/currencies/magic.tres (id = magic).
  2. idles/currencies/knowledge.tres (id = knowledge).

This creates a data-driven currency catalog that GameState, goals, and UI can query consistently.

3) Global State + Persistence (GameState)

File: core/game_state.gd

GameState is the central state authority and signal bus.

It owns:

  1. Current currency map by currency ID.
  2. Total acquired currency map by currency ID.
  3. Generator states (owned, purchased_count, unlocked, available).
  4. Generator buff levels.
  5. Generator buff unlocked flags.
  6. last_save_time.

Important signals:

  1. currency_changed.
  2. generator_state_changed.
  3. generator_buff_level_changed.
  4. generator_buff_unlocked_changed.

Persistence:

  1. Save path: user://idle_save.json.
  2. Save payload includes currencies, generator states, buff levels, buff unlocked map, and timestamp.
  3. Load path includes defensive sanitization and backward-compatible defaulting.

4) Generator Economy Runtime

Files: core/generator/currency_generator.gd, core/generator/currency_generator_data.gd, core/generator/currency_generator.tscn

CurrencyGenerator implements active gameplay behavior:

  1. Auto production cycles (_process, cycle accumulation).
  2. Click/hover grants with cooldown.
  3. Buy-one and buy-max generator purchases.
  4. Buff purchase logic and buff effect application.
  5. State registration and lookup through GameState.

CurrencyGeneratorData provides formulas and tuning knobs:

  1. Exponential cost growth.
  2. Bulk-buy geometric cost.
  3. Max-affordable estimate.
  4. Milestone multipliers.
  5. Purchased-count multiplier.
  6. Production/cycle and production/second helpers.
  7. ROI-like helpers (payback_seconds, income_to_cost_ratio).

5) Buff System

Files: core/generator/generator_buff_data.gd, idles/buffs/*.tres

Buff kinds:

  1. Auto production multiplier.
  2. Manual click multiplier.
  3. Resource purchase (instant grant on buff buy).

Each buff resource defines:

  1. Unlock rules (unlocked and optional unlock_goal).
  2. Effect scaling (base_effect, effect_increment).
  3. Cost scaling (base_cost, cost_multiplier).
  4. Optional target currency and resource grant scaling.

6) Goals and Unlock Progression

Files:

  1. core/goals/goal_requirement_data.gd
  2. core/goals/goal_data.gd
  3. core/generator-unlock-goals/generator_unlock_goal_data.gd
  4. core/generator-unlock-goals/generator_unlock_system.gd
  5. idles/goals/*.tres

Key behavior:

  1. Goal requirements validate currency + target amount.
  2. Requirement completion checks total acquired currency, not current wallet.
  3. Unlock system evaluates goals on currency change and generator state changes.
  4. If a goal is met and target generator is resolvable, it sets both unlocked = true and available = true.

7) UI Adapter Layer

Files:

  1. generator_container.gd + generator_container.tscn.
  2. generator_buff_tile.gd + generator_buff_tile.tscn.
  3. currency_label.gd + currency_tile.tscn.
  4. big_number_progress_bar.gd + big_number_progress_bar.tscn.
  5. core/generator-unlock-goals/goals_debug_ui.gd + .tscn.

These scripts primarily:

  1. Subscribe to GameState and generator signals.
  2. Convert runtime values to UI strings/states.
  3. Trigger user actions (buy generator, buy buff, debug unlock).

The architecture is mostly event-driven and avoids polling for state refresh.

Scene Composition

Active Gameplay Prototype

File: docs/museums/generator_museum.tscn

It composes:

  1. MagicGenerator instance.
  2. KnowledgeGenerator instance (initially hidden and starts locked via data).
  3. Currency tiles for magic and knowledge.
  4. Goals debug UI panel.
  5. Runtime GeneratorUnlockSystem node with configured unlock goals.

Legacy/Secondary Museum

Files: docs/museums/big_number_museum.tscn, docs/museums/big_number_museum.gd

This appears to be an older/placeholder scene and not the current gameplay focus.

Data-Driven Content Snapshot

Generators

  1. primary_generator.tres: Magic Orb, active from start, includes 3 buffs.
  2. secondary_generator.tres: Library, starts locked/unavailable.

Buffs (Magic)

  1. magic_auto_flux.tres: auto-production buff, unlocked by default.
  2. magic_click_focus.tres: manual-click buff.
  3. magic_supply_cache.tres: resource-purchase buff.

Goals

  1. magic_total_30.tres: reach total magic 30.
  2. magic_total_1300.tres: reach total magic 1300.
  3. generator_unlock_knowledge.tres: maps magic_total_30 to generator Knowledge.
  4. generator_unlock_wood.tres: maps magic_total_1300 to generator Wood.

End-to-End Runtime Flow

  1. project.godot autoloads CurrencyDatabase and GameState.
  2. CurrencyDatabase builds currency catalog from idles/currencies.
  3. GameState initializes per-currency maps and loads save data.
  4. Scene nodes initialize and connect to GameState and local gameplay signals.
  5. Generators produce currency automatically and via click/hover paths.
  6. Currency updates emit currency_changed and drive UI refresh + unlock checks.
  7. Goal unlock evaluator may transition generator state to unlocked/available.
  8. Generator and buff purchases route all balance/state mutations through GameState.

Signal Guide (Emitters and Listeners)

Custom Gameplay Signals

Signal Declared In Emitted By Emitted When Listeners
currency_changed(currency_id, new_amount) core/game_state.gd GameState.add_currency_by_id, GameState.spend_currency_by_id Any currency balance increases/decreases CurrencyGenerator._on_currency_changed, GeneratorPanel._on_currency_changed, CurrencyTile._on_currency_changed, BigNumberProgressBar._on_currency_changed, GeneratorUnlockSystem._on_currency_changed, GoalsDebugUI._on_currency_changed
generator_state_changed(generator_id, state) core/game_state.gd GameState.register_generator, GameState._set_generator_state Generator state created or changed (owned, purchased_count, unlocked, available) CurrencyGenerator._on_generated_state_changed, GeneratorPanel._on_generator_state_changed, GeneratorUnlockSystem._on_generator_state_changed, GoalsDebugUI._on_generator_state_changed
generator_buff_level_changed(generator_id, buff_id, new_level) core/game_state.gd GameState.register_generator_buff, GameState.set_generator_buff_level Buff level created/sanitized/updated GeneratorPanel._on_generator_buff_level_changed
generator_buff_unlocked_changed(generator_id, buff_id, unlocked) core/game_state.gd GameState.register_generator_buff_unlocked, GameState.set_generator_buff_unlocked Buff unlock state created/sanitized/updated GeneratorPanel._on_generator_buff_unlocked_changed
purchase_completed(amount, total_owned, total_purchased, total_cost) core/generator/currency_generator.gd CurrencyGenerator.buy Generator purchase succeeds GeneratorPanel._on_generator_updated
purchase_failed(requested_amount, required_cost, available_currency) core/generator/currency_generator.gd CurrencyGenerator.buy Generator purchase fails for insufficient funds GeneratorPanel._on_generator_updated
production_tick(amount, cycle_count, total_owned) core/generator/currency_generator.gd CurrencyGenerator._grant_cycle_income One or more automatic production cycles complete GeneratorPanel._on_generator_updated
buff_purchased(buff_id, new_level, cost, cost_currency_id) core/generator/currency_generator.gd CurrencyGenerator.buy_buff Buff purchase succeeds GeneratorPanel._on_generator_updated
buff_purchase_failed(buff_id, required_cost, cost_currency_id) core/generator/currency_generator.gd CurrencyGenerator.buy_buff Buff purchase fails for insufficient funds GeneratorPanel._on_generator_updated
goal_achieved(goal_id, target_generator_id) core/generator-unlock-goals/generator_unlock_system.gd GeneratorUnlockSystem._evaluate_goal Unlock goal transitions target generator to unlocked+available None currently (available for gameplay/UI hooks)
buy_pressed(buff_id) generator_buff_tile.gd GeneratorBuffTile._on_buy_button_pressed User presses buff buy button in a buff row GeneratorPanel._on_buy_buff_pressed

Built-In Godot Signals Wired In This Project

Source Signal Connected In Listener Method Purpose
Area2D.mouse_entered core/generator/currency_generator.tscn CurrencyGenerator._on_area_2d_mouse_entered Enter generator hover zone; mark hover true and show generator panel
Area2D.mouse_exited core/generator/currency_generator.tscn CurrencyGenerator._on_area_2d_mouse_exited Exit generator hover zone; mark hover false and hide generator panel
BuyOneButton.pressed generator_container.tscn GeneratorPanel._on_buy_pressed Buy one generator
BuyMaxButton.pressed generator_container.tscn GeneratorPanel._on_buy_max_pressed Buy max affordable generators
GeneratorContainer.mouse_entered generator_container.tscn GeneratorPanel._on_mouse_entered Intended hover hook on panel container (method currently missing)
GeneratorContainer.mouse_exited generator_container.tscn GeneratorPanel._on_mouse_exited Intended hover hook on panel container (method currently missing)
BuyButton.pressed generator_buff_tile.tscn GeneratorBuffTile._on_buy_button_pressed Emit tile-level buy_pressed custom signal
DebugIncomeButton.pressed currency_tile.tscn CurrencyTile._on_debug_income_button_pressed Add debug income to the tile currency
Button.pressed (runtime-created unlock button) core/generator-unlock-goals/goals_debug_ui.gd GoalsDebugUI._on_unlock_pressed (bound with goal id) Manual debug unlock when a goal is ready

Common Signal Chains

  1. Currency gain/spend chain: generator or debug action mutates GameState currency, GameState emits currency_changed, UI widgets and unlock systems recompute and redraw.
  2. Generator purchase chain: panel button triggers CurrencyGenerator.buy, generator updates GameState state, generator emits purchase signal, panel refreshes stats and buttons.
  3. Buff purchase chain: buff tile emits buy_pressed, panel calls CurrencyGenerator.buy_buff, generator updates buff level/unlock and optionally grants currency, GameState emits buff/currency/state signals, panel and other listeners refresh.
  4. Goal unlock chain: currency_changed triggers unlock evaluator, evaluator sets generator unlocked/available, emits goal_achieved(goal_id, target_generator_id), GameState emits generator_state_changed, generator and UI become interactable/visible.

Key Findings and Risks

  1. project.godot has no explicit run/main_scene entry, so startup scene is not pinned in tracked config.
  2. Save/load is only partially wired: load_game() runs at startup, but save_game() is not invoked anywhere else in the repository.
  3. currency_label.gd and big_number_progress_bar.gd reference GameState.GOLD_CURRENCY_ID, but that constant does not exist in core/game_state.gd.
  4. generator_container.tscn connects mouse_entered/mouse_exited to methods that do not exist in generator_container.gd.
  5. generator_unlock_wood.tres targets generator ID Wood, but no generator with that ID appears in current runtime scene/content, so this goal is currently non-functional.
  6. KnowledgeGenerator visibility logic may be inconsistent because currency_generator.gd sets visible = true whenever its generator state changes.
  7. Two buffs are configured locked with no unlock-goal path, so they remain permanently inaccessible under current logic.
  8. core/generator-unlock-goals/TECH_SPEC.md contains some outdated assumptions relative to current .tres-based implementation.

Additional Notes

  1. .uid files are identity metadata used by Godot and contain no runtime logic.
  2. icon.svg and icon.svg.import are standard icon/import metadata.
  3. Root config files (.editorconfig, .gitattributes, .gitignore) are minimal and conventional.