Add manual CR assignment and difficulty breakdown panel
All checks were successful
CI / check (push) Successful in 2m20s
CI / build-image (push) Successful in 17s

Implement issue #21: custom combatants can now have a challenge rating
assigned via a new breakdown panel, opened by tapping the difficulty
indicator. Bestiary-linked combatants show read-only CR with source name;
custom combatants get a CR picker with all standard 5e values. CR persists
across reloads and round-trips through JSON export/import.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-04-02 17:03:33 +02:00
parent 2c643cc98b
commit 1ae9e12cff
26 changed files with 1461 additions and 17 deletions

View File

@@ -9,6 +9,7 @@ import {
removeCombatantUseCase,
retreatTurnUseCase,
setAcUseCase,
setCrUseCase,
setHpUseCase,
setInitiativeUseCase,
setTempHpUseCase,
@@ -52,6 +53,7 @@ type EncounterAction =
| { type: "adjust-hp"; id: CombatantId; delta: number }
| { type: "set-temp-hp"; id: CombatantId; tempHp: number | undefined }
| { type: "set-ac"; id: CombatantId; value: number | undefined }
| { type: "set-cr"; id: CombatantId; value: string | undefined }
| {
type: "toggle-condition";
id: CombatantId;
@@ -318,6 +320,7 @@ function dispatchEncounterAction(
| { type: "adjust-hp" }
| { type: "set-temp-hp" }
| { type: "set-ac" }
| { type: "set-cr" }
| { type: "toggle-condition" }
| { type: "toggle-concentration" }
>,
@@ -358,6 +361,9 @@ function dispatchEncounterAction(
case "set-ac":
result = setAcUseCase(store, action.id, action.value);
break;
case "set-cr":
result = setCrUseCase(store, action.id, action.value);
break;
case "toggle-condition":
result = toggleConditionUseCase(store, action.id, action.conditionId);
break;
@@ -495,6 +501,11 @@ export function useEncounter() {
dispatch({ type: "set-ac", id, value }),
[],
),
setCr: useCallback(
(id: CombatantId, value: string | undefined) =>
dispatch({ type: "set-cr", id, value }),
[],
),
toggleCondition: useCallback(
(id: CombatantId, conditionId: ConditionId) =>
dispatch({ type: "toggle-condition", id, conditionId }),