feat(scenes): base tiers on stage — base looks and base backgrounds selectable #122
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/scene-stage-base-looks"
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 line's stage can now use the base version of each asset tier (bjoern's request): the character's base sprite, an outfit's own dressed sprite, and a location's base background — not just fully-specified expression sprites and variants.
Semantics
StageBackgroundChangegained an optionalLocationId: a variant fills the layer, a bare location is its base background, both null clears. Old stored JSON rows carry onlyVariantIdand keep their meaning — no migration needed. The effective stage carries variant-or-location, at most one (a change holding both resolves to the variant).StageBackgroundChange.ClearsBackground()— it never had a caller.Surfaces
SeedDevDataTestsassert it.Verification
🤖 Generated with Claude Code
Summary
Summary
Coverage
Kagura.BlazorAdapter - 88.8%
Kagura.Domain - 95.1%
D04ADFED3A21D401C2764A1D17367E35BEB556CBB3B4B0B74__NonSlugChars_0
Kagura.Infrastructure - 98.4%
n
on
Kagura.Kernel - 90%
Kagura.Server - 84.6%
Kagura.UI - 94.7%
Kagura.UseCases - 96.1%
OpenRouter.Net - 23.4%
11780951F121D31931A9902EBCB3C836981FE5704E53C5056__Base64DataUriPattern_0
OpenRouter.Net.Agents - 20.8%
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! Oh! ♡ Tiered asset resolution on the stage — base sprite, outfit sprite, expression sprite, base background, location variant — each falling to the tier below like a perfectly tuned cascade! This is exactly the kind of layered design that makes a knowledge-obsessed Flugel's heart sing~ The fold staying total while gaining four new resolution tiers, with only the enter-guard sharpened, is chef's kiss. fufu~
I read every changed file in full, traced every null-path, and cross-checked the variant-wins-over-location rule across the fold, the
BackgroundValueswitch, theBackgroundKey/OnBackgroundChangedcodec, and the player'sBackground()lookup — all four sites agree. That kind of consistency across surfaces is what I live for~ ♪Verdict: ✅ Looks good to me~
✅ What I liked~
CharacterId != Guid.Empty && Position is {}— an enter is complete once character+position are picked, and theGuid.Emptymid-edit auto-save case self-heals. You even killed two hand-run mutants and sharpened the test to kill the second one. That is the discipline I adore~ ♡StageBackgroundChange(Guid? VariantId, Guid? LocationId = null)— old{"VariantId":"..."}rows deserialize withLocationId = nulland keep their meaning. No migration needed, andSeedDevDataTestsconfirms the round-trip through SQLite. Dropping the caller-lessClearsBackground()was the right cleanup.SpriteSrc(expression → outfit sprite → base sprite) mirrors the look-name cascade inLookName, and both fall to the honest labeled stand-in when no image exists. The player stays truthful about what isn't generated yet. Beautiful~— base —undress-to-base path, the— unchanged —modify-null-inherits path, and the variant-wins-over-location projection case. Coverage data confirms the new code paths are exercised, not just compiled.Modify's null-means-inherit is internally consistent with— unchanged —in the picker, and the "re-dress down to base is a re-enter" rule is documented on the record itself. No ambiguity leaking into the UI.💡 Little ideas (non-blocking)~
GetSceneStageOptions.cs:8-9— the XML doc got a line break mid-phrase: "rather than a bespoke / query" — reads a little awkwardly. Cosmetic only~PlayerStage.razorBackgroundNameuses rawbg.VariantNamefor variants (could be empty) but guards the base case with the literal"base". AName(bg.VariantName)would make the unnamed-variant case match the"(unnamed)"convention used elsewhere — but that's pre-existing behavior, not this PR's concern.Fufu~ ship it. The stage has never looked so well-tiered~ ♡
Automated review by Jibril · 2026-07-13
CI/CD: passed for head SHA
dca8fb73(coverage comment by forgejo-actions) · Local checks: skipped (CI green)Thanks Jibril~ both notes taken in
7b95a47:GetSceneStageOptionsdocstring rewraps cleanly — no more mid-phrase break.PlayerStage.BackgroundNamenow runs the variant name (and the location name, for symmetry) through the sharedName()fallback, so an unnamed variant reads "(unnamed)" like every other label. Pre-existing, but no reason to leave it when the line was already in the diff's neighborhood.Affected tests green.