New source found from dndbeyond.com
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import React, { useCallback, useContext, useEffect, useMemo } from "react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
import { Tooltip } from "@dndbeyond/character-common-components/es";
|
||||
import {
|
||||
DiceComponentUtils,
|
||||
@@ -19,19 +20,16 @@ import {
|
||||
Spell,
|
||||
LeveledSpellManager,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
import { RollTypes } from "@dndbeyond/pocket-dimension-dice/constants";
|
||||
import {
|
||||
Dice,
|
||||
DiceEvent,
|
||||
DiceTools,
|
||||
IRollContext,
|
||||
RollRequest,
|
||||
RollType,
|
||||
} from "@dndbeyond/dice";
|
||||
import { GameLogContext } from "@dndbeyond/game-log-components";
|
||||
RollContext,
|
||||
RollDicePayload,
|
||||
} from "@dndbeyond/pocket-dimension-dice/types";
|
||||
|
||||
import { ItemName } from "~/components/ItemName";
|
||||
import { NumberDisplay } from "~/components/NumberDisplay";
|
||||
import { SpellName } from "~/components/SpellName";
|
||||
import { TypeScriptUtils } from "../../utils";
|
||||
|
||||
import SpellSlotChooser from "../SpellSlotChooser";
|
||||
import { ThemeButton } from "../common/Button";
|
||||
|
||||
@@ -61,7 +59,7 @@ interface Props {
|
||||
diceEnabled: boolean;
|
||||
theme: CharacterTheme;
|
||||
proficiencyBonus: number;
|
||||
rollContext: IRollContext;
|
||||
rollContext: RollContext;
|
||||
}
|
||||
|
||||
function SpellsSpell({
|
||||
@@ -89,9 +87,9 @@ function SpellsSpell({
|
||||
() => new LeveledSpellManager({ spell: spellData }),
|
||||
[spellData]
|
||||
);
|
||||
const [isSlotChooserOpen, setIsSlotChooserOpen] = React.useState(false);
|
||||
const [isCriticalHit, setIsCriticalHit] = React.useState(false);
|
||||
const spellsSpellNode = React.useRef<HTMLDivElement>(null);
|
||||
const [isSlotChooserOpen, setIsSlotChooserOpen] = useState(false);
|
||||
const [isCriticalHit, setIsCriticalHit] = useState(false);
|
||||
const spellsSpellNode = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleSpellClick = (evt: React.MouseEvent): void => {
|
||||
evt.nativeEvent.stopImmediatePropagation();
|
||||
@@ -127,22 +125,11 @@ function SpellsSpell({
|
||||
setIsSlotChooserOpen(false);
|
||||
};
|
||||
|
||||
const handleRollResults = (result: RollRequest): void => {
|
||||
const handleRollResults = (result: RollDicePayload["data"]): void => {
|
||||
let wasCrit = DiceComponentUtils.isCriticalRoll(result);
|
||||
setIsCriticalHit(wasCrit);
|
||||
};
|
||||
|
||||
const diceEventHandler = useMemo(() => {
|
||||
if (!spellsSpellNode.current) {
|
||||
return () => {
|
||||
/* NOOP */
|
||||
};
|
||||
}
|
||||
return DiceComponentUtils.setupResetCritStateOnRoll(
|
||||
spell.getName(),
|
||||
spellsSpellNode.current
|
||||
);
|
||||
}, [spell]);
|
||||
// TODO: use mui click away listener
|
||||
const handleDocumentClick = useCallback((): void => {
|
||||
handleSpellSlotChooserClose();
|
||||
@@ -154,15 +141,11 @@ function SpellsSpell({
|
||||
if (isSlotChooserOpen) {
|
||||
document.removeEventListener("click", handleDocumentClick);
|
||||
}
|
||||
|
||||
Dice.removeEventListener(DiceEvent.ROLL, diceEventHandler);
|
||||
},
|
||||
[isSlotChooserOpen, handleDocumentClick, diceEventHandler]
|
||||
[isSlotChooserOpen, handleDocumentClick]
|
||||
);
|
||||
|
||||
// Todo: consider making a separate component for this
|
||||
const [{ messageTargetOptions, defaultMessageTargetOption, userId }] =
|
||||
useContext(GameLogContext);
|
||||
const renderAttackInfo = (): React.ReactNode => {
|
||||
let toHit: number | null = null;
|
||||
let saveDcValue: number | null = null;
|
||||
@@ -182,27 +165,18 @@ function SpellsSpell({
|
||||
return (
|
||||
<div className="ct-spells-spell__tohit">
|
||||
<DigitalDiceWrapper
|
||||
diceNotation={DiceTools.CustomD20(toHit)}
|
||||
rollType={RollType.ToHit}
|
||||
rollAction={spell.getName()}
|
||||
diceEnabled={diceEnabled}
|
||||
themeColor={theme.themeColor}
|
||||
onRollResults={handleRollResults}
|
||||
rollContext={rollContext}
|
||||
rollTargetOptions={
|
||||
messageTargetOptions
|
||||
? Object.values(messageTargetOptions.entities).filter(
|
||||
TypeScriptUtils.isNotNullOrUndefined
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
rollTargetDefault={defaultMessageTargetOption}
|
||||
userId={Number(userId) || 0}
|
||||
diceNotation={`1d20${
|
||||
toHit > 0 ? `+${toHit}` : toHit !== 0 ? toHit : ""
|
||||
}`}
|
||||
rollType={RollTypes.ToHit}
|
||||
action={spell.getName()}
|
||||
isDiceEnabled={diceEnabled}
|
||||
rollCallback={handleRollResults}
|
||||
entityId={String(rollContext.entityId)}
|
||||
entityType={String(rollContext.entityType)}
|
||||
name={String(rollContext.name)}
|
||||
>
|
||||
<NumberDisplay
|
||||
number={toHit}
|
||||
type="signed"
|
||||
/>
|
||||
<NumberDisplay number={toHit} type="signed" />
|
||||
</DigitalDiceWrapper>
|
||||
</div>
|
||||
);
|
||||
@@ -312,7 +286,7 @@ function SpellsSpell({
|
||||
actionNode = <span className="ct-spells-spell__at-will">At Will</span>;
|
||||
} else {
|
||||
actionNode = (
|
||||
<React.Fragment>
|
||||
<>
|
||||
<ThemeButton
|
||||
size={"small"}
|
||||
onClick={
|
||||
@@ -337,7 +311,7 @@ function SpellsSpell({
|
||||
doesPactSlotExist={doesPactSlotExist}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
</>
|
||||
);
|
||||
}
|
||||
let classNames: Array<string> = ["ct-spells-spell", className];
|
||||
@@ -431,6 +405,11 @@ function SpellsSpell({
|
||||
theme={theme}
|
||||
isCriticalHit={isCriticalHit}
|
||||
rollContext={rollContext}
|
||||
rollCallback={() => {
|
||||
if (isCriticalHit) {
|
||||
setIsCriticalHit(false);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{showNotes && (
|
||||
|
||||
Reference in New Issue
Block a user