2026-04-15 12:01:28 +02:00
2026-04-24 00:55:00 +02:00
2026-05-03 19:30:11 +02:00
2026-05-03 19:00:16 +02:00
2026-04-15 12:01:28 +02:00
2026-04-18 00:56:44 +02:00
2026-04-10 01:09:57 +02:00
2026-03-08 10:38:30 +01:00
2026-03-08 10:38:30 +01:00
2026-03-19 22:18:34 +01:00
2026-04-23 12:46:01 +02:00
2026-03-08 10:38:30 +01:00
2026-03-08 10:38:30 +01:00
2026-04-25 12:26:27 +02:00
2026-03-08 10:38:30 +01:00
2026-04-08 14:49:09 +02:00
2026-03-08 10:38:30 +01:00
2026-03-08 10:38:30 +01:00
2026-04-10 01:09:57 +02:00
2026-05-03 19:30:11 +02:00
2026-05-03 19:30:59 +02:00

Idles — Godot 4.6 Idle Game

A modular idle/incremental game prototype featuring a decoupled buff system, multi-target buffs with wildcard support, goal-based progression, prestige resets, and production-driven research.

Quick Start

# Run the project
"$GODOT_BIN" --path .

# Headless mode (lint/smoke test)
"$GODOT_BIN" --headless --path . --quit

# Check single script syntax
"$GODOT_BIN" --headless --check-only --script res://core/big_number.gd

Architecture Overview

Core Systems

System Location Purpose
BigNumber core/big_number.gd Handles huge numbers (mantissa + exponent) for idle game math
LevelGameState core/level_game_state.gd Central state authority — currencies, generators, buffs, goals, research, persistence
Currency core/currency/, core/currency_catalogue.gd Catalog system for all in-game currencies
Generators core/generator/ Production mechanics (auto cycles, clicks, purchases)
Buffs core/generator/generator_buff_data.gd Global, multi-target buffs applied to generators
Goals core/goals/ Unlock conditions and achievement tracking
Prestige core/prestige/ Reset-with-bonus mechanics
Research core/research/ XP-based progression with production multipliers

Key Nodes

Node Script Description
LevelGameState core/level_game_state.gd Central state management, save/load, catalogs, all signals
PrestigeManager core/prestige/prestige_manager.gd Prestige calculation, reset orchestration
CurrencyGenerator core/generator/currency_generator.gd Per-generator production, purchasing, buff interaction
GeneratorPanel core/generator/generator_container.gd UI panel for a single generator

Important: There are no autoload singletons. LevelGameState and PrestigeManager are regular nodes instantiated in the scene (e.g., docs/gyms/tiny_sword/tiny_sword.tscn). All code accesses them through @export references or get_node(), never through an autoload name like /root/GameState.

Data Directory Structure

All gameplay resources (.tres files) live under:

docs/gyms/tiny_sword/
├── currencies/          # Currency resources (gold, food, wood, worker, etc.)
├── buildings/           # Generator configuration data
│   ├── farm/            #   farm_generator.tres
│   ├── forestry/        #   forestry_generator.tres
│   ├── gold_mine/       #   gold_mine_generator.tres
│   ├── monastery/       #   monastery_generator.tres
│   └── alchemy_tower/   #   alchemy_tower_data.tres + recipes/
├── buffs/               # Buff definitions with target_ids
├── goals/               # Unlock goal definitions
├── prestige/            # Prestige configuration (primary_prestige.tres)
├── research/            # Research track data
└── test/                # (reserved for tests)

Game art assets live separately in:

sandbox/tiny_swords/
├── Buildings/           # Building sprites
├── Terrain/             # Tilesets and decorations
├── UI Elements/         # UI assets
└── Units/               # Unit sprites

Core Documentation

Each core/ subsystem has its own detailed README:

Module Documentation
Core overview core/README.md
Currency system core/currency/README.md
Generator system core/generator/README.md
Goals system core/goals/README.md
Prestige system core/prestige/README.md
Research system core/research/README.md

Buff System

Buffs are globally registered and multi-target capable:

  • Global Levels: Each buff has a single level shared across all generators it targets.
  • Multi-Target: A single buff resource can affect multiple generators. Controlled by the target_ids array on GeneratorBuffData.
  • Wildcards: A target_ids value of ["*"] applies the buff to all current AND future generators.
  • Catalog-Based Loading: Buffs are defined in a BuffCatalogue resource (@export var buff_catalogue: BuffCatalogue on LevelGameState). No runtime directory scanning is performed.
  • Goal-Based Activation: Buffs with an unlock_goal automatically unlock when their goal is completed.
  • Multiplicative Stacking: Multiple buffs of the same kind on a generator stack multiplicatively (buff1 × buff2 ×).
  • Buff Kinds: AUTO_PRODUCTION_MULTIPLIER, MANUAL_CLICK_MULTIPLIER, RESOURCE_PURCHASE, RESEARCH_XP_MULTIPLIER

Lifecycle

Event What happens
Default state Inactive (locked) until its unlock goal is met
Goal met Buff auto-unlocks, becomes purchasable
Purchased Level increments, effect applies to all target generators
Prestige reset All buff levels reset to 0, all buffs re-locked

API (on LevelGameState)

LevelGameState.register_buff(buff: GeneratorBuffData)
LevelGameState.get_buff(buff_id: StringName) -> GeneratorBuffData
LevelGameState.get_buff_level(buff_id: StringName) -> int
LevelGameState.get_buffs_for_generator(generator_id: StringName) -> Array[GeneratorBuffData]
LevelGameState.get_effective_multiplier(generator_id: StringName, kind: int) -> float
LevelGameState.set_buff_level(buff_id: StringName, level: int)
LevelGameState.is_buff_active(buff_id: StringName) -> bool

Goals System

Goals track player progress and unlock generators or buffs when requirements are met.

  • Automatic or Manual: Goals define their own unlock_behavior (AUTOMATIC or MANUAL).
  • Logarithmic Progress: Progress bars use log-scale for visual feedback on huge numbers.
  • Prestige Reset: All goals are reset to incomplete on prestige. Previously unlocked generators re-lock until their goal is met again.

Signals on LevelGameState

goal_completed(goal_id: StringName)
goal_progress_changed(goal_id: StringName, progress: float)

Prestige System

Prestige resets run progress in exchange for a permanent production multiplier.

  • Configuration: PrestigeConfig resource at docs/gyms/tiny_sword/prestige/primary_prestige.tres
  • Basis types: LIFETIME_TOTAL (single currency), RUN_TOTAL, RUN_MAX, ALL_CURRENCIES (sum of all tracked currencies)
  • Formula types: POWER (scale × ratio^exponent) or TRIANGULAR_INVERSE
  • Multiplier modes: ADDITIVE or MULTIPLICATIVE_POWER

What gets reset on prestige

State Behavior
Current currency balances Reset to 0 (except prestige currency if configured)
Generator states (owned, unlocked) Cleared
Buff levels All reset to 0, all re-locked
Goals All reset to incomplete
Research XP and levels All cleared to 0
Lifetime currency totals Preserved
All-time currency acquired Preserved
Prestige points earned Preserved (permanent)

Research System

XP-based progression tied to generator output. Research tracks level up automatically, granting permanent production multipliers to their associated generator.

  • XP Formula: XP = currency_produced × xp_per_currency_produced × buff_multiplier
  • Level Formula: xp_required(n) = base_xp_required × growth_multiplier^(n-1)
  • Buffs: The RESEARCH_XP_MULTIPLIER buff kind increases XP gain for a research track.
  • Prestige Reset: All research XP and levels reset to 0.

Save Format

Version 5 (current):

{
  "save_format_version": 5,
  "currencies": {
    "<currency_id>": {
      "current":  {"m": 1.0, "e": 0},
      "total":    {"m": 1.0, "e": 0},
      "all_time": {"m": 1.0, "e": 0}
    }
  },
  "generator_states": {
    "<generator_id>": {
      "owned": 0,
      "purchased_count": 0,
      "unlocked": false,
      "available": false
    }
  },
  "buff_levels":   { "<buff_id>": 0 },
  "buff_unlocked": { "<buff_id>": false },
  "buff_active":   { "<buff_id>": false },
  "goals":         { "completed": ["<goal_id>"] },
  "research_xp":       { "<research_id>": {"m": 0.0, "e": 0} },
  "research_levels":   { "<research_id>": 0 },
  "research_workers": 0,
  "prestige_state": {  },
  "last_save_time": 1234567890
}

Notes:

  • All large numbers are serialized as {"m": mantissa_float, "e": exponent_int} (BigNumber format).
  • prestige_state is an external section managed by PrestigeManager, not by LevelGameState directly.
  • research_workers tracks workers assigned to research across all tracks.
  • Save file is written to user://level_save.json.

Save/Load

  • Save: LevelGameState.save_game() serializes all state to JSON. Called on prestige reset (via PrestigeManager) and when manually triggered.
  • Load: LevelGameState.load_game() deserializes from disk during _ready(). Handles version migration from v2+.
  • External sections: Other systems (e.g. PrestigeManager) can attach their data via set_external_save_data() / get_external_save_data().

Development

Adding New Content

All gameplay resources go under docs/gyms/tiny_sword/ (not sandbox/ — that's for art assets only).

New Currency:

  1. Create res://docs/gyms/tiny_sword/currencies/<name>.tres (extend Currency)
  2. Set id, display_name, icon
  3. Add to the CurrencyCatalogue resource (ts_currency_catalogue.tres)

New Generator:

  1. Create res://docs/gyms/tiny_sword/buildings/<name>/<name>_generator.tres (extend CurrencyGeneratorData)
  2. Configure production stats, costs, purchase currency, optional unlock_goal
  3. Add a CurrencyGenerator node to the scene referencing this data

New Buff:

  1. Create res://docs/gyms/tiny_sword/buffs/<name>.tres (extend GeneratorBuffData)
  2. Set target_ids (e.g., ["farm", "forestry"] or ["*"] for all generators)
  3. Configure kind, effect_increment, cost, and optional unlock_goal
  4. Add to the BuffCatalogue resource (ts_buff_catalogue.tres)

New Research:

  1. Create res://docs/gyms/tiny_sword/research/<name>.tres (extend ResearchData)
  2. Link to a generator via generator_id
  3. Configure xp_per_currency_produced, base_xp_required, xp_growth_multiplier, multiplier_per_level
  4. Add to the ResearchCatalogue resource (ts_research_catalogue.tres)

BigNumber System

  • Representation: mantissa: float × 10^exponent: int
  • Range: Values up to ~10^308 before float precision loss
  • Operations: add(), subtract(), multiply(), divide(), compare_to(), add_in_place()
  • Serialization: .serialize(){"m": float, "e": int}; BigNumber.deserialize(dict)BigNumber
  • Display: .to_string_suffix(decimals: int)"1.50K", "3.21M", etc.

Production Formulas

Cost for N items:   base × coefficient^owned × (coefficient^n  1) / (coefficient  1)
Max affordable:     floor(log(currency × (coefficient  1) / (base × coefficient^owned) + 1) / log(coefficient))
Production/cycle:   initial_productivity × owned × run_mult × milestone_mult × purchased_mult
Production/second:  production/cycle / initial_time

Project Structure

core/                         # Engine code (all .gd scripts)
├── big_number.gd             # BigNumber class
├── level_game_state.gd       # Central state manager (LevelGameState node)
├── buff_catalogue.gd         # Buff catalogue resource
├── currency_catalogue.gd     # Currency catalogue resource
├── goal_catalogue.gd         # Goal catalogue resource
├── currency/                 # Currency resource definition
├── generator/                # Generator, buff data, UI panel, research buff calculator
├── goals/                    # Goal/requirement resources
├── prestige/                 # Prestige manager, config, panel
└── research/                 # Research catalogue, panel, row UI

docs/gyms/tiny_sword/         # Playable game content (.tres resources)
├── currencies/               # Currency definitions
├── buildings/                # Generator configs
├── buffs/                    # Buff definitions
├── goals/                    # Goal definitions
├── prestige/                 # Prestige config
├── research/                 # Research configs
└── test/                     # (reserved for tests)

sandbox/tiny_swords/          # Art assets (sprites, tilesets, UI textures)
└── Buildings/, Terrain/, UI Elements/, Units/

docs/museums/                 # Prototype/demo scenes (big_number_museum)

Known Issues / TODOs

  • Periodic auto-save not implemented (saves only on prestige and manual trigger)
  • No automated test suite
  • Some buffs may be configured with no unlock path

Technical Details

Buff Multiplier Stacking

Multiple buffs of the same kind on the same generator stack multiplicatively:

total_multiplier = buff1_effect(level) × buff2_effect(level) × buff3_effect(level) ×

Prestige Multiplier Application

Generators apply prestige multipliers automatically. The prestige multiplier is fetched from PrestigeManager.get_total_multiplier() and multiplied into the effective production rate alongside research and buff multipliers.

License

Internal prototype — no external license applied.


Godot version: 4.6

Description
No description provided
Readme 4.4 MiB
Languages
GDScript 99%
Shell 1%