Files
dota_factory/docs/content_design.md
Malte Langkabel b4fa3e6dff Restructure balancing docs into docs/balancing/
Split the cluttered progression_design.md and content_design.md into
separated documents by role:

- docs/balancing/rules.md    - design rules and principles (moved from
                               progression_design.md, which is removed)
- docs/balancing/targets.md  - the chosen base numbers: run shape,
                               factory curve, threat ladder (achieved
                               values adopted), combat anchors, pacing
                               anchors
- docs/balancing/derived.md  - current tuned state of all derived
                               numbers, mirroring the configs
- docs/balancing/process.md  - pass order, tuning discipline learned in
                               arena rounds 1-5, tools, next-round
                               checklist
- docs/balancing/history.md  - chronological record: decisions, numbers
                               pass, calculator bugs, arena rounds,
                               pacing pass
- docs/balancing/README.md   - index, status, open action items (moved
                               from progression_design.md)

content_design.md slims back down to actual content: footprint gating,
hull grids, gating matrix (module names updated to railguns), and the
production tree structure with its fiction - numbers, anchors, arena
logs, and pacing all moved to docs/balancing/. Stale references in the
config comments updated to the new locations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DyCu8vwChKMbLJQ3xosYEN
2026-07-06 17:15:08 +02:00

12 KiB
Raw Blame History

Content Design — Ships, Modules & Production Tree

The designed game content: hull layout grids, module footprints and the gating between them, and the production tree (items, chains, fiction). All numbers — quantities, durations, threat values, stats, unlock levels — live in the config files and are documented with their derivations in docs/balancing/ (see balancing/README.md for the index).

Design principle: footprint gating

Which module fits on which hull is controlled purely by geometry — no explicit allow-lists. Each hull grid is shaped so that it physically cannot contain the footprint of modules from a larger size class. This keeps the rules transparent to the player ("it doesn't fit because there is no room") and makes them trivially moddable through the config files alone.

Module footprint ladder

Footprint Modules Smallest hull that fits it
1x1 railgun_s, salvager, repair_tool drone
1x2 maneuvering_thrusters, sensor_booster, armor_plates frigate
1x3 afterburner frigate (eats most of it)
L-shape (3 cells) weapon_stabilizer, weapon_primer, weapon_upgrade frigate
2x2 railgun_m, drone_bay cruiser
3x3 railgun_l battleship
2x6 drone_hangar carrier (only)

Hull grids

O = buildable cell, X = hull structure (not buildable).

drone (xs, 1 cell) — exactly one 1x1 module: a small gun, a salvager, or a repair tool. This is what makes drone roles swappable.

O

frigate (s, 5 cells) — plus shape. Every 1x2 placement crosses the center cell, so at most ONE 1x2 support fits; alternatively one L-shaped weapon modifier or one afterburner through the center line. Gun-boat with one or two support modules, as intended.

XOX
OOO
XOX

destroyer (s, 8 cells) — gun deck with three turret bumps. More cells than the frigate (more small guns), but still no 2x2 area anywhere, so medium hardware can never be mounted.

OXOXO
OOOOO

cruiser (m, 12 cells) — notched corners. Fits at most two 2x2 m guns (stacked through the middle), leaving the side cells for supports. No 3x3 area.

XOOX
OOOO
OOOO
XOOX

battlecruiser (m, 16 cells) — split bow with two gun cheeks, tapered stern. Fits three 2x2 m guns — one more than the cruiser — with small support slots left over. The bow split and stern taper prevent any 3x3 area (no l gun) and any 2x6 area (no drone hangar).

OOXXOO
OOOOOO
XOOOOX
XXOOXX

battleship (l, 24 cells) — broadside hull with notched flanks on every other row. Fits four 2x2 m guns (two per gun deck) — one more than the battlecruiser — with bow, stern, and flank cells for supports. All 3x3 placements crowd the center columns, so at most ONE l gun fits: mounted center it blocks every m gun mount (pure support strips remain), mounted offset it still allows two m guns. The notched rows are never adjacent-and- full, so no 2x6 drone hangar fits.

XOOOOX
OOOOOO
XOOOOX
OOOOOO
XOOOOX

dreadnought (xl, 36 cells) — the main battery deck is split into three 3x3 gun slots by structural spacer columns, so exactly three l guns fit side by side (or m guns / supports in unused slots), plus bow/stern strips for supports. The spacers cap every horizontal run at 5 cells, so the 2x6 drone hangar can never fit — the carrier stays the only hangar hull.

XXXOOOOOXXX
OOOXOOOXOOO
OOOXOOOXOOO
OOOXOOOXOOO
XXOOXXXOOXX

carrier (xl, 37 cells) — the top flight deck (rows 01) is the only region wide enough for the 2x6 drone hangar, and exactly one fits. The middle deck row is broken up by elevator shafts (X cells placed so every 3-column window hits one), which is what prevents any 3x3 l gun from ever fitting. Lower decks hold supports and 2x2 point-defense m guns.

XOOOOOOOOX
OOOOOOOOOO
OOXOOXOOXO
XOOOOOOOOX
XXXOOOOXXX

Verified gating matrix

Checked programmatically against the configs (all four mask rotations, all placements) with tools/verify_layouts.py — re-run it after editing layout grids or surface masks:

python dota_factory/tools/verify_layouts.py
Footprint drone frigate destroyer cruiser battlecruiser battleship dreadnought carrier
1x1 x x x x x x x x
1x2 x x x x x x x
1x3 x x x x x x x
L-shape x x x x x x x
2x2 x x x x x
3x3 x x
2x6 x

Maximum simultaneous (disjoint) placements: m guns — cruiser 2, battlecruiser 3, battleship 4; l guns — battleship 1, dreadnought 3; drone hangar — carrier 1.

Production tree

Designed against the rules in docs/balancing/rules.md (ratio curve, cost ladder, cost archetypes, refactorability). Quantities, durations, and threat values live in docs/balancing/derived.md.

Base inputs (4) and fiction

  • iron_ore, copper_ore — from the start, minable on every asteroid tile. Fiction: the asteroid is an M-type (metal) body — its bulk rock is ore, which is why the shipyard operation was built here at all.
  • quartz — mid-game, minable only on geode deposit patches in expansion territory (see the Resource deposits rules in docs/balancing/rules.md; the deposit mechanic itself is an open action item — until it lands, quartz mines anywhere). Fiction: ordinary silicate dust is everywhere and worthless; chips and optics need rare, pocket-bound optical-grade crystal.
  • voidsteel — late-game, obtained only by reprocessing scrap. Fiction: battle-forged — formed when weapon plasma anneals hull metal in the violence of ship destruction. Any wreck yields it, including the player's own; no foundry can replicate it.
  • titanium was dropped (v1 tree). Its hull-gating role moved to quartz-era control systems ("you can smelt all the steel you want, but you cannot steer a battlecruiser without electronics") plus the hardened-steel quality step (a deliberately long-running, time-heavy recipe) — explicitly not sheer steel quantity alone.

Material palette (fingerprints per family)

  • iron/steel — structure.
  • copper — conduction and heat: wiring, coils, heat sinks.
  • silicon family (all derived from quartz): silicon (logic, sensors), ceramics (heat shielding, insulators); glass/optics are cut from v1 — their only consumers would be lasers, which are deferred.
  • voidsteel — capital-tier structure and exotics.
  • Deliberately skipped: carbon (mostly redundant with copper/ceramics), plastics (drags in Factorio-style chemical chains; ceramics read more sci-fi anyway), volatiles/ice (materials are build costs only — no consumption mechanic to justify fuel).

Weapons

  • All v1 weapons are railguns (railgun_s/m/l, renamed from the laser placeholders; footprints and the gating matrix unchanged). Implementation is instant damage application with no projectile and no ammunition — the beam visual reads as a tracer round. Materials: iron slugs, copper coils, steel rails — the starting-metal fingerprint.
  • Lasers are reserved for later as a genuinely distinct weapon type (e.g. once projectile/ammunition mechanics exist for other families), arriving with quartz optics. More weapon types are planned; railguns are simply the baseline tech that ships with v1.
  • drone_bay and drone_hangar are footprint-only placeholders: the drone-launching capability does not exist in the simulation yet, so they define no capability section. The carrier is deliberately weak until that capability lands (see the accepted imbalances in docs/balancing/targets.md).

Tree structure

Input lists only — quantities, durations, and per-item threat values are in docs/balancing/derived.md and the configs.

Mined (miner): iron_ore, copper_ore (every tile), quartz (geode deposits in expansion territory).

Smelted (smelter — exactly one recipe per input item):

output input ratio class
iron_ingot iron_ore nice (1:1)
copper_ingot copper_ore nice
silicon quartz mid entry
iron_ingot scrap the safe, boring scrap sink

Reprocessing pool (scrap): iron_ingot, copper_ingot, silicon, voidsteel — the only source of voidsteel. Weights authored for the fully unlocked pool state.

Tier 2 — early intermediates (clean ratios, ~2:3):

item inputs role
steel_plate iron_ingot structure backbone, highest volume
copper_wire copper_ingot conductors
copper_coil copper_wire electromagnets: railguns, thrusters
building_block steel_plate depth-3 chain = the doubling-time knob

Tier 3 — mid intermediates (strange ratios begin, need quartz):

item inputs role
control_chip silicon + copper_wire electronics gate for m+ hulls
capacitor_bank copper_coil + silicon power for railgun m/l
hardened_steel steel_plate (long cycle) quality gate for m+ hulls; time-heavy
ceramic_plate quartz heat shielding: drives, l guns, capitals
drive_unit steel_plate + copper_coil + control_chip propulsion for m+ hulls

Tier 4 — late intermediates (need voidsteel):

item inputs role
voidsteel_plate voidsteel + hardened_steel capital structure
capital_core voidsteel + capacitor_bank + control_chip capital heart

Hull items (<ship>_hull, assembler-made; the shipyard consumes the hull item plus module materials). The m+ hull gate is both hardened_steel (quality steel, the time-heavy step) and control_chip (electronics):

hull inputs
drone_hull iron_ingot
frigate_hull steel_plate + copper_wire
destroyer_hull steel_plate + copper_coil
cruiser_hull hardened_steel + control_chip
battlecruiser_hull hardened_steel + control_chip + drive_unit
battleship_hull voidsteel_plate + drive_unit + control_chip
dreadnought_hull voidsteel_plate + capital_core + drive_unit
carrier_hull voidsteel_plate + capital_core + drive_unit

Module items (<module>_module, assembler-made prefabs — kept as items so shipyard belt inputs stay simple and module production can be stockpiled):

module inputs archetype
railgun_s copper_coil lean
salvager steel_plate + copper_wire balanced
repair_tool steel_plate + copper_wire balanced
armor_plates steel_plate (many) material-heavy, fast
maneuvering_thrusters steel_plate + copper_coil balanced
sensor_booster copper_wire + copper_coil lean (an antenna, no chip)
afterburner copper_coil + steel_plate balanced
weapon_stabilizer steel_plate + copper_coil balanced
weapon_primer capacitor_bank + copper_coil mid; time-heavy
weapon_upgrade control_chip + copper_coil mid; time-heavy
railgun_m capacitor_bank + steel_plate + copper_coil mid
drone_bay control_chip + steel_plate + copper_coil mid
railgun_l capacitor_bank + hardened_steel + ceramic_plate late
drone_hangar voidsteel_plate + control_chip + drive_unit late (carrier only)

Refactorability check (the default technique holds): railgun_s → m introduces capacitor_bank, built from a subset of the small gun's inputs (copper_coil) plus the new base resource (silicon); the m gun otherwise reuses the small gun's inputs. Hulls likewise: the cruiser adds hardening (fed by the existing steel line) and chips (fed by the new quartz territory) without touching the iron/copper core.

Shortcut recipes (drop-only assembler schematics; not every strange chain gets one): iron_ore → steel_plate (skips the ingot step on the highest-volume chain), quartz → control_chip (skips silicon), iron_ingot → hardened_steel (a nicer-ratio route past the deliberately awkward hardening step).

Consistency is checked by tools/verify_recipes.py — re-run it after editing recipes, ship/module materials, or visuals:

python dota_factory/tools/verify_recipes.py

It verifies every consumed item has a producer, every item has a visuals entry, flags orphaned items, and prints which items are reprocessing-only (currently exactly voidsteel).