Research-grounded transform of the base arena from a bright meadow into a dark 'Aether Siege Outpost' reading as a concentric bullseye (Core -> Ore ring -> dark perimeter). Camera (Game.unity): pitch 45->58, FOV 55->44, dist 13->17, lead 1->0.5, follow 8->6, targetH 1.3 (telephoto so Core + arena read together, near-iso enemy spacing). Lighting: sun dimmed+cooled 1.6->0.9, ambient 1.0->0.62 dark-cool, fog Linear 18->42 dark; WorldAtmosphere base darkened. Post-FX (PostFX_Daylight): ACES kept, bloom gated (thr 1.0->1.2 + clamp 10), exposure/contrast up, saturation +6->0, added ShadowsMidtonesHighlights cool-shadow/warm-highlight split, vignette 0.15->0.32. Ground re-tinted dark teal-grey; ~390 meadow-cheer objects cut. Core staged as hero (crystal 14m->4.6m cyan glow + cyan beacon light). Ore ring pulled into the arena (23.5-27m -> 6-11.5m, count 10->12) and recoloured AMBER (new Mat_OreNode_Amber, emissive, no atlas bleed).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The terminal banner gains PLAY AGAIN + QUIT TO MENU buttons so a finished run has a clear action (no Esc-hunting). PLAY AGAIN restarts a fresh Single run via WorldLauncher.StartSession (the proven menu lifecycle, no save load); QUIT TO MENU reuses TeardownToMenu (autosave + menu); both self-guard on WorldLauncher.Busy. The button row picks (Position) under the Ignore banner root, matching the build-palette idiom. AimReticleSystem (the sole Cursor.visible writer) keeps the cursor visible while RunOutcome != InProgress so the buttons are clickable regardless of aim state. 342/342 EditMode green. Co-op retry-together stays a cut slice-limit (a client's Play Again starts a solo run). See DR-036.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The client derives the climactic final siege from the replicated Charge>=Target and marks it distinctly: 'FINAL SIEGE INCOMING - Ns' during the cap-reached arming window (vs the generic 'INCURSION'), 'HOLD THE ENGINE - FINAL SIEGE' + intense red during the wave, and a last-stand location line. Pure client presentation (no sim/replication change); 342/342 EditMode green. Serves the END-2 fun-gate (the Engine telegraphs the climax + prompts deliberate prep).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
At GoalProgress.Charge>=Target a new server-only GoalReachedSystem arms a larger final siege (x live FinalSiegeMultiplier) and flips RunPhase=FinalDefense; CyclePhaseSystem latches a REPLICATED RunOutcome (Victory on clear / Loss on Core breach) and halts the director. RunOutcome is a [GhostField] byte on the global CycleDirector ghost (the client banner observes it); RunPhase stays server-only. ThreatDirector/CoreRestore/CoreDamage halt once decided; SiegeTimeout is off during the final siege. SaveData v5 persists the outcome so a won/lost run loads finished. GoalProgress.Target 10->4. Completes Path A's spine. See DR-036.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CoreSystemsTests (new): a breaching Husk drains + is consumed; idles at 0;
regen fires once per interval in Calm only; no regen mid-Siege; caps at Max.
CyclePhaseSystemTests: the soft-loss overrun edge ends the siege, drains the
ledger, despawns husks, withholds the goal charge, and resolves once.
StorageMathTests: DrainFraction floors per row, drops zeroed rows, clamps.
SavePersistenceTests: CoreCurrent round-trips at v4; a pre-END-1 save with no
CoreCurrent defaults to 0 (-> born full); the v3->v4 version pin updated.
TuningConfig golden pin extended with the 3 Core defaults.
See DR-034.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds CoreIntegrity{[GhostField] Current,Max,OverrunTick} on the GLOBAL
CycleDirector ghost (no new ghost/relevancy). CoreDamageSystem (server,
after EnemyAISystem): a Husk within ~3u of PlotCenter drains + is consumed;
CoreRestoreSystem regenerates only in Calm. The SOFT-loss edge lives inside
CyclePhaseSystem (sole Phase writer): Current<=0 in Siege flips to Calm with
NO goal reward, StorageMath.DrainFraction drains the shared ledger, all Husks
despawn, and OverrunTick is stamped (a transient HUD-flash pulse, not a
latching outcome - the Victory latch is END-2's). EnemyAISystem treats the
Core as a FALLBACK target so an undefended base is overrun instead of idling.
SaveData -> v4 persists CoreCurrent (0 -> born full, the EB-1 HP sentinel);
3 live TuningConfig knobs + a red HUD Core bar. Soft-loss + targeting +
breach-resolution forks operator-locked.
See DR-034.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- TurretFireSystem: seed a Charge pool for existing tests; add soft-fail-when-dry,
consume-one-Charge-per-shot, two-turrets-share-a-finite-pool.
- FabricatorProductionSystem: ledger-fed withdraw/deposit, two machines split via the
live in-loop read, and a catch-up affordability-clamp regression pin.
See DR-033.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mined Ore now has an ongoing sink: a ledger-fed Fabricator converts Ore->Charge
(1 Ore -> 3 Charge / 30t) and turrets spend Charge per shot, soft-failing (no
shot, no cooldown burn) when the shared pool runs dry.
- ResourceId.Charge=4 rides the existing [GhostField] StorageEntry ledger (no new wire).
- TurretFireSystem: single ledger resolve + atomic spend / soft-fail / partial-refund.
- Fabricator.InputFromLedger (byte, server-only) feeds input from the shared ledger,
read live in-loop so two machines split a finite pool; both modes deposit to ledger.
- HudSystem: violet Charge chip + global quiet-turret cue when siege && Charge==0.
- StorageMath.TotalOf backs the affordability read; catalog re-enables the Fabricator (4 entries).
See DR-033.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
10 new EditMode tests (312 total, all green): HealthApplyDamage destroys a Destructible at 0 + a wounded structure survives clamped; PickWeightedNearest x5 (player-only, structure-preferred-by-weight, player-in-the-way wins, raze undefended base, no targets); persistence (StructureSave.HP round-trip + writes v3, v2 in the load floor, SaveApply.ToPending maps the wounded HP - the staging-copy bug the pre-code review caught); + the StructureAggroWeight default pin. See DR-032.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Structures (Turret/Wall/Pylon) reuse the combat spine: authoring bakes Health(GhostField)+DamageEvent buffer+a Destructible tag (no HitRadius -> no friendly projectile fire; no EffectiveCharacterStats -> clamp-to-0). HealthApplyDamageSystem destroys a Destructible at 0 (occupancy auto-frees). EnemyAISystem fortress-targets the weighted-nearest of players+structures via the shared EnemyAIMath.PickWeightedNearest (StructureAggroWeight TuningConfig knob, <1 prefers structures, squared factor; snapshot above the early-return so an undefended base is razed). Persistence v3: per-structure HP threaded through 5 sites (SaveData/PendingStructure/scan-guarded/BaseRestore same-ECB born-correct/WorldLauncher via SaveApply.ToPending); SaveService floor-gate [2,3] loads old saves. Loss feedback: proximity-gated StructureFeedbackSystem; CombatFeedbackSystem suppressed for structures. Pre-code review caught the DamageEvent-buffer crash blocker + 8 majors; post-code review clean. See DR-032.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace every placeholder-cube ghost prefab with nested Synty (PolygonFantasyKingdom) models: ResourceNode->crystal, Turret->ballista, Wall->spike palisade, Pylon->crystal beacon, Storage->chest, UpgradePickup->gem, BlightClutter->rock chunk (nest as a Model child, strip colliders, reset the [GhostField] root Scale, atlas for bare FBXs). Gameplay subscene: place the BaseFieldSpawner, trim Harvester/Fabricator/Conveyor from the build palette. CycleDirector prefab bakes the schedule siege config. See DR-031.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8 new EditMode tests (302 total, all green): BaseFieldSpawnSystem (target count + Base/Ore + cadence + top-up), ExpeditionFieldSystem teardown preserves the base field, ThreatDirector schedule arming, and melee harvest routing (base->ledger, expedition->personal inventory) which guards the cross-region leak the post-impl review caught. See DR-031.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Consolidate the divorced combat + economy halves into one base-local loop. BaseFieldSpawnSystem tops up RegionTag{Base} Ore nodes around the plot; harvest routes Base->shared ledger and Expedition/untagged->personal inventory for BOTH the projectile (ResourceHarvestSystem) and melee (MeleeComboSystem server-only block, writes Remaining back for VFX). Activate the reserved Schedule source in ThreatDirectorSystem so base sieges arm WITHOUT an expedition trip (the loop-closer: previously zero waves ever attacked a base-only player). Region-filter the ExpeditionFieldSystem teardown so it no longer wipes the permanent base field. HudSystem shows phase-aware loop copy. See DR-031.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The movement look-ahead added its 2.5u lead raw onto the framed point and smoothed only the final camera position, so the lead target snapped with the instantaneous input -- start/stop panned the view and reversing direction swung it ~5u (the jarring walk-shift).
Fix with the genre-standard separate view-position technique: ease a dedicated _leadOffset toward the desired lead via a new gentle LeadSharpness knob, independent of FollowSharpness. Cut the lead magnitude 2.5->1.0 (AimLeadDistance, 0 = fully centred like Diablo/PoE) and pull the default zoom 16->13 (~19% closer). Code defaults + the live Game.unity Main Camera values both updated. See 2026-06-11_Camera_Feel_LookAhead_Zoom.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
An attack clip that keys ONLY the Root bone makes Rukhanka collapse every un-keyed bone (Hips/Spine/legs) to identity for the duration of the state -> the body folds halfway into the floor (player MeleeSwing + enemy Attack; writeDefaultValues does NOT prevent it -- confirmed since even a pure yaw, which is height-preserving, still sank). Fix: build the attack clips FROM the full idle pose (every bone keyed) + a Root YAW twist on top, so nothing is un-keyed. Applied to both runtime clips (PlayerMeleeSwing/EnemyAttackWindup) and both editor recipes (PlayerRigTools/EnemyRigTools) so rebuilds stay correct. Operator-verified in Play.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CombatFeedbackSystem.UpdateEnemyDanger paints a red ground danger cone at each enemy while its AttackWindup counts down -- oriented along the enemy facing, sized to EnemyStats.AttackRange, brightening + scaling as the strike nears (intensity = 1 - ticksRemaining/22) so the player reads WHERE + WHEN to dodge. Client-only observe-only; one pooled mesh per winding-up enemy, pruned each frame. Play-verified (14-enemy wave, 8 telegraphs at once, zero errors).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The procedural attack clips key only the Root bone, but the Attack/MeleeSwing states had writeDefaultValues=true -> a partial (Root-only) clip resets every un-keyed bone (Hips/Spine/legs) to Rukhanka defaults (~identity), collapsing the body into the floor (player + enemy). Root carries the mesh-positioning offset (localPos -0.90, identity rot) while Hips/Spine carry the authored orientation. Fix: writeDefaultValues=false on the attack states (leave un-keyed bones in pose, only lean the Root). Patched both controllers + both recipes (PlayerRigTools/EnemyRigTools) so a rebuild can't regress. Rule: partial bone-subset overlay clips => writeDefaultValues=false.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
byte Archetype on AbilityDefBlob (AbilityArchetype enum: Projectile/Hitscan/Cone/Aoe), authored on AbilityDefinition + baked in AbilityDatabaseAuthoring, read at dispatch in AbilityFireSystem -- NOT folded through EffectiveAbilityStats/StatRecomputeSystem (static identity, not a tunable stat; MC-4 review BURST-1). All current abilities are Projectile (0) -> zero behaviour change; the dispatch read-point is the de-risk spike for MC-6 hitscan/cone/aoe.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rukhanka swing animation: PlayerRigTools builds a procedural Root-bone PlayerMeleeSwing.anim and adds an IsAttacking param + MeleeSwing state to AC_PlayerTopDown (mirroring the enemy attack recipe -- no authored Synty Generic melee clip exists). PlayerAnimationDriveSystem pulses IsAttacking from the replicated MeleeCombo swing window (local + remote, NetworkTick wrap-safe, re-triggers per chained hit). CombatFeedbackSystem flashes a procedural cone slash-arc mesh matching the LIVE cleave range + half-angle on each swing (finisher wider/warmer) -- the arc IS the range telegraph. Addresses 'range isn't clear + no animation'.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Melee combo (left-click / pad-West) becomes the player's primary verb; the ranged projectile is demoted to right-click / pad-left-trigger. Predicted, owner-replicated combo Step (path-dependent -> [GhostField] anchor + absolute-write idempotency, NOT derived like the dash), server-only cleave mirroring ProjectileDamageSystem (SourceTick-stamped DamageEvent + KnockbackState), dash-cancellable movement-commit, 9 live TuningConfig knobs, and swing juice scaling with the combo step. The MC-6 archetype byte is deferred (the melee is its own verb). See DR-030.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Data-driven ItemDatabase catalog + per-player replicated InventorySlot ([GhostField] OwnerSendType.All, a StatModifier twin). Harvest reroutes to the firing player's personal inventory (optional ComponentLookup<GhostOwner> in ResourceHarvestSystem; remainder/un-owned -> ledger); the G-key InventoryDepositRequest RPC moves the bag into the shared ledger the build economy spends. Catalog asset (Aether/Ore/Biomass + Stone Pickaxe) wired into the Gameplay subscene; read-only HUD inventory panel. ushort ItemId subsumes ResourceId; byte Category/Tier baked for gear-tier progression. Session-only (no SaveData bump).
Play-validated host+client: catalog baked into both worlds, the re-baked player ghost carries InventorySlot with a clean handshake, a server write replicates to the client owner, the deposit RPC round-trips, and the HUD renders catalog names. See DR-026.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the sci-fi-colony dressing with two cosmetic classic-URP biomes in Game.unity: a lush Meadow_Forest base sanctuary (origin) and a hostile Arid_Desert survey expedition (+1000) - ~380 collider-stripped instances, warpgate/outpost landmarks, cyan/orange Aether accent lights. Warm daylight sun + Trilight ambient + a procedural daytime skybox + a cloned daylight post-FX grade (ACES kept). New client-only WorldAtmosphereSystem(+Config) cross-fades per-region fog/ambient by camera X>500 (mirrors HudSystem). Cosmetic-only - colliders stripped, never the subscene - so zero sim/netcode/PhysicsWorld impact (adversarially verified). Shadow-casting disabled on small foliage. EditMode 214/214. See DR-025.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
+4 EditMode cases (identity/yaw-180/pitched-degenerate/normalized) for the
helper the enemy animation drive uses to derive facing from the replicated
LocalTransform.Rotation. EditMode suite 204 -> 208, all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extends the DR-022 player pipeline to Husk enemies. A Husk is an ownerless
interpolated ghost = structurally a remote player, so the new client-only
EnemyAnimationDriveSystem mirrors PlayerAnimationDriveSystem's remote path:
velocity from LocalTransform-delta (prevPos cache, pruned every frame), facing
from LocalTransform.Rotation (AnimParamMath.PlanarForward), maxSpeed from baked
EnemyStats, IsAttacking from the already-replicated AttackWindup telegraph. No
new [GhostField], no server/asmdef/ghost-hash change.
Monster-mash roster: Werewolf (Grunt), Werewolf-Undead (Swarmer), Kaiju (Brute),
built by the reusable, GUID-preserving EnemyRigTools editor tool (materials +
AC_EnemyTopDown + EnemyAttackWindup clip + 3 rigged prefabs). WaveSystem now
preserves the baked variant Scale (was reset to 1 by LocalTransform.FromPosition).
See DR-023. EditMode 208/208; validated in Play (rigs skin, scales replicate,
locomotion + attack telegraph drive correctly).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Delete the NetConnectionUI GameObject from Game/DevSandbox/SampleScene + ConnectionUI.cs (the UITK frontend menu owns Host/Join+IP now); repoint 4 stale doc-comments (GameBootstrap done in commit C; DebugOverlay/ConnectionConfig/EditorAutoHostSystem here) to MainMenuController/WorldLauncher; remove the Assets/_Recovery crash-recovery scenes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rebuild the in-game HUD on UI Toolkit (HudUi/HudSystem, Aether palette) consistent with the menu; build-palette bar (BuildPaletteState) drives cursor->cell ground-ghost preview (green/red via BuildPreviewMath), left-click place / right-click cancel / rotate; fire suppressed in build mode; combat juice restyle. +4 BuildPreviewMath EditMode tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Netcode frontend pattern: UITK main menu / pause / settings (MenuUi + controllers), on-demand world lifecycle (WorldLauncher/SessionRunner), GameBootstrap menu branch; Graphics/Audio settings (SettingsService/GameVolume); single-slot save foundation (SaveData/SaveService, born-correct load at director spawn, autosave on Siege->Calm + quit); RuntimePanelSettings + theme; BuildTool menu; 10 EditMode tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Server-only production chains (never predicted): components + server systems + pure byte-only math (ProductionMath/ConveyorMath/MachineSlotMath), authoring + 3 machine prefabs wired into the Gameplay subscene, StructureCatalog rows, BuildPlace Direction/RuntimePlacedTag, Tuning, and 35 EditMode tests (catch-up gating, conveyor shuffle-invariance, SaveData v2 round-trip).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add BefourStudios SciFi environment packs, Gabriel Aguiar VFX, and the
ShaderCrew Toon Shader embedded packages, plus combat/enemy/wave/death
gameplay systems and supporting vault docs/screenshots.
Rename 11 vendor textures from uppercase .PNG/.HDR to lowercase so the
case-sensitive Git LFS filters (*.png/*.hdr) match on case-sensitive
filesystems (Linux CI, case-sensitive macOS), not just locally where
core.ignorecase=true masks the gap. Each .meta moved with its asset so
GUID references are preserved. All ~1000 binaries tracked via LFS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>