7.6 KiB
Feature Specification: HP Status Indicators
Feature Branch: 013-hp-status-indicators
Created: 2026-03-05
Status: Draft
Input: User description: "When a combatant's health is lower than half, the creature is considered bloodied, which makes the UI show an indicator. If a combatant is at <=0 HP the creature is unconscious/dead, which should also be shown. Visual treatment at implementer's discretion to fit the existing modern UI style."
User Scenarios & Testing (mandatory)
User Story 1 - Bloodied Indicator (Priority: P1)
As a game master running an encounter, I want to see at a glance which combatants are bloodied (below half their maximum HP) so I can narrate the battle's intensity and make tactical decisions without mental math.
Why this priority: The bloodied condition is a core D&D/TTRPG concept that GMs check frequently during combat. Providing a visual indicator eliminates the need to compare current HP vs max HP for every combatant each round.
Independent Test: Can be fully tested by setting a combatant's max HP and reducing current HP below half, then verifying the visual indicator appears. Delivers immediate at-a-glance awareness.
Acceptance Scenarios:
- Given a combatant with max HP set to 20 and current HP at 10, When the combatant row is displayed, Then the HP area shows a bloodied visual indicator (e.g., amber/orange color treatment on the HP value)
- Given a combatant with max HP set to 20 and current HP at 9, When the combatant row is displayed, Then the bloodied indicator is visible
- Given a combatant with max HP set to 20 and current HP at 11, When the combatant row is displayed, Then no bloodied indicator is shown (normal appearance)
- Given a combatant with max HP set to 21 (odd number) and current HP at 10, When the combatant row is displayed, Then the bloodied indicator is shown (10 < 21/2 = 10.5)
- Given a combatant with no max HP set, When the combatant row is displayed, Then no status indicator is shown regardless of current HP value
User Story 2 - Unconscious/Dead Indicator (Priority: P1)
As a game master, I want to see which combatants have reached 0 HP or below so I can immediately identify who is down without scanning HP numbers.
Why this priority: Equally critical to bloodied -- knowing who is unconscious or dead is essential for combat flow and takes priority over other status information.
Independent Test: Can be fully tested by reducing a combatant's current HP to 0 or below and verifying the visual indicator appears.
Acceptance Scenarios:
- Given a combatant with max HP set to 20 and current HP at 0, When the combatant row is displayed, Then the HP area shows an unconscious/dead visual indicator (e.g., red color treatment and/or a skull/death icon)
- Given a combatant with max HP set to 20 and current HP at -5, When the combatant row is displayed, Then the unconscious/dead indicator is shown (negative HP still counts as down)
- Given a combatant with max HP set to 20 and current HP at 1, When the combatant row is displayed, Then the unconscious/dead indicator is NOT shown (1 HP is bloodied, not dead)
- Given a combatant at 0 HP whose HP is then healed above 0, When the HP changes, Then the unconscious/dead indicator is removed and replaced with the appropriate status (bloodied or healthy)
User Story 3 - Status Transitions (Priority: P2)
As a game master adjusting HP during combat, I want the visual indicators to update in real time as I apply damage or healing so I always have an accurate picture of the battlefield.
Why this priority: Indicator transitions are a natural consequence of the first two stories but need explicit attention to ensure smooth, responsive visual feedback.
Independent Test: Can be tested by using the quick HP input to deal damage across thresholds and observing indicator changes.
Acceptance Scenarios:
- Given a combatant at full HP (20/20), When I deal 11 damage (reducing to 9/20), Then the indicator transitions from healthy to bloodied
- Given a bloodied combatant (5/20), When I deal 5 damage (reducing to 0/20), Then the indicator transitions from bloodied to unconscious/dead
- Given an unconscious combatant (0/20), When I heal 15 HP (restoring to 15/20), Then the indicator transitions from unconscious/dead to healthy (skipping bloodied since 15 > 10)
Edge Cases
- What happens when max HP is 1? At 1/1 HP the combatant is healthy; at 0/1 HP they are unconscious/dead. There is no bloodied state since 0 < 0.5 rounds to unconscious/dead.
- What happens when max HP is 2? At 1/2 HP the combatant is healthy (1 is not less than 2/2 = 1); at 0/2 they are unconscious/dead. Bloodied only applies when currentHp < maxHp / 2 (strict less-than with exact division).
- What happens when current HP exceeds max HP (e.g., temporary HP or manual override)? The combatant shows healthy status -- no special indicator for over-max.
- What happens when max HP is set but current HP has not been modified? Current HP equals max HP by default, so the combatant shows healthy status.
Requirements (mandatory)
Functional Requirements
- FR-001: System MUST derive a combatant's HP status from their current HP and max HP values: "healthy" (currentHp >= maxHp / 2), "bloodied" (0 < currentHp < maxHp / 2), or "unconscious" (currentHp <= 0)
- FR-002: System MUST display a visual indicator on the combatant row when a combatant is bloodied -- the HP value text MUST use a warm/amber color to signal danger
- FR-003: System MUST display a visual indicator on the combatant row when a combatant is unconscious/dead -- the HP value text MUST use a red/destructive color and the row MUST appear visually muted (reduced opacity or strikethrough name) to signal the combatant is out of action
- FR-004: System MUST NOT show any status indicator when max HP is not set for a combatant
- FR-005: System MUST update the visual indicator immediately when current HP changes (no delay or animation lag)
- FR-006: The HP status derivation MUST be a pure domain-level computation with no UI dependencies
Key Entities
- HP Status: A derived value (not stored) computed from a combatant's currentHp and maxHp. Possible values: "healthy", "bloodied", "unconscious". Only meaningful when maxHp is defined.
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: Users can identify bloodied combatants at a glance without reading HP numbers -- 100% of combatants below half HP display a distinct visual treatment
- SC-002: Users can identify unconscious/dead combatants at a glance -- 100% of combatants at 0 HP or below display a distinct visual treatment that differs from the bloodied indicator
- SC-003: Visual indicators update within the same interaction frame as HP changes -- no perceptible delay between HP adjustment and indicator update
- SC-004: Status indicators are visually consistent with the existing UI design system (colors, spacing, typography match the established style)
Assumptions
- "Bloodied" uses the D&D 4e/5e convention: strictly below half max HP (not at exactly half)
- The unconscious/dead label is intentionally combined into one state -- the system does not distinguish between unconscious and dead (this is a GM decision, not a system decision)
- No sound effects or animation beyond color/opacity changes for MVP baseline
- MVP baseline does not include a tooltip or label explaining what "bloodied" means
- The status is purely visual/derived -- it does not affect game mechanics or stored data