Initiative rolls (single and bulk) called makeStore() directly from useInitiativeRolls, bypassing the withUndo wrapper. Expose withUndo from the encounter context and wrap both roll paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import {
|
|
rollAllInitiativeUseCase,
|
|
rollInitiativeUseCase,
|
|
} from "@initiative/application";
|
|
import {
|
|
type CombatantId,
|
|
isDomainError,
|
|
type RollMode,
|
|
} from "@initiative/domain";
|
|
import { useCallback, useState } from "react";
|
|
import { useBestiaryContext } from "../contexts/bestiary-context.js";
|
|
import { useEncounterContext } from "../contexts/encounter-context.js";
|
|
import { useSidePanelContext } from "../contexts/side-panel-context.js";
|
|
|
|
function rollDice(): number {
|
|
return Math.floor(Math.random() * 20) + 1;
|
|
}
|
|
|
|
export function useInitiativeRolls() {
|
|
const { encounter, makeStore, withUndo } = useEncounterContext();
|
|
const { getCreature } = useBestiaryContext();
|
|
const { showCreature } = useSidePanelContext();
|
|
|
|
const [rollSkippedCount, setRollSkippedCount] = useState(0);
|
|
const [rollSingleSkipped, setRollSingleSkipped] = useState(false);
|
|
|
|
const handleRollInitiative = useCallback(
|
|
(id: CombatantId, mode: RollMode = "normal") => {
|
|
const diceRolls: [number, ...number[]] =
|
|
mode === "normal" ? [rollDice()] : [rollDice(), rollDice()];
|
|
const result = withUndo(() =>
|
|
rollInitiativeUseCase(makeStore(), id, diceRolls, getCreature, mode),
|
|
);
|
|
if (isDomainError(result)) {
|
|
setRollSingleSkipped(true);
|
|
const combatant = encounter.combatants.find((c) => c.id === id);
|
|
if (combatant?.creatureId) {
|
|
showCreature(combatant.creatureId);
|
|
}
|
|
}
|
|
},
|
|
[makeStore, getCreature, withUndo, encounter.combatants, showCreature],
|
|
);
|
|
|
|
const handleRollAllInitiative = useCallback(
|
|
(mode: RollMode = "normal") => {
|
|
const result = withUndo(() =>
|
|
rollAllInitiativeUseCase(makeStore(), rollDice, getCreature, mode),
|
|
);
|
|
if (!isDomainError(result) && result.skippedNoSource > 0) {
|
|
setRollSkippedCount(result.skippedNoSource);
|
|
}
|
|
},
|
|
[makeStore, getCreature, withUndo],
|
|
);
|
|
|
|
return {
|
|
rollSkippedCount,
|
|
rollSingleSkipped,
|
|
dismissRollSkipped: useCallback(() => setRollSkippedCount(0), []),
|
|
dismissRollSingleSkipped: useCallback(
|
|
() => setRollSingleSkipped(false),
|
|
[],
|
|
),
|
|
handleRollInitiative,
|
|
handleRollAllInitiative,
|
|
} as const;
|
|
}
|