Commit graph

2,411 commits

Author SHA1 Message Date
Meta Vens
2d30403ab2 Tests: pin generation's fill preference, lot reuse and thermostat billing
Soul's S6. Generation always gives Zenith's 16-cell Reactor hardpoint a reactor
that fills it though smaller ones fit; a generated Djinni's eight thrusters
share one lot; across 5 K either side of a heater's target the bus bills it
exactly when its thermostat is open; and a thermostat gates only its own
behaviour group (a two-group fixture: the closed group's 10 is not billed, the
other group's 7 is).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:38 +02:00
Meta Vens
ff2be8e26f One placement rule for hardpoint gear
Soul's S3 and the S2 ruling ("B is the design intent, saving slots in a
hardpoint can be a valid tradeoff for crowded ships if you really need to fit
an extra tool"). Entity.HardpointAt is the one placement rule: at an origin,
the item lies within a hardpoint of its type at that hardpoint's rotation
(HardpointData.TakesAt), its own cells are free, and that hardpoint holds no
other hardpoint item. The origin no longer has to be a hardpoint cell, and
TryFindSpace tries every offset inside a hardpoint, the offsets the fit rule
tries, so an L-shaped hardpoint takes its L design instead of generation
throwing. Leftover hardpoint cells may hold general gear, and a hardpoint still
holds one hardpoint item.

Tests: an L hardpoint takes its L design by hand and in generation (Soul's
P11); a turret's gun goes back beside the tool gear in its leftover cells
(P21); a second gun in a roomy hardpoint is refused; a saved entity reloads to
the same loadout with its items in reverse order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:37 +02:00
Meta Vens
d50fd1b973 A faction reaches its own gear; allegiance names only other factions
Operator ruling, 2026-09-30: "removing the 11 self-entries was my intention".
IsAvailable, the one reach rule, now says a faction always reaches its own
manufacturer's gear, and a transient `AetherDb allegiance-self [apply]` drops
the self-entries from the eleven factions that had one (Rossum & Douglas never
did, which is why its stations could not carry its own gear).

Tests: in a main-sector galaxy every faction is offered all it makes and no
allegiance map names its own faction; and, through a fixture faction outside
the galaxy with no self-entry, its own product is on offer to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:34 +02:00
Meta Vens
f458206c76 Content: a station reactor for every reactor maker
Operator ruling, 2026-09-30: "Keep the variety, not every galaxy will have
Zhestokost in it." A transient `AetherDb station-reactors [apply]` gives each
manufacturer that makes reactors a design for Zenith's 16-cell Reactor
hardpoint, scaled by cells from its largest reactor with every other value,
stat term, role, temperature and sound bank its own, and a product by it:

  Vulcan Station Reactor     (AU, from Vulcan 12 cells x1.333)  charge 66.7..266.7, mass 666.7, price 1,550,000
  Notorious Station Reactor  (Lucent, from Notorious 9 x1.778)  charge 711.1..2133.3, mass 1333.3, price 1,800,000
  MoveOnPro Station Reactor  (NiteLife, from MoveOnPro 4 x4)    charge 100..500, mass 1200, price 3,600,000
  Core Power Station Reactor (R&D, from Core Power 4 x4)        charge 400, mass 200, price 1,000,000
  products: Vulcan Station, Notorious Station, MoveOnPro Station, Steadfast Station

The Manhattan-derived one is renamed "Manhattan Station Reactor" (product
"Manhattan Station").

Reach is read through the one rule, LoadoutGenerator.IsAvailable. Test: a
faction allied only to AU, Lightsail and NiteLife is offered none of
Zhestokost's products and AU's, its stations carry nothing it cannot reach and
nothing by Zhestokost, and they are powered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:31 +02:00
Meta Vens
09050ae920 Tests: drop the flaky failed-belt-task test
AFailedBeltTaskSurfacesOnce swapped a belt's asteroids while that belt's task
could still be running, so it failed in 5 of 8 runs including unmutated ones
(Soul S1). It tests belt-task machinery that codex/mining deletes (Cut 1,
22a54ccb), so it goes rather than being reworked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:27 +02:00
Meta Vens
2125f2b181 AetherDb: retire the damage-curves one-shot
It landed its content; git history keeps it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:35 +02:00
Meta Vens
c4af127280 Stations carry only gear their faction can reach
Operator ruling B, 2026-09-30: "a station with no access to Zhestokost gear
should not have Zhestokost gear." Test: in a main-sector galaxy (not the
prelude, which offers every product), every faction's generated stations carry
a heater and a reactor, and nothing, equipped or stocked, whose manufacturer is
outside the galaxy or the faction's allegiance.

With today's catalog every faction's allegiance names every faction (weights
only bias preference) except Rossum & Douglas, which leaves out itself; the
test killed a reach that ignores allegiance through an R&D station carrying
R&D reactors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:32 +02:00
Meta Vens
f879527158 Zone: every writer of what the belt tasks read settles them first
Soul's F5 and F6. The asteroid-belt tasks read the clock, the orbits and each
belt's damage and respawn state. Update advanced the clock before waiting on
last tick's tasks (Soul measured 242k transforms placed for the next tick in
576 of 3000 ticks), MineAsteroid wrote damage and respawn state under a
running task, CreateOrbit and AddOrbit wrote the orbits, and a task that threw
stayed in the list, so Wait rethrew it on every tick after.

SettleBelts waits for the tasks and clears the list even when one failed; Update
settles before it advances the clock, and MineAsteroid, CreateOrbit and
AddOrbit settle before they write.

Tests: over 3000 ticks every asteroid of a belt is placed for the time of the
tick that started its task; mining every asteroid of a belt, chipping and
breaking each four times a tick for 1000 ticks, never races the task; a task
that fails surfaces once and later ticks run clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:31 +02:00
Meta Vens
74d2cf8fc4 Power bus: a consumer its thermostat has closed is not billed
The bus billed every active IPowerConsumer, but a behaviour group stops at its
Thermotoggle: a heater above its target never runs its EnergyDraw, yet its
full draw (1000-2500/s) was charged every tick. On an idle station that kept
the reactor in permanent deficit, overloading at overload efficiency. The bus
now skips a consumer whose group has a closed thermostat ahead of it, the same
rule it already applies to inactive items; Thermotoggle.Open is the one
statement of when a thermostat is open, and Execute returns it.

Tests (Soul's F2; S17 survived before): from a hull at one uniform temperature,
one tick below the heater's target raises its cells and one above does not, so
the heater's own contribution is measured with no reactor heat in it; and the
bus bills the heater's draw below its target and not above.

This does not keep an idle station warm (Soul's F1, reported separately): the
reactor's throttled idle heat alone still drives it past its plateau.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:30 +02:00
Meta Vens
072a56f0b4 One loose fit rule for hardpoint gear
Operator ruling, 2026-09-30: "Hardpoint fit is loose: nobody's gonna stop you
from putting a small reactor in a large reactor's hardpoint." There is one rule,
HardpointData.Takes: gear of the hardpoint's type fits when its shape, at the
hardpoint's rotation, lies within the hardpoint's cells. TakesAt is the same
rule at one offset, and Entity.ItemFits (equipping, save load, presets) now
asks it instead of repeating the containment test. Generation's hardpoint
picks, HasHome (so station stock and loadouts), product reuse and `AetherDb
hardpoint-fit` all read Takes.

Generation keeps its own placement preference, named IsFilledBy and not a fit
rule: it offers gear that fills the hardpoint when any is on offer and falls
back to anything that fits only when none is, so loadouts change only where a
hardpoint used to stay empty. RestoredHullsTests pick fillers through
IsFilledBy.

Consequence: the Autocannon, Vulcan, scorched void policy, Notorious, pretty
pretty bang bang, Manhattan, plight, DeathCluster, Small Drive and pswarm now
have a home and are offered. Still homeless: CShot RainbowLite Lazer,
ChargeBlast SG, ChargeBlast+-, OK Disperser.

Tests: generation offers exactly the sold hardpoint gear some hull fits; a 7x7
design no hull fits is offered only once a hull that takes it exists; a 5x5
Reactor hardpoint nothing fills still gets a reactor; equipping and the rule
agree for every hull, hardpoint and design; the homeless list is stated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:28 +02:00
Meta Vens
87fae6e4f0 Content: damage curves for the five sold weapons that had none
Soul's F4: LRMM72, SRMM72, Autocannon, pswarm and plight had DamageCurve ==
null, and once they had products NPCs were generated with them and
CombatState.SampleDps threw at InstantWeapon.cs:64 / ChargedWeapon.cs:81.
A transient `AetherDb damage-curves [apply]` copies each one's curve from its
nearest comparable weapon, same class first, then closest range and damage:

  Autocannon <- DeathCluster (auto-fire Ballistic, 4 cells, range reaching 1000)
  LRMM72     <- GT 3K (the only other unguided launcher)
  SRMM72     <- scorched void policy (guided; 750 range and 128 damage inside its 500-1250, 128-512)
  pswarm     <- scorched void policy (guided; identical damage, range, cooldown)
  plight     <- ChargeBlast+- (charged Energy; nearest range)

Every curve in the catalog is the same one, keys (0, 1, 0, 0) and
(1, 0, -1.7656243, -1.7656243): full damage at minimum range falling to none
at maximum. Test: every weapon a product sells has a damage curve.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:27 +02:00
Meta Vens
adad301b7a AetherDb: retire the product-gap and station-reactor one-shots
Both landed their content (653ba490, the station reactor commit); git history
keeps them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:01:36 +02:00
Meta Vens
d91ab8daf9 Generation never offers gear no hull can mount
Operator ruling, 2026-09-30, on the Autocannon: "Leave the autocannon unsold,
we'll need to author a bunch more hulls before all the gear variety in the game
has a home." The fit rule gets one owner, HardpointData.Takes (the gear's type,
laid in at the hardpoint's rotation, filling every cell); LoadoutGenerator's
hardpoint picks, its reuse of a previous product and `AetherDb hardpoint-fit`
all read it. RandomProducts, which both station stock and NPC loadouts draw
through, offers only gear with a home: Tool gear, hulls, or hardpoint gear some
hull in the catalog takes. The Autocannon keeps its product and price.

Test: the Autocannon is never drawn in 2000 draws of its hardpoint type; after
a scratch hull whose hardpoint takes it is authored, it is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:01:35 +02:00
Meta Vens
5c3cd599ac Zone: wait for last tick's belt tasks before clearing the orbit cache
Update cleared `_updatedOrbits` and only then waited on the previous tick's
asteroid-belt tasks, which read the cache through GetOrbitPosition. A task
still running could see the set mid-clear ("concurrent update ... corrupted its
state") or recompute an orbit into last tick's position. The wait now comes
first.

Test (Soul's orbit counter, committed): 3000 back-to-back 0.02 s ticks of a
quiet arena, and no orbit stands still against its parent. Clearing first gave
500+ stalls or the corruption exception. Measured against the parent because a
moon can genuinely pause in zone space: one such reading (tick 1321, a moon
whose motion cancels its planet's) is real motion, not the race.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:01:34 +02:00
Meta Vens
b3e7995ceb Stations: a station reactor, so the heater has power
Operator ruling, 2026-09-30: "Yep, we need a station reactor." Zenith's 16-cell
Reactor hardpoint had no design to fill it, so generated stations had no power.
A transient `AetherDb station-reactor [apply]` authored it from Manhattan, the
largest and most industrial reactor, scaled by cells (16/9):

  Station Reactor (GearData, Reactor hardpoint, full 4x4)
    mass 500 -> 888.9, price 750,000 -> 1,350,000 (to the nearest 50,000),
    charge 500..1000 -> 888.9..1777.8; every other value, the efficiency,
    overload and throttling stats and all stat terms, the roles (core,
    regulator), temperatures, durability and sound bank are Manhattan's.
  Product "Station Reactor" by Zhestokost (Manhattan's maker), default role
  quality.

Station generation fills the slot through its ordinary hardpoint pass. Tests:
every generated station carries one heater and a reactor; an idle station (a
quiet arena, nothing else running) holds its heater's cells above freezing over
the second five of ten minutes (unpowered they fell to ~247 K); a station hull
with no room for a heater fails generation by name instead of skipping it
(Soul's S11 survived before).

The station's border cells still sit near 265 K with the heater and reactor
running (the reactor core reaches ~433 K); how warm the whole hull should run
is left as a tuning question.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:01:32 +02:00
Meta Vens
89ef80d298 Stations: every generated station carries a heater
Operator ruling, 2026-09-30: an idle station has no heat source and cools
toward freezing and invisibility, so station generation (LoadoutGenerator, the
one owner of station loadouts) equips one heater after the docking bay, from
the products whose design is Tool gear with a low-pass Thermotoggle and Heat,
the cockpit's thermostat composition. It is required, like the docking bay.

Not yet warm: generated stations have no reactor (no reactor product fits
Zenith's 16-cell Reactor hardpoint), so the heater's EnergyDraw gets no supply
and the station still cools (280 K to ~247 K over ten idle minutes). The test
that an idle station stays above freezing waits on that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:45:32 +02:00
Meta Vens
f4703e8288 Scenarios Cut 1: every unsold design is a scenario test design
Q3 with the 2026-09-30 ruling: a design no product sells is a scenario test
design and nothing else. A test design is recognised as one a scenario places:
its preset's hull or a slot of it, or cargo it carries. The census holds for
the shipped catalog (today there is no unsold design at all), and in a scratch
copy a new unsold design is flagged until a scenario places it, once through a
preset slot and once as an entity's cargo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:45:30 +02:00
Meta Vens
653ba490a7 Scenarios content: delete five industrial placeholders; products for four weapons and the heater
Operator rulings, 2026-09-30 (docs/scenarios-cut.md, "the ten real designs with
no product"), landed through a transient `AetherDb product-gap [apply]`:

- Deleted, nothing referencing them: Assembly Line, Deep Ore Extractor, Surface
  Ore Extractor, Refinery, Shipyard (RTS-era placeholders, price and durability
  0, three with unreadable behaviour entries).
- Products, maker taken from the nearest analogue's product:
    Autocannon  -> Autocannon by Zhestokost (DeathCluster: Ballistic, 4 cells, AutoWeapon)
    LRMM72      -> LRMM72 by Rossum & Douglas (GT 3K: the only other unguided launcher)
    SRMM72      -> SRMM72 by Death Monkey Explosives (scorched void policy: guided, nearest size and price)
    Tractor Beam -> Space Tractor by Ewan Hart Inc (no analogue; the wishlist's
                   "Space Tractor: It's a tractor. In space.", content-batch-one section 10)
    Industrial Thermostatic Heater -> same name by Lightsail Express (Cockpit 2x2,
                   the same Thermotoggle/EnergyDraw/Heat group)
  Each product carries its design's roles at the default quality (0.5 +- 0.15).
- The heater design kept (operator), with Price 0 -> 100,000 (between Cockpit
  2x2 and Fire Control Array) and Durability 0 -> 100 (Cockpit 2x2's): at zero
  price generation never offers it, at zero durability it never comes online.

The rewrite stores every weapon record at the current schema, so
FireControlCut124's shipped-catalog check now expects an Exact migration
report instead of drift with slot 32 defaulted. `AetherDb census` reports no
unsold design. Tractor Beam keeps price 0, durability 0 and no behaviour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:45:18 +02:00
Meta Vens
27598a464a BaseState: an includeChildren walk keeps its state in locals
AddTransition's graph walk kept its visited, leaf and ignore sets in static
lists, so two Minions built at once on different threads (zones are built in
parallel) walked and cleared each other's state. Soul hit it as "collection
was modified" during parallel test runs. The sets are now the call's own.

BaseStateTests starts sixteen walks together behind a barrier, fifty rounds,
over prebuilt 200-state chains; with the statics restored every run failed
(several hundred of 800 walks wrong or throwing); with locals, clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:12:41 +02:00
Meta Vens
ff75b8ea34 Scenarios Cut 1: a stance survives docking; it goes only with an entity gone for good
Every entity's zone-removal subscription dropped its IFF override for whatever
left the zone, and TryDock removes the docking ship, so a scenario stance was
lost one way (the other entity forgot; the docked ship, deactivated, kept its
own) as soon as the player docked. The removal event already tells the two
apart: TryDock parents the ship to its dock before removing it, and every
leaving-for-good path (death, warp, unload) leaves with no parent. The override
is now dropped only for an entity that leaves unparented.

Tests: a hostile stance holds both ways, including the live hostility each side
tracks, across dock and undock; a destroyed entity takes the player's stance
toward it with it. UndockingAdmitsWithNoAgent commits Soul's probe: undock
admits unpiloted, active, with no agent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:09:12 +02:00
Meta Vens
929020e7df Scenarios Cut 1: a quiet arena drops a story station's turrets too
The quiet-arena test ran with an empty Narrative directory, so the story-station
branch of ZoneGenerator never ran under Ambient: false and keeping its turrets
went unnoticed (Soul's S06). The test now places a story station in the entrance,
as the narrative loader would, and checks it is generated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:00:44 +02:00
Meta Vens
178897ce7a Scenarios Cut 1: a failed staging reports what it admitted, not a crash
"Zone unchanged on failure" was defended only by xunit formatting an entity
sequence until the test host overflowed its stack. SafeAssert.Unchanged compares
the zone's entities and agents by identity and order and names what changed by
hull name; every Assert.Contains over zone.Entities in RunStartTests goes through
SafeAssert.In for the same reason.

AMissingDesignFailsNamedAndChangesNothing gains the partial-admission case: a
player and a piloted entity that build cleanly, then a later entity whose preset
is missing. Admitting the built player before the all-or-nothing return now fails
by name ("the zone's entities changed, 5 -> 6: added [Djinni]").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:59:50 +02:00
Meta Vens
7e7c08bc73 Scenarios Cut 1: pin that admission activates
An admitted entity that was never activated tracks no hostility, so
targeting and grudges never see the stance. The stance test now also reads
each side's live EntityHostility, which only activation populates; dropping
Activate from Zone.Admit survived the suite before this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:59:43 +02:00
Meta Vens
2724a0d8a7 Scenarios Cut 1: observe an unpiloted ship's steering, not its position
The zone's gravity moves every ship, so an unpiloted scenario ship drifts
(about 14 m over 5 s at the test's spot) with nothing flying it. The rule is
"no agent steers it": the test now checks its movement and look inputs stay
untouched every tick, and that it still has no agent afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:10:03 +02:00
Meta Vens
72c58d365f Scenarios Cut 1: a bare hull updates
Entity.Update walks _orderedEquipment, which only TryEquip and TryUnequip
set, so an entity nothing was ever equipped on threw a
NullReferenceException on its first tick. Scenario presets stage bare hulls
(a turret, an unpiloted target), and RunStartTests found it: MapEntity now
sets the ordered equipment to the hull alone when it adds the hull.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:52:44 +02:00
Meta Vens
f527154e26 Scenarios Cut 1: StartGame stages through RunStart; the game's joins admit
StartGame's new-run branch no longer generates, unpacks or admits the
player: RunStart generates the arena and stages the run, and StartGame
enters the zone and binds the returned player (docs/scenarios-cut.md, 2.2,
deletion line). PopulateLevel's warp arrival and the spawnturret console
command admit through Zone.Admit, unpiloted. The console commands stay (Q4);
give's hull route moors a ship at the docked entity and joins a zone only
through Entity.TryUndock, which already admits.

Needs the Unity batchmode compile; Assembly-CSharp is not built headless.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:35:19 +02:00
Meta Vens
85ebe036e1 Scenarios Cut 1: RunStart stages a new run; the Scenario catalog type
RunStart (ServerShared, no Unity type) owns what a new run starts with
(docs/scenarios-cut.md, 2.2):
- GenerateArena: the galaxy's entrance pack, generated under the scenario's
  Ambient rule. ZoneGenerator.GenerateZone gains `ambient`; false keeps
  planets, orbits and stations and generates no ship, turret or wanderer.
- Check: every failure staging a scenario would hit, found with no zone,
  touching no store.
- Stage: all-or-nothing. With no scenario, the generated starting-hull ship
  at the origin, as StartGame built it. With one, the player preset and the
  entities at their authored place and heading with cargo, stance set both
  ways through SetIff, a Minion for each piloted one; all through Zone.Admit.

Scenario (aetheria.scenario v1) joins AetheriaStores.CatalogTypes.
RunStartTests stage into a real prelude arena from the shipped catalog and
authored settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:35:18 +02:00
Meta Vens
5706b657e3 Scenarios Cut 1: Materialize builds product-less designs unbranded; the hull picks the entity
Two rules on Loadouts.Materialize (docs/scenarios-cut.md, 2.2, Q3):
- A design no product makes is outside the economy and is built unbranded,
  with no maker, at Loadouts.UnbrandedQuality (.95, the console give's).
  A design whose products are all unavailable still fails, as before.
- The hull's type picks the entity: a ship hull builds a Ship, a turret hull
  an OrbitalEntity with no orbit; a station hull is refused. Materialize now
  returns Entity.

Loadouts.Resolve is the one rule for how a design is built; RunStart uses it
for scenario cargo. LoadoutTests.MissingDesignReports no longer uses the
product-less "Orphan" as a failure (it now builds); two tests pin the Q3 rule
and the unavailable-product contract it does not loosen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:33:00 +02:00
Meta Vens
fbda4c74fb Scenarios Cut 1: Zone.Admit is the one admission into a zone
Zone.Admit(entity, piloted) adds the entity to Entities, activates it and,
when piloted, gives it the zone's Minion. It is the only writer of
Entities.Add and the only creator of agents (docs/scenarios-cut.md, 2.2).
The constructor's pack loop admits every packed ship but the player's as
piloted and keeps its own origin-scatter rule, which is generation
placement, not admission. Entity.TryUndock admits the undocked ship
unpiloted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:32:59 +02:00
Meta Vens
702b454bea Scenarios map: record Q1-Q4 rulings; Cut 0 cancelled
Q1 A, Q2 B, Q3 A. Q4: every console command stays ("never toss a
single one"), so Cut 0 is cancelled and give/spawnturret admit through
Zone.Admit in Cut 1. Self restores the smoke weapons in the operator
tree when Cut 4 lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:14:40 +02:00
Meta Vens
65c6349537 Map the scenario cut: authored arenas launched from the main menu
Imagination pass 1 against dcd7bbc5, designed from the operator's own
words (quoted in the map). Cuts 0-4; four operator questions open
(Q1 arena in a real run, Q2 who records results, Q3 test-only designs,
Q4 which ad hoc affordances retire).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:11:09 +02:00
Meta Vens
dcd7bbc5f6 Merge fire control (codex/fire-control-12) into master
Fire-control batches 1-8 with Soul passes, verified headless (Aetheria
Shared tests). Play smoke 2026-09-30: compile clean, steps 3-6 played
(pass/partial), steps 7-20 and fire-control checks A-F unplayed. The
operator preferred to merge now; Self ruled merge, with the unplayed
checks carried as open behaviours to verify through authored main-menu
scenarios (new Eureka cut). Report: docs/merge-to-master-checklist.md
section 8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:32:19 +02:00
Meta Vens
d3075eb06d Record the play smoke stop, operator direction and stale checklist expectations
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:15:06 +02:00
Meta Vens
f935c29b4b Fix console text input and route give through ship commissioning
- ConsoleView appended the control characters text input delivers (\b, \r),
  so Backspace inserted a glyph and Enter's \r got every command refused
  since d503f076 made the parser refuse instead of strip. Control characters
  are no longer text; Backspace deletes like Delete.
- give reports an unknown name or a full cargo bay. A ship hull is refused
  unless docked, and when docked is commissioned through
  ActionGameManager.CommissionShip, the primitive TradeMenu.Buy now uses: a
  bare player ship moored at the docked entity, no docking bay. Non-ship
  hulls are refused.
- Record play smoke results for steps 3-6 and the docking bay finding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:04:11 +02:00
Meta Vens
c6430c93e4 Make AetherDb the agent's data tool in project doctrine
Missing catalog or save capabilities are added to AetherDb as commands,
not written as scratch projects, loose scripts or byte readers. Records
the serializer options and the CultLib pin gate an agent hits on first use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:08:34 +02:00
Meta Vens
97edf48cec Add the debug info panel and the shield panel test rig
ARPG.unity gains Debug Info Panel and Debug Info Text, which
ActionGameManager.DebugInfoText drives as the fire-control debug HUD.
FieldShieldTest.unity gains the ShieldInterceptor, ShieldEnvelope and
Panel prototype rig from shield-panel Cut 4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:38:54 +02:00
Meta Vens
e0a802084e Use the generated accessor for Cycle Target Item
Regenerate AetheriaInput.cs from the committed Aetheria.inputactions so the
wrapper carries Cycle Target Item, and bind it through Input.Player like the
other target actions. The by-name FindAction lookup was a stopgap from when
the generator could not be run outside the editor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:38:48 +02:00
Meta Vens
113164fadb Record fire control batches 5-8 landing and their follow-ups
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:24:39 +02:00
Meta Vens
06001b57a8 Merge fire control fix batches 5-8: fused weapons follow player intent
One Solve decision feeds Fire, Inspect and Refuses. Literal arming distance
on every detonation path; no-lock rounds of any fuse stop at the first hull;
a round fired at a target that leaves does not burst; refusal is free,
cooldown included; AI decides per weapon and never fires a refused weapon;
the HUD shows the outcome. Soul passes 5-7; batch 8 closes their follow-ups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:21:12 +02:00
Meta Vens
7f317bd332 Freeze a guided round that waits on its verdict and place a positionless hit at its target
After its fade a round kept integrating Velocity through the BindingLifetime wait, then a Hit (which carries
no burst point) played HitEffect at the drifted position. The wait now holds still; a hit without a point
plays the effect at the round's target position, and is skipped when the round never knew one. OnEnable resets
BindingLifetime so a pooled split child, which is never bound, does not inherit the last round's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:15:53 +02:00
Meta Vens
742cb23f5b Gate a charged weapon's Activate on CanFire, and start a burst's cooldown with the tick it flew in
A released charge has a burst pending and no cooldown until its first round, so a second Activate in that
window started a second charge; Activate now asks CanFire. The round that starts a burst's cooldown does so
after the tick's decrement, which made every cooldown one tick long; it now charges that tick to the cooldown.
Pins both, and that a burst triggered after a fired one is not ready before its first round.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:15:51 +02:00
Meta Vens
819b282346 Pin that Combat picks no group whose weapon cannot reach the target
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:54:36 +02:00
Meta Vens
c0fb26fca1 Pin that a triggered burst is not ready before its first round
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:39:18 +02:00
Meta Vens
1c5872e7a8 Give the stance-test gun a burst and a cooldown
The default InstantWeaponData has Count 0, so the fixture gun never had a round to fire.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:35:53 +02:00
Meta Vens
c4b628fad7 Resolve the stance-test gun before triggering it
A burst is sized from stats the first Execute resolves, so the untouched fixture gun fired nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:32:31 +02:00
Meta Vens
020a42fcb6 Execute the weapon directly in the stance tests
The stance fixture has a shooter the zone cannot tick; the weapon runs on its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:31:38 +02:00
Meta Vens
7c1b1cd3d8 Tick the zone before reading the cooldown in the stance tests
BurstCount is set by the first Execute, so a trigger pulled with no tick has no burst pending. The
tests now run one tick and read whether the cooldown started.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:27:28 +02:00
Meta Vens
0e73bbac72 Read the pending burst, not Progress, as the mark that Trigger ran; sound the charged control by its own event
The cooldown now starts at a burst's first fired round, so Progress no longer moves at the trigger.
IffAndCombatTests read CanFire (false while a burst is pending) instead, and the charged-weapon
control uses the charge-start event name the sound bank resolves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:23:04 +02:00
Meta Vens
136fddf15a Start the cooldown at a burst's first unrefused round; refused charged weapons never charge
A burst whose every round is refused fires nothing and leaves no cooldown: the cooldown moves from
Trigger to the first round Execute does not refuse, and CanFire holds a triggered burst that has not
yet fired. ChargedWeapon.Activate asks FireControl before it starts charging, so a refused weapon pays
no charge heat or audio. InReach is deleted: Designated carries the one range test and the lock gate,
and Combat reads it. GuidedProjectile answers Resolve while alive and keeps its binding through the
shot's flight time, so a faded round still shows the simulation's detonation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:16:52 +02:00
Meta Vens
76e78db4b2 Record that a refused round starts no cooldown
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:52:21 +02:00