Add PF2e persistent damage condition tags
All checks were successful
CI / check (push) Successful in 2m39s
CI / build-image (push) Successful in 19s

Persistent damage displayed as compact tags with damage type icon and
formula (e.g., Flame + "2d6"). Supports fire, bleed, acid, cold,
electricity, poison, and mental types. One instance per type, added via
sub-picker in the condition picker. PF2e only, persists across reload.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-04-11 12:09:31 +02:00
parent 09a801487d
commit 4b1c1deda2
20 changed files with 1257 additions and 111 deletions

View File

@@ -1,6 +1,7 @@
import type { EncounterStore, UndoRedoStore } from "@initiative/application";
import {
addCombatantUseCase,
addPersistentDamageUseCase,
adjustHpUseCase,
advanceTurnUseCase,
clearEncounterUseCase,
@@ -8,6 +9,7 @@ import {
editCombatantUseCase,
redoUseCase,
removeCombatantUseCase,
removePersistentDamageUseCase,
retreatTurnUseCase,
setAcUseCase,
setConditionValueUseCase,
@@ -28,6 +30,7 @@ import type {
DomainError,
DomainEvent,
Encounter,
PersistentDamageType,
Pf2eCreature,
PlayerCharacter,
UndoRedoState,
@@ -78,6 +81,17 @@ type EncounterAction =
conditionId: ConditionId;
}
| { type: "toggle-concentration"; id: CombatantId }
| {
type: "add-persistent-damage";
id: CombatantId;
damageType: PersistentDamageType;
formula: string;
}
| {
type: "remove-persistent-damage";
id: CombatantId;
damageType: PersistentDamageType;
}
| { type: "clear-encounter" }
| { type: "undo" }
| { type: "redo" }
@@ -427,6 +441,8 @@ function dispatchEncounterAction(
| { type: "set-condition-value" }
| { type: "decrement-condition" }
| { type: "toggle-concentration" }
| { type: "add-persistent-damage" }
| { type: "remove-persistent-damage" }
>,
): EncounterState {
const { store, getEncounter } = makeStoreFromState(state);
@@ -488,6 +504,21 @@ function dispatchEncounterAction(
case "toggle-concentration":
result = toggleConcentrationUseCase(store, action.id);
break;
case "add-persistent-damage":
result = addPersistentDamageUseCase(
store,
action.id,
action.damageType,
action.formula,
);
break;
case "remove-persistent-damage":
result = removePersistentDamageUseCase(
store,
action.id,
action.damageType,
);
break;
}
if (isDomainError(result)) return state;
@@ -651,6 +682,16 @@ export function useEncounter() {
(id: CombatantId) => dispatch({ type: "toggle-concentration", id }),
[],
),
addPersistentDamage: useCallback(
(id: CombatantId, damageType: PersistentDamageType, formula: string) =>
dispatch({ type: "add-persistent-damage", id, damageType, formula }),
[],
),
removePersistentDamage: useCallback(
(id: CombatantId, damageType: PersistentDamageType) =>
dispatch({ type: "remove-persistent-damage", id, damageType }),
[],
),
setCreatureAdjustment: useCallback(
(
id: CombatantId,