Found by running the A0 style-proof against the SHIPPING scene instead of
ArtStaging (which judges static glTF bakes on an import shader, with zero
SkinnedMeshRenderers and no Animator — it cannot answer "does the game look
like this").
Player-facing bugs fixed:
- AC_PlayerTopDown/AC_EnemyTopDown "Death" had ZERO outgoing transitions.
Any State enters on IsDead and nothing ever leaves. The player ghost is a
persistent entity, so its Rukhanka animator never resets: once you died you
rendered sprawled on the seabed permanently — sim fully respawned, moving and
fighting, visually a corpse. Added Death -> Idle on (IsDead == false).
- AmbientMotionSystem drift was still the deleted biome system: key 0 =
"meadow", MeadowMoteColor (0.62, 0.85, 0.60) = GREEN motes, 600 of them in a
36x7x24 box following the camera — the most off-palette thing in the frame.
Its x>500 region probe pointed at space now holding zero renderers. Collapsed
to one cold marine particulate; dropped the 4 dead mote colours + AridWind.
- FeedbackFx.MakeParticleMaterial built Sprites/Default with NO texture, so
every procedural particle rendered as a hard SQUARE. Added a procedural soft
dot (no Resources.Load — build-stripped; asset-free presentation is the rule).
- Game.unity carried a stock Unity "Directional Light" (warm-WHITE, 1.05, Soft)
outranking KeyWarm as a second competing shadow caster, plus 6 orphaned
LandmarkLights — four at x=1030/1530 lighting a kilometre of empty water, two
with no renderer within 12u, two of them purple. All 7 deleted. Added RimCold
for silhouette separation; key:fill set to the tuned 3.9:1; WarmPool -> Soft.
ArtStaging (kept as a lighting lab): KeyWarm 0.15 -> 0.85 — it was the only
shadow-caster yet sat BELOW GloamFill 0.22, which destroys form by definition
and is what read as "flat". StagingAmbiance was attached to nothing and its
flora wiring searched for a Game.unity parent, which is what read as "static";
it also force-played the combat one-shot pool, now restricted to looping
emitters. Flicker raised to a measured x2.11 cold swing vs x1.03 warm.
304/304 EditMode green; death-recovery, palette and particulate all verified
live in Game.unity Play.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
BLENDER (5 new/re-authored clips, all full-body, mirrored-left-arm axes
FIXED - Synty L shoulders mirror X/twist vs R, verified by axis probes):
- A_Swing_R2L / A_Swing_L2R (0.47s): horizontal slash + backhand with real
anticipation (torso wound 25 deg), 2-frame strikes, follow-through past
the target.
- A_Swing_Finisher (0.60s): overhead crash with a crouch drop into impact.
- A_Special_Slam (0.53s): two-handed ground slam - the Warrior cone finally
LOOKS like a cone attack.
- A_Fire_OneHand re-authored punchier (cock -> full-extension thrust with
torso commit -> recoil kick).
Export lesson: Blender 4.4 slotted actions - reassigning animation_data.
action does NOT bind the slot; force animation_data.action_slot before
export/render or you bake a stale pose.
CONTROLLER: MeleeSwing (one clip for everything) replaced by Swing1/2/3
keyed on new ComboStep int param (replicated MeleeCombo.Step); Fire gated
!IsCone (Ranger shot), new SpecialSlam state on IsFiring+IsCone (Warrior).
DRIVE SYSTEM: writes ComboStep from the replicated combo step and IsCone
from the replicated AbilityRef -> AbilityDatabase blob archetype (works for
remote teammates too).
SWORD: SM_Wep_Sword_01 (SciFiSpace - same pack/atlas as the soldier) as a
mesh-sub-asset child of Hand_R, grip rot (90,0,0) tuned live against the
running entity. Required RigDefinitionAuthoring boneEntityStrippingMode
Automatic -> None so the hand bone entity exists + is posed (stripped bones
never animate attachments). Play-verified: the energy blade rides the fist.
456/456 EditMode.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Four clips authored programmatically in Blender on the PolygonSyntyCharacter
skeleton (full-body keys per pose, numeric world-space verification of the
fall: hips 0.88->0.14m) and exported per-action FBX (Key All Bones, Force
Start/End Keying, FBX Units Scale). Imported as HUMANOID - the project's
pipeline is Human rigs (CharactersAvatar isHuman=true; CLAUDE.md's 'Generic'
note was stale), so muscle-space retargeting plays these on the player AND
every monster rig with zero bone-path matching. CopyFromOther failed on the
Blender-added 'Armature' node (hierarchy mismatch) -> CreateFromThisModel;
root motion fully baked into pose (the CC owns the transform).
- A_Death_FallBack (0.90s = exactly the 54-tick corpse window): recoil ->
fall -> flat on the back -> settle. Wired as the Death state on BOTH
controllers, replacing the crouch-idle placeholder.
- A_Fire_OneHand (0.4s): new IsFiring param + Fire state on the player
controller; PlayerAnimationDriveSystem routes FireActive to it (melee owns
IsAttacking again).
- A_Dash_Lean (0.33s): new IsDashing param + Dash state; driven from the
local player's predicted DashState window (not replicated -> remotes skip).
- A_HitReact (0.27s): imported + avatar'd, wiring deferred (needs a
replicated hit-tick source; body flash covers the read today).
456/456 EditMode; Play-validated: forced IsDead renders the soldier flat on
the ground in-game (Blender->FBX->Humanoid->Rukhanka chain proven), Fire
state enters and plays; console clean.
Co-Authored-By: Claude Fable 5 <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>
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>