89 lines
3.2 KiB
Markdown
89 lines
3.2 KiB
Markdown
# Data Model: Combat Conditions
|
|
|
|
## Entities
|
|
|
|
### ConditionId (new type)
|
|
|
|
String literal union representing the 15 valid condition identifiers.
|
|
|
|
```
|
|
"blinded" | "charmed" | "deafened" | "exhaustion" | "frightened" |
|
|
"grappled" | "incapacitated" | "invisible" | "paralyzed" | "petrified" |
|
|
"poisoned" | "prone" | "restrained" | "stunned" | "unconscious"
|
|
```
|
|
|
|
- Order of literals in the union defines the canonical display order (FR-003).
|
|
- Extensible: future conditions can be added to the union.
|
|
|
|
### ConditionDefinition (new type)
|
|
|
|
Static metadata for each condition.
|
|
|
|
| Field | Type | Description |
|
|
| --------- | ----------- | ------------------------------------------------ |
|
|
| id | ConditionId | Unique identifier |
|
|
| label | string | Human-readable display name (e.g., "Blinded") |
|
|
| iconName | string | Lucide icon component name (e.g., "EyeOff") |
|
|
| color | string | Color category (e.g., "neutral", "pink", "amber") |
|
|
|
|
- Registry: `CONDITION_DEFINITIONS` — a static readonly array of all 15 definitions, ordered by display priority.
|
|
- No lifecycle/state transitions — definitions are immutable reference data.
|
|
|
|
### Combatant (modified)
|
|
|
|
| Field | Type | Change |
|
|
| ---------- | ----------------------------- | -------- |
|
|
| id | CombatantId | existing |
|
|
| name | string | existing |
|
|
| initiative | number \| undefined | existing |
|
|
| maxHp | number \| undefined | existing |
|
|
| currentHp | number \| undefined | existing |
|
|
| ac | number \| undefined | existing |
|
|
| conditions | readonly ConditionId[] \| undefined | **new** |
|
|
|
|
- `conditions` is optional; `undefined` means no conditions active.
|
|
- When present, the array contains unique `ConditionId` values sorted in definition order.
|
|
- Maximum cardinality: 15 (one of each condition).
|
|
|
|
## Relationships
|
|
|
|
```
|
|
Encounter 1──* Combatant
|
|
Combatant 0──* ConditionId (from CONDITION_DEFINITIONS registry)
|
|
```
|
|
|
|
## Validation Rules
|
|
|
|
- A condition can appear at most once per combatant.
|
|
- Only valid `ConditionId` values are accepted (unknown strings rejected).
|
|
- The conditions array is always sorted in definition order after any mutation.
|
|
- An empty conditions array is normalized to `undefined`.
|
|
|
|
## Domain Events
|
|
|
|
### ConditionAdded
|
|
|
|
| Field | Type |
|
|
| ----------- | ----------- |
|
|
| type | "ConditionAdded" |
|
|
| combatantId | CombatantId |
|
|
| condition | ConditionId |
|
|
|
|
Emitted when a condition is toggled on or explicitly added.
|
|
|
|
### ConditionRemoved
|
|
|
|
| Field | Type |
|
|
| ----------- | ----------- |
|
|
| type | "ConditionRemoved" |
|
|
| combatantId | CombatantId |
|
|
| condition | ConditionId |
|
|
|
|
Emitted when a condition is toggled off (via picker or tag click).
|
|
|
|
## Persistence
|
|
|
|
- Serialization: `conditions` array serializes to JSON as `["blinded", "poisoned"]`.
|
|
- Deserialization: Filter stored values through the `ConditionId` set; discard unknown strings. If resulting array is empty, set to `undefined`.
|
|
- No schema migration required (field is optional with `undefined` default).
|