Implement the 025-display-initiative feature that adds initiative modifier and passive initiative display to creature stat blocks, calculated as DEX modifier + (proficiency multiplier × proficiency bonus) from bestiary data, shown in MM 2024 format on the AC line

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-10 11:27:46 +01:00
parent c6349928eb
commit 5b0bac880d
14 changed files with 650 additions and 1 deletions

View File

@@ -0,0 +1,63 @@
# Data Model: Display Initiative
## Modified Entities
### Creature (domain)
**File**: `packages/domain/src/creature-types.ts`
Add one new field to the `Creature` interface:
| Field | Type | Description |
|-------|------|-------------|
| `initiativeProficiency` | `number` | Proficiency multiplier for initiative (0, 1, or 2). Defaults to 0 when absent from bestiary data. |
This field stores the raw multiplier from bestiary data. The actual initiative modifier is derived via the `calculateInitiative` function — not stored on the entity.
### Initiative (derived value)
**File**: `packages/domain/src/initiative.ts`
Not a persisted entity — a computed result from a pure function.
| Field | Type | Description |
|-------|------|-------------|
| `modifier` | `number` | The initiative modifier: DEX mod + (proficiency multiplier × proficiency bonus) |
| `passive` | `number` | The passive initiative: 10 + modifier |
## New Functions
### `calculateInitiative` (domain)
**File**: `packages/domain/src/initiative.ts`
```
Input: { dexScore: number, cr: string, initiativeProficiency: number }
Output: { modifier: number, passive: number }
```
Pure function. No side effects. Uses existing `proficiencyBonus(cr)` helper.
### `formatInitiativeModifier` (domain)
**File**: `packages/domain/src/initiative.ts`
```
Input: modifier: number
Output: string (e.g., "+7", "1", "+0")
```
Formats the modifier with explicit sign. Uses U+2212 () for negative values.
## Modified Adapters
### Bestiary Adapter
**File**: `apps/web/src/adapters/bestiary-adapter.ts`
- Add `initiative?: { proficiency?: number }` to `RawMonster` interface
- Parse `m.initiative?.proficiency ?? 0` into `Creature.initiativeProficiency`
## State Transitions
None. This feature is purely derived/display. No state mutations, no events, no persistence changes.