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>
This commit is contained in:
parent
472de1d93e
commit
097e17f7aa
18 changed files with 567 additions and 12 deletions
|
|
@ -24,6 +24,8 @@ const CRAFTER_COLOR: Color = Color(1.0, 0.72, 0.25)
|
|||
const COMMAND_COLOR: Color = Color(0.55, 0.6, 1.0)
|
||||
const TRANSPORT_HUB_COLOR: Color = Color(0.95, 0.55, 0.85)
|
||||
const SHIP_LAB_COLOR: Color = Color(0.55, 0.95, 0.9)
|
||||
const GAS_BURNER_COLOR: Color = Color(0.95, 0.35, 0.15)
|
||||
const GAS_BURNER_ENERGY_COLOR: Color = Color(0.85, 0.95, 0.15)
|
||||
|
||||
# Ship lab: a test frame with a vessel held in it and instruments sweeping
|
||||
# over it. Reads as a workshop rather than a factory - the crafter already
|
||||
|
|
@ -278,6 +280,42 @@ func _animate_transport_hub() -> void:
|
|||
_hub_traffic.rotation = phase_time * HUB_SPIN_SPEED
|
||||
|
||||
|
||||
# --- gas burner (#54) ------------------------------------------------------
|
||||
# A squat furnace rather than more scaffolding: a hexagonal combustion
|
||||
# chamber with a hot inner core, fed by intake vents drawn in gas's own
|
||||
# colour and exhausting through ports glowing in energy's colour - so the
|
||||
# structure itself reads as "gas in, energy out" without needing a label.
|
||||
# Drawn once and never redrawn, same as the command centre.
|
||||
|
||||
const BURNER_CHAMBER_RADIUS: float = 50.0
|
||||
const BURNER_CORE_RADIUS: float = 34.0
|
||||
const BURNER_VENT_COUNT: int = 4
|
||||
const BURNER_VENT_LENGTH: float = 26.0
|
||||
const BURNER_PORT_RADIUS: float = 6.0
|
||||
|
||||
|
||||
func _draw_gas_burner_static(target: CanvasItem) -> void:
|
||||
var c: Color = GAS_BURNER_COLOR
|
||||
|
||||
NeonDraw.draw_glowing_polygon(target, _ring(Vector2.ZERO, BURNER_CHAMBER_RADIUS, 6, PI / 6.0), c, 1.0)
|
||||
NeonDraw.draw_glowing_polygon(target, _ring(Vector2.ZERO, BURNER_CORE_RADIUS, 6, PI / 6.0), c, 0.5,
|
||||
NeonDraw.DEFAULT_CORE, 0.7)
|
||||
NeonDraw.draw_glowing_polygon(target, _ring(Vector2.ZERO, BURNER_CORE_RADIUS * 0.5, 6, PI / 6.0),
|
||||
Color(1.0, 0.75, 0.35), 0.85)
|
||||
|
||||
for i in range(BURNER_VENT_COUNT):
|
||||
var a: float = (float(i) / BURNER_VENT_COUNT) * TAU + PI / 4.0
|
||||
var dir: Vector2 = Vector2(cos(a), sin(a))
|
||||
var tip: Vector2 = dir * (BURNER_CHAMBER_RADIUS + BURNER_VENT_LENGTH)
|
||||
# Intake vent in gas's own colour, so it is unmistakably the feed
|
||||
# rather than another structural brace.
|
||||
NeonDraw.draw_glowing_line(target, dir * BURNER_CHAMBER_RADIUS, tip,
|
||||
Color(0.85, 0.52, 1.0), 0.7, 0.34)
|
||||
# Output port glowing in energy's colour, at the same vent tip -
|
||||
# the building's own silhouette shows both ends of the conversion.
|
||||
NeonDraw.draw_glowing_polygon(target, _ring(tip, BURNER_PORT_RADIUS, 5), GAS_BURNER_ENERGY_COLOR, 0.9)
|
||||
|
||||
|
||||
func _diamond(centre: Vector2, r: float) -> PackedVector2Array:
|
||||
return PackedVector2Array([
|
||||
centre + Vector2(0, -r), centre + Vector2(r, 0),
|
||||
|
|
|
|||
Loading…
Reference in a new issue