Carrier vessel #57
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 fleet vessel that cannot shoot but substantially raises how much the fleet can carry.
Depends on #56 (limit how much the fleet can carry) - the carrier is meaningless until a cap exists.
Scope
CarrierVesselDefinition.tres:definition_id = "carrier",fleet_eligible = truecapabilities = ["cargo"]andcomponent_scenes = [VesselCargoComponent.tscn]only - noVesselWeaponComponent, so it structurally cannot fire. This is exactly how the shield vessel ended up weaponless after #35; do not add anifanywhere to suppress firing.base_stats: a largecargo_capacity(suggest 120, i.e. six interceptors' worth), slightly lowermax_speed/accelerationthan an interceptor, plus thedelivery_speedevery vessel carries.unlock_id/unlock_name/unlock_description/unlock_resource_costsso it is researched at a ship lab like the shield vessel and gas bomber.VesselDefinitions.ORDERandDEFINITIONS.BuildControllerresolves crafter and hangar entries by fixed node path (../UI/CraftMenu/ShieldButton,../UI/HangarMenu/AvailableGasBomber,FleetGasBomber, and their*Labelsiblings). Add the matchingCarrierButton/CarrierLabel,AvailableCarrier/AvailableCarrierLabel,FleetCarrier/FleetCarrierLabelnodes toMain.tscnand extend those arrays.VesselDefinitions.fleet().VesselUpgradeDefinition,additive_modifiersoncargo_capacity).Acceptance criteria
GameState.fleet_cargo_capacity()by its stat.Tests
tests/test_carrier_vessel.gd(bash tests/run_tests.sh carrier), plus a 720x1280 screenshot of the crafter and hangar showing the new entry laid out cleanly alongside the existing vessels.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 in
bbb1d4b.An unarmed hauler that trades weapons for a much larger cargo hold - the first real payoff for #56's fleet capacity cap.
CarrierVesselDefinition.tres:capabilities = ["cargo"],component_scenes = [VesselCargoComponent.tscn]only - noVesselWeaponComponent, so it structurally cannot fire (same pattern that already made the shield vessel weaponless after #35 - noifanywhere suppresses firing, there is simply nothing to calltick()on).cargo_capacity = 120(six interceptors' worth),max_speed/accelerationa bit below an interceptor's, a wide flat-bottomed hull silhouette and its own amber glow colour, and a newCarrierCapacityUpgrade.tres(+30 cargo per level, 3 levels) researchable at the ship lab like every other vessel upgrade.VesselDefinitions.ORDER/DEFINITIONS, appended aftertransporter- a pure append, so every existing vessel keeps its current index in both.all()and.fleet().VesselDefinitions.fleet()/.all()(BuildController._refresh_craft_status()/_refresh_hangar()/_refresh_lab(), connected via index-bound generic handlers) - only the per-vessel UI nodes are hand-placed inMain.tscn, not the logic. AddedCarrierButton/CarrierLabel,AvailableCarrier/AvailableCarrierLabel,FleetCarrier/FleetCarrierLabeland a 5th ship-lab slot (VesselE/VesselELabel), repacking each row from 3/3/4 to 4/4/5 columns to fit. ExtendedBuildController's matching@onreadyarrays - no new signal handlers were needed anywhere.CARRIER_VESSELicon glyph, appended toIconButton.Icon(never inserted - ints are baked into scenes).A genuine regression surfaced and fixed:
test_vessel_composition.gdhardcoded the combat-fleet catalog at exactly 3 vessels; now that carrier is fleet-eligible it's 4, so that assertion is now!= 4.Tests:
tests/test_carrier_vessel.gd(bash tests/run_tests.sh carrier) covers: structurally unarmed + cargo-capable; capacity math directly (fleet_cargo_capacity(["carrier"]) == 120); unbuildable before research, buildable and correctly priced (24 ore) after; correct icon/colour/label in the crafter, hangar and ship lab; crewing one raisesfleet_cargo_total_capacity()by exactly 120; and - with an enemy parked well inside interceptor fire range and the enemy frozen so it can't close in and wipe the (unarmed, unescorted) fleet first - zeroplayer_projectilesever appear from a fleet made only of a carrier.run_tests.sh vessel(4/4, after the fix above),fleet/cargo/hangar/lab/build/skill/iconregressions all pass. Full suite: 84/84.Screenshots taken and visually confirmed (720x1280): the crafter menu with all 4 vessels researched, Carrier's wide amber hull glyph clearly distinct from interceptor/shield/gas bomber, correctly labelled "Carrier / 24 ore"; the hangar with one of each vessel available and an interceptor+carrier crewed, both AVAILABLE and FLEET rows laid out cleanly across 4 columns with no overlap, and the HUD's "FLEET HOLD 0/140" caption independently confirming the 20+120 capacity math.