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
89 lines
1.8 KiB
TOML
89 lines
1.8 KiB
TOML
[[ship]]
|
|
id = "interceptor"
|
|
layout = ["XOX", "OOO", "XOX"]
|
|
default_modules = [{type = "laser_cannon", x = 1, y = 1, rotation = "east"}]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "iron_ingot", amount = 3}, {item = "circuit_board", amount = 1}]
|
|
production_time_seconds = 10
|
|
|
|
[ship.health]
|
|
hp = 45
|
|
|
|
[ship.movement]
|
|
speed_mps = 2050
|
|
main_acceleration_mpss = 1000000
|
|
maneuvering_acceleration_mpss = 1000000
|
|
angular_acceleration_radpss = 100000
|
|
max_rotation_speed_radps = 100000
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 2000
|
|
|
|
|
|
[[ship]]
|
|
id = "destroyer"
|
|
layout = ["XOOX", "OOOO", "XOOX"]
|
|
default_modules = [{type = "laser_cannon", x = 1, y = 1, rotation = "east"}]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "iron_ingot", amount = 5}, {item = "circuit_board", amount = 2}]
|
|
production_time_seconds = 20
|
|
|
|
[ship.health]
|
|
hp = 135
|
|
|
|
[ship.movement]
|
|
speed_mps = 1200
|
|
main_acceleration_mpss = 1000000
|
|
maneuvering_acceleration_mpss = 1000000
|
|
angular_acceleration_radpss = 100000
|
|
max_rotation_speed_radps = 100000
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 3000
|
|
|
|
|
|
[[ship]]
|
|
id = "salvage_ship"
|
|
layout = ["OOO", "OOO"]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "iron_ingot", amount = 4}]
|
|
production_time_seconds = 10
|
|
|
|
[ship.health]
|
|
hp = 44
|
|
|
|
[ship.movement]
|
|
speed_mps = 1100
|
|
main_acceleration_mpss = 1000000
|
|
maneuvering_acceleration_mpss = 1000000
|
|
angular_acceleration_radpss = 100000
|
|
max_rotation_speed_radps = 100000
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 2500
|
|
|
|
|
|
[[ship]]
|
|
id = "repair_ship"
|
|
layout = ["XOX", "OOO", "XOX"]
|
|
|
|
[ship.schematic]
|
|
materials = [{item = "iron_ingot", amount = 4}, {item = "circuit_board", amount = 2}]
|
|
production_time_seconds = 15
|
|
|
|
[ship.health]
|
|
hp = 65
|
|
|
|
[ship.movement]
|
|
speed_mps = 1300
|
|
main_acceleration_mpss = 1000000
|
|
maneuvering_acceleration_mpss = 1000000
|
|
angular_acceleration_radpss = 100000
|
|
max_rotation_speed_radps = 100000
|
|
|
|
[ship.sensor]
|
|
sensor_range_m = 2500
|