import * as React from "react"; import { Action, ActionUtils, Attack, CharacterTheme, Item, ItemUtils, Spell, SpellUtils, } from "@dndbeyond/character-rules-engine/es"; import { AttackSourceTypeEnum } from "@dndbeyond/character-rules-engine/es/engine/Character"; import { DiceTools, RollType, RollRequest, IRollContext, } from "@dndbeyond/dice"; import { GameLogContext } from "@dndbeyond/game-log-components"; import { DiceComponentUtils } from "../utils"; import { NumberDisplay } from "~/components/NumberDisplay"; import { DigitalDiceWrapper } from "../Dice"; interface Props { attack: Attack; className: string; icon: React.ReactNode; name: React.ReactNode; metaItems: Array; rangeValue: React.ReactNode; rangeLabel: React.ReactNode; isProficient: boolean; toHit: number | null; attackSaveValue?: number | null; attackSaveLabel?: React.ReactNode; damage: React.ReactNode; notes?: React.ReactNode; theme: CharacterTheme; rollContext: IRollContext; onClick?: (attack: Attack) => void; showNotes: boolean; diceEnabled: boolean; onRoll?: (wasCrit: boolean) => void; } class CombatAttack extends React.PureComponent { static defaultProps = { rangeLabel: "Reach", damage: "--", className: "", showNotes: true, isProficient: false, diceEnabled: false, }; handleClick = (evt: React.MouseEvent): void => { const { onClick, attack } = this.props; if (onClick) { evt.nativeEvent.stopImmediatePropagation(); evt.stopPropagation(); onClick(attack); } }; handleRollResults = (result: RollRequest) => { const { onRoll } = this.props; let wasCrit = DiceComponentUtils.isCriticalRoll(result); if (onRoll) { onRoll(wasCrit); } }; render() { const { icon, name, metaItems, rangeLabel, rangeValue, toHit, attackSaveValue, attackSaveLabel, damage, notes, className, showNotes, diceEnabled, attack, theme, rollContext, } = this.props; const [{ messageTargetOptions, defaultMessageTargetOption, userId }] = this.context; let actionNode: React.ReactNode = null; if (toHit !== null) { let rollAction: string; switch (attack.type) { case AttackSourceTypeEnum.ACTION: case AttackSourceTypeEnum.CUSTOM: rollAction = ActionUtils.getName(attack.data as Action); break; case AttackSourceTypeEnum.ITEM: rollAction = ItemUtils.getName(attack.data as Item); break; case AttackSourceTypeEnum.SPELL: rollAction = SpellUtils.getName(attack.data as Spell); break; } actionNode = (
); } else if (attackSaveValue !== null) { actionNode = (
{attackSaveValue} {attackSaveLabel}
); } let classNames: Array = [className, "ddbc-combat-attack"]; return (
{icon}
{name}
{metaItems.length > 0 && (
{metaItems.map((metaItem, idx) => ( {metaItem} ))}
)}
{rangeValue ? ( rangeValue ) : ( -- )}
{rangeLabel}
{actionNode ? ( actionNode ) : ( -- )}
{damage}
{showNotes && (
{notes}
)}
); } } CombatAttack.contextType = GameLogContext; export default CombatAttack;