spaceship/buildings/GasBurnerBuildingDefinition.tres

34 lines
1.2 KiB
Text
Raw Normal View History

Garrison laser vessels and gas bombers, on a shared ability seam #105 shipped with interceptors as the only garrisonable vessel, and the reason was a design fault rather than a decision: firing the laser and the gas bomb lived in the player's fleet controllers, so a stationed laser would have held its position and never shot. The shot is now a thing in the world rather than something a controller draws. LaserBeamEffect and GasBombEffect are self-contained, self-animating and self-freeing, added to the tree root - the same shape EnemyBigLaserBeam and ArtilleryShell already had on the enemy side - and they outlive the vessel that fired them. Above them sits one seam, on VesselCooldownFillComponent: ability_range(), ability_ammo_resource(), ability_ammo_cost() and fire_ability(). A beam and a bomb are now the same shape of thing to whoever pulls the trigger, so the garrison AI never names an ability - the test asserts that literally, by reading the AI's own source. A third armed vessel needs to implement the seam and nothing else. Ammunition is the CALLER's business, deliberately: the fleet spends from its hold, a garrison from its outpost's store, and neither concern belongs in the component. A garrison with an empty magazine holds fire rather than falling back on the fleet's hold. Outpost storage: 50 gas per stationed bomber and 50 energy per stationed laser, off the VESSEL definitions, so an outpost never learns which vessel needs what. It is a capacity, not a stock - hub transporters fill it exactly as they fill a gas burner's buffer, because building_logistics_deficit now takes the larger of the definition's static buffer and the garrison's magazine. Every other resource is capped at zero: an outpost is not a depot, and ore parked at one has nothing to do there and no transporter coming for it. Also restores two properties the Godot editor dropped from GasBurnerBuildingDefinition.tres when it re-saved the file: collected_outputs and capabilities. Without the first, nothing ever collects the burner's energy - test_gas_burner caught it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 19:23:35 +02:00
[gd_resource type="Resource" script_class="BuildingDefinition" format=3 uid="uid://cia6vbju65sbe"]
[ext_resource type="Script" uid="uid://d10s0frtxiw62" path="res://buildings/BuildingDefinition.gd" id="1"]
#84: move 215 root files into a folder hierarchy Everything lived in one flat directory, so a diff gave no clue what area it touched and finding the file you wanted meant knowing its exact name. Twelve folders now, grouped by what a thing IS rather than what type it is - a vessel's definition, its component scenes and its upgrade resources sit together, because that is the set you read when you change one of them. buildings core controllers enemies logistics planets resources shaders surface ui vessels vfx world 332 files moved and every res:// reference rewritten - 306 files touched, including the autoload and main-scene paths in project.godot. Nothing renamed: this is purely where files sit, so the diff is a pile of pure moves and no behaviour is buried in it. ui_theme.tres, icon.svg and web_shell.html stay at the root, where Godot and the export preset expect them. Verified three ways, because a suite alone would not have caught all of it: the full 117 pass, the web export builds clean, and the game renders. The export is why that matters. The FIRST export after the move failed with "Attempt to open script 'res://GameState.gd'" - the old path - while project.godot on disk plainly said res://core/GameState.gd. That is this project's documented Android FUSE mtime trap: Godot served a cached copy of a file whose content had changed. A `touch` fixed it. Nothing in the test suite would have found that, because the suite runs from a copy on a native filesystem - the one place the bug cannot happen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 19:44:14 +02:00
[ext_resource type="PackedScene" path="res://buildings/GasBurnerBuildingVisual.tscn" id="2"]
Garrison laser vessels and gas bombers, on a shared ability seam #105 shipped with interceptors as the only garrisonable vessel, and the reason was a design fault rather than a decision: firing the laser and the gas bomb lived in the player's fleet controllers, so a stationed laser would have held its position and never shot. The shot is now a thing in the world rather than something a controller draws. LaserBeamEffect and GasBombEffect are self-contained, self-animating and self-freeing, added to the tree root - the same shape EnemyBigLaserBeam and ArtilleryShell already had on the enemy side - and they outlive the vessel that fired them. Above them sits one seam, on VesselCooldownFillComponent: ability_range(), ability_ammo_resource(), ability_ammo_cost() and fire_ability(). A beam and a bomb are now the same shape of thing to whoever pulls the trigger, so the garrison AI never names an ability - the test asserts that literally, by reading the AI's own source. A third armed vessel needs to implement the seam and nothing else. Ammunition is the CALLER's business, deliberately: the fleet spends from its hold, a garrison from its outpost's store, and neither concern belongs in the component. A garrison with an empty magazine holds fire rather than falling back on the fleet's hold. Outpost storage: 50 gas per stationed bomber and 50 energy per stationed laser, off the VESSEL definitions, so an outpost never learns which vessel needs what. It is a capacity, not a stock - hub transporters fill it exactly as they fill a gas burner's buffer, because building_logistics_deficit now takes the larger of the definition's static buffer and the garrison's magazine. Every other resource is capped at zero: an outpost is not a depot, and ore parked at one has nothing to do there and no transporter coming for it. Also restores two properties the Godot editor dropped from GasBurnerBuildingDefinition.tres when it re-saved the file: collected_outputs and capabilities. Without the first, nothing ever collects the burner's energy - test_gas_burner caught it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 19:23:35 +02:00
[ext_resource type="Script" uid="uid://cydp18abylrgd" path="res://buildings/BuildingLogisticsProfile.gd" id="3"]
[sub_resource type="Resource" id="Resource_logistics"]
script = ExtResource("3")
input_buffers = {
"gas": 40
}
collected_outputs = PackedStringArray("energy")
conversion_input = "gas"
conversion_output = "energy"
conversion_rate = 1.0
conversion_yield = 2
Gas burner building and the energy resource (#54) A new building that consumes gas to produce energy, a new resource stored and moved exactly like ore and gas. The resource: EnergyResourceGlyph (a cell/bolt mark) + energy's own warm yellow-green ResourceDefinition, registered in ResourceDefinitions.ORDER/DEFINITIONS and GameState.RESOURCE_ENERGY. Inventory/ResourceBar/ResourceTransferList needed no changes - #49 already made them resource-agnostic, confirmed structurally in the test rather than touched. The building: GasBurnerBuildingVisual (a hexagonal chamber with intake vents in gas's colour and output ports in energy's, so the silhouette itself reads "gas in, energy out"), GasBurnerBuildingDefinition (capabilities=["gas_burner"], its own build-menu icon appended to IconButton.Icon rather than inserted, per the ticket's own warning about renumbering stored scene values), and the matching UI/BuildMenu/GasBurner* nodes in Main.tscn. Gated behind a new "Power Systems" skill-tree node, mirroring how "freight" unlocks the transport hub. Conversion: _advance_gas_burners(), simulated in GameState alongside _advance_production/extractor mining so it keeps running while the player is elsewhere. Withdraws gas and deposits energy in the building's OWN inventory only - never the bank - so it stalls with no local gas exactly like a lab waiting on materials. Logistics: a gas burner's ongoing gas deficit is folded into the existing queued-building-supply dispatch path (same "needs resource X" loop production/research orders already use, extended with gas_burner_gas_deficit()), and a new TO_BUILDING_PICKUP/ TO_MOTHERSHIP_FROM_BUILDING transporter state pair collects its energy to the bank, mirroring the extractor pickup path per the ticket. The existing f5c60f8 priority (queued deliveries outrank collection) holds: the pickup dispatch loop runs last. Tests: new tests/test_gas_burner.gd (resource genericity, stall semantics, research gate, and full delivery+pickup logistics via a real hub), run_tests transporter/resource regressions, and screenshots of the build menu (all 7 buildings) and transfer menu (all 3 resources). Full suite: 81/81. Two real bugs found and fixed along the way, neither gas-burner- specific: - _transporter_inbound_to() matched ANY non-idle transporter with a matching target_id, regardless of purpose. Once pickup states shared target_id with delivery states (both address a building, not an extractor), a transporter delivering gas made the SAME building look "busy" to the unrelated energy-pickup dispatch, starving it even with a second, genuinely free transporter sitting idle at the hub. Split into _transporter_inbound_to() (delivery states only) and a new _transporter_inbound_for_pickup() (pickup states only). - The build menu's 3-row/6-slot layout (MENU_ROW_TOPS + row content sizing) had no room for a 7th building - despite the ticket's own note that no layout changes should be needed. A naive 4th row ran off the bottom of a 720x1280 viewport; fitting one meant both adding a 4th row top AND shrinking the shared button/label/cost sizing so each row's content no longer taller than the compressed row spacing. Caught only by actually screenshotting it - a real build menu, not headless, since --headless renders nothing. 🤖 Generated with Claude Code Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 12:10:31 +02:00
[resource]
script = ExtResource("1")
definition_id = "gas_burner"
display_name = "Gas Burner"
description = "Burns gas into energy at its own site. Hub transporters keep it stocked with gas and collect the energy it makes."
cost = 30
action_icon = 33
menu_icon = 33
visual_scene = ExtResource("2")
capabilities = PackedStringArray("gas_burner")
logistics = SubResource("Resource_logistics")
Gas burner building and the energy resource (#54) A new building that consumes gas to produce energy, a new resource stored and moved exactly like ore and gas. The resource: EnergyResourceGlyph (a cell/bolt mark) + energy's own warm yellow-green ResourceDefinition, registered in ResourceDefinitions.ORDER/DEFINITIONS and GameState.RESOURCE_ENERGY. Inventory/ResourceBar/ResourceTransferList needed no changes - #49 already made them resource-agnostic, confirmed structurally in the test rather than touched. The building: GasBurnerBuildingVisual (a hexagonal chamber with intake vents in gas's colour and output ports in energy's, so the silhouette itself reads "gas in, energy out"), GasBurnerBuildingDefinition (capabilities=["gas_burner"], its own build-menu icon appended to IconButton.Icon rather than inserted, per the ticket's own warning about renumbering stored scene values), and the matching UI/BuildMenu/GasBurner* nodes in Main.tscn. Gated behind a new "Power Systems" skill-tree node, mirroring how "freight" unlocks the transport hub. Conversion: _advance_gas_burners(), simulated in GameState alongside _advance_production/extractor mining so it keeps running while the player is elsewhere. Withdraws gas and deposits energy in the building's OWN inventory only - never the bank - so it stalls with no local gas exactly like a lab waiting on materials. Logistics: a gas burner's ongoing gas deficit is folded into the existing queued-building-supply dispatch path (same "needs resource X" loop production/research orders already use, extended with gas_burner_gas_deficit()), and a new TO_BUILDING_PICKUP/ TO_MOTHERSHIP_FROM_BUILDING transporter state pair collects its energy to the bank, mirroring the extractor pickup path per the ticket. The existing f5c60f8 priority (queued deliveries outrank collection) holds: the pickup dispatch loop runs last. Tests: new tests/test_gas_burner.gd (resource genericity, stall semantics, research gate, and full delivery+pickup logistics via a real hub), run_tests transporter/resource regressions, and screenshots of the build menu (all 7 buildings) and transfer menu (all 3 resources). Full suite: 81/81. Two real bugs found and fixed along the way, neither gas-burner- specific: - _transporter_inbound_to() matched ANY non-idle transporter with a matching target_id, regardless of purpose. Once pickup states shared target_id with delivery states (both address a building, not an extractor), a transporter delivering gas made the SAME building look "busy" to the unrelated energy-pickup dispatch, starving it even with a second, genuinely free transporter sitting idle at the hub. Split into _transporter_inbound_to() (delivery states only) and a new _transporter_inbound_for_pickup() (pickup states only). - The build menu's 3-row/6-slot layout (MENU_ROW_TOPS + row content sizing) had no room for a 7th building - despite the ticket's own note that no layout changes should be needed. A naive 4th row ran off the bottom of a 720x1280 viewport; fitting one meant both adding a 4th row top AND shrinking the shared button/label/cost sizing so each row's content no longer taller than the compressed row spacing. Caught only by actually screenshotting it - a real build menu, not headless, since --headless renders nothing. 🤖 Generated with Claude Code Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 12:10:31 +02:00
map_color = Color(0.95, 0.35, 0.15, 1)
map_sides = 5
menu_button_name = "GasBurnerButton"
menu_label_name = "GasBurnerLabel"
menu_cost_name = "GasBurnerCost"
max_hp = 60