Enemy research lab planet and research points #63
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 planet type that produces no resources, but grants a research point when conquered. Research points become a required currency for progressing the mothership skill tree and researching at the ship lab.
This changes the whole progression economy, so read the balance note at the end before starting.
Depends on the capture/conquest loop (#43, already merged) - the award hooks
GameState.planet_conquered.Scope
ResearchLabPlanetVisual.tscn+.gd(same informal interface asGasGiantVisual:configure(shape_seed),extractor_anchor()), andResearchLabPlanetDefinition.treswithdefinition_id = "research_lab", an emptyresource_id(it yields nothing), its ownnames, map colour, and a surface profile with no resource provider (features_scene = null, as #55 also uses). Register inPlanetDefinitions.WorldGen.planet_data_at_chunk()as a rare deterministic outcome, same constraints as every other body - a pure function of chunk coordinates, sincePlanetFieldand the world map both resolve through it and must never disagree (#37).GameState.research_points: int = 0andsignal research_points_changed(total: int).planet_conqueredand award +1 when the conquered planet's definition isresearch_lab. Conquest is permanent for the run so the signal fires once per planet, but guard against double-award anyway and assert it in the test.SKILL_TREEentries gain an optionalresearch_pointscost.GameState.can_unlock()requires it in addition to the ore cost, andunlock()spends it.VesselDefinitionandVesselUpgradeDefinitiongain aresearch_point_cost.GameState.unlock_vessel()and the lab upgrade path require and spend it alongsideunlock_resource_costs.SkillTreeViewand the lab menu.BuildControlleruses for unaffordable builds.Balance note (decide deliberately)
A fresh game has zero research points and no way to get one until the player finds, fights and conquers a research lab. If every skill-tree node costs points, the opening is hard-blocked. Give the early nodes (
shipyards, and enough of its immediate children to reach a ship crafter and an extractor) a cost of 0 research points, and put the cost on mid/late nodes only. State the chosen split in the ticket's closing comment so the next balance pass knows what was intended.Acceptance criteria
Tests
tests/test_research_points.gd(bash tests/run_tests.sh research), plusrun_tests.sh skillandrun_tests.sh labfor regressions, and a 720x1280 screenshot of the skill tree showing the balance and a points-blocked node.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.Implemented and pushed in
3f3a222, with the two-day code-quality review/refactor ind68f4d4.What shipped:
Balance split:
shipyardsandlogisticscost 0 research points, so a fresh run can still reach the crafter and extractor. Mid/late skills cost points:coordination1, and later logistics/power/combat nodes 1-2. Vessel unlocks and upgrades cost 1 point each.The follow-up review removed resource-specific gas-burner branches from transport by composing logistics/conversion data into building definitions; extracted shared aimed-ability and per-vessel cooldown/fill controllers; made skill research-point lookup explicit; and fixed a scene-transition race where the outgoing distorder UI could reset the boost before the surface fleet restored.
Validation:
JOBS=2).No tickets after #63 were implemented in this pass.