Gas burner building and the energy resource #54
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A new building that consumes gas to produce energy, a new resource stored and moved exactly like ore and gas.
Depends on #49 (generalize the resource HUD readouts) - without it, energy needs two more hand-placed nodes in two scenes.
Scope
EnergyResourceGlyph.tscn+.gddrawn withNeonDraw(a cell/bolt mark; seeGasResourceGlyph.gdfor the shape of one).EnergyResourceDefinition.tres:resource_id = "energy", display name, its own colour (suggest a warm yellow-green, clearly distinct from ore teal, gas pink, and the amber in-transit colour).ENERGY_IDtoResourceDefinitionsand append it toORDERandDEFINITIONS.const RESOURCE_ENERGYtoGameStatebesideRESOURCE_ORE/RESOURCE_GAS.Inventory,ResourceBarandResourceTransferListare already resource-agnostic and need no edit - confirm that in the test rather than touching them.GasBurnerBuildingVisual.tscn+.gdfollowingTransportHubBuildingVisualetc., composed throughBuildingVisualBase.GasBurnerBuildingDefinition.tres:definition_id = "gas_burner",capabilities = ["gas_burner"],placement_mode = "space", cost, action/menu icons (append newIconButton.Iconenum entries - inserting one silently renumbers every icon int already stored in scenes), map colour/sides, andmenu_button_name/menu_label_name/menu_cost_name.UI/BuildMenu/GasBurnerButton/GasBurnerLabel/GasBurnerCostnodes toMain.tscn.BuildController._layout_build_menu()already positions whatever is researched, so no layout code changes.GameStateautoload alongside_advance_production/extractor mining, so it keeps running while the player is landed or far away:const GAS_BURN_RATE: float(gas/second) andconst ENERGY_PER_GAS: int._advance_transporters(the priority rule fixed inf5c60f8- queued deliveries outrank extractor collection - must keep holding).SKILL_TREEnode unlockinggas_burner, mirroring howfreightunlocksBUILDING_TRANSPORT_HUB.Acceptance criteria
ResourceBarand the transfer menu with no per-resource code anywhere.Tests
tests/test_gas_burner.gd(bash tests/run_tests.sh burner), plusrun_tests.sh transporterandrun_tests.sh resourcefor regressions, and a 720x1280 screenshot of the build menu and transfer menu showing three resources laid out cleanly.Repo notes (read before starting)
/storage/emulated/0/GodotProjects/SpaceshipTest.touchon it. Android FUSE does not bump mtime under~/storage/shared, and Godot's import cache will silently keep serving the old version, making a correct fix look like it did nothing.bash tests/run_tests.sh <substring>; full suite with no argument. Tests areSceneTreescripts printingTEST_NAME: PASS/TEST_NAME: FAIL (reason)and callingquit(0|1)- copy the shape oftests/test_capture_points.gd.bash tests/screenshot.sh <res://Scene.tscn> <out.png> <frames> 720x1280. Use few frames (~15); the software rasterizer is slow.--headlessrenders nothing at all, so it cannot validate visuals.NeonDraw/NeonPiece; do not introduce a different visual idiom.*Definitionresources plus capability component scenes. Do not addif type == "..."branches.FileAccess, nouser://).GameStateis an in-memory autoload. Do not invent a save system.Traps that have already cost hours on this codebase
const X = preload(...)in a test file that is itself the-sentry point. It evaluates during that file's own early compilation, which can run before autoloads are registered; any script it pulls in that referencesGameStateinside a function body then fails to compile withIdentifier not found: GameState. Usevar X: Scriptplusload()inside_initialize()instead. See the header comment intests/test_capture_points.gd.[]to a typedArray[Resource]export from another script fails at runtime - the compiler only sees the target asResourceand cannot confirm the element type. Leave the declared default alone, or build the typed array inside the owning script.Fleet.spawn_ships(0, ...)does not empty the fleet - it falls back to one default interceptor by design. Clearfleet.shipsexplicitly if a test or preview needs genuinely zero ships.ship.positionwithout also settingship.move_targetletsShip._physics_processsteer it straight back toward the stale target within a few frames.SceneTreetest's own_process()clock under device load, even with--fixed-fps 60. Gate waits on the system's own state (a component's timer or flag), not onelapsed >= duration.queue_free()s itself (projectiles, shells) must not be re-read inside a per-frame wait condition - cache the scalar you need before the wait._screenshot_tool.gd's_initialize(), so their_ready()races the game scene's own_ready(). Do setup on the first_process()tick, andget_tree().paused = trueonce everything is placed if the scene must hold still.Done in commit
097e17f, pushed to main.The resource:
EnergyResourceGlyph(a cell/bolt mark) + energy's own warm yellow-greenResourceDefinition, registered inResourceDefinitions.ORDER/DEFINITIONSandGameState.RESOURCE_ENERGY.Inventory/ResourceBar/ResourceTransferListneeded 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 toIconButton.Iconrather than inserted, per the ticket's own warning about renumbering stored scene values), and the matchingUI/BuildMenu/GasBurner*nodes inMain.tscn. Gated behind a new "Power Systems" skill-tree node, mirroring how "freight" unlocks the transport hub.Conversion:
_advance_gas_burners(), simulated inGameStatealongside_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 newTO_BUILDING_PICKUP/TO_MOTHERSHIP_FROM_BUILDINGtransporter state pair collects its energy to the bank, mirroring the extractor pickup path. The existingf5c60f8priority (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/resourceregressions, and screenshots of the build menu (all 7 buildings,shots/gas_burner_build_menu.png) and transfer menu (all 3 resources,shots/gas_burner_transfer.png). 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 matchingtarget_id, regardless of purpose. Once pickup states sharedtarget_idwith 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).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 is no longer taller than the compressed row spacing. Caught only by actually screenshotting it - a real build menu, not headless, since--headlessrenders nothing.