Closes a task-5 review finding: the fighter__level badge on the combat
page still read "Stufe {{ level }}"; the design doc gap that excluded
it has since been fixed. Changed to "Level {{ level }}" to match
encounter-card.component.html's pending equivalent (out of scope here).
The branch review approved the slice with no blocking findings. These
are the substantive non-blocking ones.
N1, the one no per-task review could see: every seeded monster rolls
silverMin/silverMax = 0 (R7), so the victory screen showed "Silber +0"
after every fight in the shipped game. Three tasks were each correct in
isolation -- the mechanism stays, the values are zero, the field still
exists -- and the composite was wrong. Now conditional, with a test.
This does not contradict R16: R16 deleted the XP block because the
field ceased to exist, leaving nothing to hide. Silver still exists and
can be non-zero, so a conditional is the right tool.
N2: world.store.ts still said a combat "granted XP and silver". Same
false-fact-in-a-comment defect fixed in b5bcd50, one file over.
N4: resolveReputationRank threw a TypeError on negative input, since
findIndex returns -1 and REPUTATION_RANKS[-1] is undefined. Unreachable
today, but grantReputation is public and accepts any number.
N5/N6: grantReputation resolved factions without the enabled filter the
read path applies, so a disabled faction could accumulate invisible
reputation -- "disabled" was not actually a kill switch. The dense read
also had no ORDER BY, so the list could reorder between requests.
N8: design 13 requires silver stay 0 for every seeded monster; only two
of four were pinned. Re-adding silver to the others would have shipped
silently.
N9: spec 36's "a normal kill grants no Renown" had no test. It was
structurally guaranteed but unasserted -- now locked down against a
later slice wiring renown into combat.
N10: an impossible renown: 0 fixture, and RENOWN_MIN exported but never
used to clamp the floor.
API 268/268, web 230/230, API build zero errors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Design ruling R16: the victory screen removes the data-reward-experience
element and its "Erfahrung" line outright rather than hiding them behind
a conditional. CombatReward is now { silver, items }.
The surviving spec assertion checks that [data-reward-experience] is
absent, so it would genuinely fail if the block came back -- rather than
merely observing that some text changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A finished journey now opens the location view instead of leaving the
player on the map, and backing out of the hunt returns to the place the
hunt happens in. The victory and defeat screens gain "Zum Ort" alongside
"Weiter jagen", so the location is always reachable without costing the
hunt loop its one-click rhythm.
The store raises the arrival only after the server-owned current location
has been re-read, and does not navigate itself — timers, arrival times and
the server-side completion are untouched; only the screen that shows the
result changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The server resolves a whole round in one call, so both blows used to land
at the same instant. The page now keeps its own view of the combat and
plays the round back: the swing animates, the monster's HP and log line
land, then after a beat the monster strikes and the player recoils.
Both animations are six-frame sprite sheets driven by steps(6), which is
why the phase durations mirror the stylesheet.
The status row reflows on the stage's own width via a container query —
the side rails can squeeze it narrow while the viewport is still wide,
which previously overlapped the round marker with the player's name. The
component-style budget moves to 12kB to fit this screen's stylesheet.
Move both health bars to a status row at the top of the scene with a
circular portrait beside each, and place full-body sprites for the
player and the monster standing on the location background instead of
square portraits. The Angriff action now uses the ornate HUD frame art,
with the keybind in the frame's own tab.
Sprite and icon derivatives are keyed by monster key so both seeded
monsters resolve; the Aschenratte body art still carries its original
backdrop until a cut-out version replaces it at the same path.
Wires up the Slice 0.3 combat screen (player/monster HP bars, round
display, Angriff action, grouped German combat log, victory/defeat
panels) and replaces the Slice 0.2 combat/new placeholder route with
combat/:combatId loading CombatPageComponent.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>