Lift unlocking into first-class unlock groups defined in unlocks.toml, so one defence-station drop can grant a bundle of ships/modules/buildings/ recipes at once (e.g. the salvager module + salvage bay), and buildings can now be locked at game start and unlocked via a drop. Config: - New UnlocksConfig + ConfigLoader::loadUnlocks + validateUnlocks (unknown/ duplicate/non-assembler grants, unknown requires, empty group all fail load). - Drop unlock_at_station_level/unlock_requires from ship/module/recipe defs; add unlocked_at_start bool to recipes for graph-unreachable base recipes. Simulation: - Track awarded groups + per-building unlock state; an item starts unlocked iff no group grants it. Rework generateSchematicChoices/applySchematicChoice to operate on groups (grant all members at once). Extend state checksum. - isBuildingUnlocked query; tryPlaceBuilding rejects locked types. UI: - Build-menu buttons for locked buildings start hidden, revealed via a new UnlockedBuildingsChangedEvent (emitted from GameWorldView's poll loop). - Schematic choice dialog lists a group's granted items. - Blueprint placement excludes locked building types (REQ-LOCK-UI-BLUEPRINT). Data: unlocks.toml (app + test) reproduces the prior per-item gates as singleton groups and adds salvage_operations (salvager + salvage_bay, lvl 1) and reprocessing (reprocessing_plant, lvl 2). Tests: rewrote unlock/config/recipe-schematic/artifact/wave/shipyard tests for the group model; added UnlockGroupTest. All 443 cases pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y7N59FsLA5e2kuVdqe4Uhc
312 lines
8.7 KiB
TOML
312 lines
8.7 KiB
TOML
# ships.toml
|
|
#
|
|
# First real-content iteration: ship ids and layout grids are the designed
|
|
# content; stats, materials, and production times are placeholders until the
|
|
# recipe and balancing passes.
|
|
#
|
|
# Unlock gating is defined in unlocks.toml, not here (REQ-LOCK-EXPLICIT): a ship
|
|
# id granted by an unlock group starts locked and is awarded via a defence
|
|
# station drop; ids absent from unlocks.toml (drone, frigate) start unlocked.
|
|
#
|
|
# Size classes:
|
|
# xs drone 1 cell — exactly one 1x1 module
|
|
# s frigate, destroyer no 2x2 area anywhere: only 1x1/1x2/1x3/L modules fit
|
|
# m cruiser, battlecruiser 2x2 areas (m guns, drone bays) but no 3x3 area
|
|
# l battleship four m guns, or exactly one 3x3 l gun at heavy
|
|
# opportunity cost
|
|
# xl dreadnought, carrier dreadnought fits three l guns but no drone
|
|
# hangar; carrier fits one drone hangar (2x6)
|
|
# but no l gun (its deck rows are broken up
|
|
# by elevator shafts)
|
|
|
|
[[ship]]
|
|
id = "drone"
|
|
layout = ["O"]
|
|
default_modules = [{type = "railgun_s", x = 0, y = 0, rotation = "east"}]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "drone_hull", amount = 1}]
|
|
production_time_seconds = 1
|
|
|
|
[ship.health]
|
|
hp = 60
|
|
|
|
[ship.movement]
|
|
speed_mps = 45
|
|
main_acceleration_mpss = 60
|
|
maneuvering_acceleration_mpss = 30
|
|
angular_acceleration_radpss = 12
|
|
max_rotation_speed_radps = 6
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 150
|
|
|
|
|
|
# Frigate — 5 cells in a plus shape. Holds a couple of small guns plus at
|
|
# most one 1x2 support (every 1x2 placement crosses the center cell), or one
|
|
# L-shaped weapon modifier, or an afterburner spanning the full center line.
|
|
[[ship]]
|
|
id = "frigate"
|
|
layout = [
|
|
"XOX",
|
|
"OOO",
|
|
"XOX",
|
|
]
|
|
default_modules = [
|
|
{type = "railgun_s", x = 1, y = 0, rotation = "east"},
|
|
{type = "railgun_s", x = 2, y = 1, rotation = "east"},
|
|
{type = "maneuvering_thrusters", x = 0, y = 1, rotation = "east"},
|
|
]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "frigate_hull", amount = 1}]
|
|
production_time_seconds = 2
|
|
|
|
[ship.health]
|
|
hp = 300
|
|
|
|
[ship.movement]
|
|
speed_mps = 35
|
|
main_acceleration_mpss = 45
|
|
maneuvering_acceleration_mpss = 22
|
|
angular_acceleration_radpss = 8
|
|
max_rotation_speed_radps = 4
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 200
|
|
|
|
|
|
# Destroyer — 8 cells: a long gun deck with three turret bumps on top.
|
|
# Still no 2x2 area, so it packs more small guns than a frigate but can never
|
|
# mount medium hardware.
|
|
[[ship]]
|
|
id = "destroyer"
|
|
layout = [
|
|
"OXOXO",
|
|
"OOOOO",
|
|
]
|
|
default_modules = [
|
|
{type = "railgun_s", x = 0, y = 0, rotation = "east"},
|
|
{type = "railgun_s", x = 2, y = 0, rotation = "east"},
|
|
{type = "railgun_s", x = 4, y = 0, rotation = "east"},
|
|
{type = "armor_plates", x = 0, y = 1, rotation = "east"},
|
|
{type = "sensor_booster", x = 3, y = 1, rotation = "east"},
|
|
]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "destroyer_hull", amount = 1}]
|
|
production_time_seconds = 3
|
|
|
|
[ship.health]
|
|
hp = 550
|
|
|
|
[ship.movement]
|
|
speed_mps = 30
|
|
main_acceleration_mpss = 35
|
|
maneuvering_acceleration_mpss = 18
|
|
angular_acceleration_radpss = 6
|
|
max_rotation_speed_radps = 3
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 220
|
|
|
|
|
|
# Cruiser — 12 cells with notched corners. Fits at most two 2x2 m guns
|
|
# (stacked through the middle), leaving the four side cells for small
|
|
# supports; no 3x3 area exists for an l gun.
|
|
[[ship]]
|
|
id = "cruiser"
|
|
layout = [
|
|
"XOOX",
|
|
"OOOO",
|
|
"OOOO",
|
|
"XOOX",
|
|
]
|
|
default_modules = [
|
|
{type = "railgun_m", x = 0, y = 1, rotation = "east"},
|
|
{type = "railgun_m", x = 2, y = 1, rotation = "east"},
|
|
{type = "armor_plates", x = 1, y = 0, rotation = "east"},
|
|
{type = "maneuvering_thrusters", x = 1, y = 3, rotation = "east"},
|
|
]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "cruiser_hull", amount = 1}]
|
|
production_time_seconds = 4
|
|
|
|
[ship.health]
|
|
hp = 1500
|
|
|
|
[ship.movement]
|
|
speed_mps = 24
|
|
main_acceleration_mpss = 25
|
|
maneuvering_acceleration_mpss = 12
|
|
angular_acceleration_radpss = 4
|
|
max_rotation_speed_radps = 2
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 250
|
|
|
|
|
|
# Battlecruiser — 16 cells: a wide bow split into two gun cheeks, tapering
|
|
# toward the stern. Fits three 2x2 m guns (two in the cheeks, one through
|
|
# the middle) with small support slots left over; the split bow and tapered
|
|
# stern leave no 3x3 area for an l gun and no 2x6 area for a drone hangar.
|
|
[[ship]]
|
|
id = "battlecruiser"
|
|
layout = [
|
|
"OOXXOO",
|
|
"OOOOOO",
|
|
"XOOOOX",
|
|
"XXOOXX",
|
|
]
|
|
default_modules = [
|
|
{type = "railgun_m", x = 0, y = 0, rotation = "east"},
|
|
{type = "railgun_m", x = 4, y = 0, rotation = "east"},
|
|
{type = "railgun_m", x = 2, y = 1, rotation = "east"},
|
|
{type = "armor_plates", x = 2, y = 3, rotation = "east"},
|
|
{type = "railgun_s", x = 1, y = 2, rotation = "east"},
|
|
{type = "railgun_s", x = 4, y = 2, rotation = "east"},
|
|
]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "battlecruiser_hull", amount = 1}]
|
|
production_time_seconds = 5
|
|
|
|
[ship.health]
|
|
hp = 2400
|
|
|
|
[ship.movement]
|
|
speed_mps = 20
|
|
main_acceleration_mpss = 20
|
|
maneuvering_acceleration_mpss = 10
|
|
angular_acceleration_radpss = 3
|
|
max_rotation_speed_radps = 1.5
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 260
|
|
|
|
|
|
# Battleship — 24 cells: a broadside hull with notched flanks on every other
|
|
# row. Fits four 2x2 m guns (two per gun deck) with the bow, stern, and flank
|
|
# cells left for supports. All 3x3 placements crowd the center columns, so at
|
|
# most ONE l gun fits — and mounting it blocks every m gun mount, leaving
|
|
# only narrow support strips. The notched rows are never adjacent-and-full,
|
|
# so no 2x6 drone hangar fits.
|
|
[[ship]]
|
|
id = "battleship"
|
|
layout = [
|
|
"XOOOOX",
|
|
"OOOOOO",
|
|
"XOOOOX",
|
|
"OOOOOO",
|
|
"XOOOOX",
|
|
]
|
|
default_modules = [
|
|
{type = "railgun_l", x = 1, y = 0, rotation = "east"},
|
|
{type = "railgun_m", x = 1, y = 3, rotation = "east"},
|
|
{type = "railgun_m", x = 3, y = 3, rotation = "east"},
|
|
{type = "weapon_stabilizer", x = 4, y = 1, rotation = "east"},
|
|
{type = "railgun_s", x = 4, y = 0, rotation = "east"},
|
|
{type = "railgun_s", x = 0, y = 1, rotation = "east"},
|
|
]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "battleship_hull", amount = 1}]
|
|
production_time_seconds = 6
|
|
|
|
[ship.health]
|
|
hp = 6300
|
|
|
|
[ship.movement]
|
|
speed_mps = 15
|
|
main_acceleration_mpss = 14
|
|
maneuvering_acceleration_mpss = 7
|
|
angular_acceleration_radpss = 2
|
|
max_rotation_speed_radps = 1
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 280
|
|
|
|
|
|
# Dreadnought — 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). The spacers cap every
|
|
# horizontal run at 5 cells, so the 2x6 drone hangar can never fit — carriers
|
|
# stay the only hangar hull. Bow and stern strips hold supports.
|
|
[[ship]]
|
|
id = "dreadnought"
|
|
layout = [
|
|
"XXXOOOOOXXX",
|
|
"OOOXOOOXOOO",
|
|
"OOOXOOOXOOO",
|
|
"OOOXOOOXOOO",
|
|
"XXOOXXXOOXX",
|
|
]
|
|
default_modules = [
|
|
{type = "railgun_l", x = 0, y = 1, rotation = "east"},
|
|
{type = "railgun_l", x = 4, y = 1, rotation = "east"},
|
|
{type = "railgun_l", x = 8, y = 1, rotation = "east"},
|
|
{type = "armor_plates", x = 3, y = 0, rotation = "east"},
|
|
{type = "armor_plates", x = 5, y = 0, rotation = "east"},
|
|
{type = "armor_plates", x = 2, y = 4, rotation = "east"},
|
|
{type = "armor_plates", x = 7, y = 4, rotation = "east"},
|
|
{type = "railgun_s", x = 7, y = 0, rotation = "east"},
|
|
]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "dreadnought_hull", amount = 1}]
|
|
production_time_seconds = 8
|
|
|
|
[ship.health]
|
|
hp = 24000
|
|
|
|
[ship.movement]
|
|
speed_mps = 10
|
|
main_acceleration_mpss = 8
|
|
maneuvering_acceleration_mpss = 4
|
|
angular_acceleration_radpss = 1
|
|
max_rotation_speed_radps = 0.5
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 300
|
|
|
|
|
|
# Carrier — 37 cells: the top flight deck (rows 0-1) is the only place wide
|
|
# enough for the 2x6 drone hangar, and exactly one fits. The middle deck row
|
|
# is broken up by elevator shafts (the X cells) so no 3x3 l gun can ever fit;
|
|
# the lower decks hold supports and 2x2 point-defense m guns.
|
|
[[ship]]
|
|
id = "carrier"
|
|
layout = [
|
|
"XOOOOOOOOX",
|
|
"OOOOOOOOOO",
|
|
"OOXOOXOOXO",
|
|
"XOOOOOOOOX",
|
|
"XXXOOOOXXX",
|
|
]
|
|
default_modules = [
|
|
{type = "drone_hangar", x = 2, y = 0, rotation = "east"},
|
|
{type = "railgun_m", x = 3, y = 2, rotation = "east"},
|
|
{type = "railgun_m", x = 6, y = 2, rotation = "east"},
|
|
{type = "armor_plates", x = 0, y = 1, rotation = "east"},
|
|
{type = "armor_plates", x = 8, y = 1, rotation = "east"},
|
|
{type = "sensor_booster", x = 3, y = 4, rotation = "east"},
|
|
]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "carrier_hull", amount = 1}]
|
|
production_time_seconds = 8
|
|
|
|
[ship.health]
|
|
hp = 24000
|
|
|
|
[ship.movement]
|
|
speed_mps = 10
|
|
main_acceleration_mpss = 8
|
|
maneuvering_acceleration_mpss = 4
|
|
angular_acceleration_radpss = 1
|
|
max_rotation_speed_radps = 0.5
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 350
|