Grabbed dndbeyond's source code
``` ~/go/bin/sourcemapper -output ddb -jsurl https://media.dndbeyond.com/character-app/static/js/main.90aa78c5.js ```
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
import * as React from "react";
|
||||
import { Tooltip } from "@dndbeyond/character-common-components/es";
|
||||
import {
|
||||
ConditionUtils,
|
||||
DiceUtils,
|
||||
HigherLevelContract,
|
||||
HigherLevelEntryContract,
|
||||
ModifierUtils,
|
||||
RuleData,
|
||||
RuleDataUtils,
|
||||
Spell,
|
||||
SpellConditionContract,
|
||||
SpellModifierContract,
|
||||
SpellUtils,
|
||||
CharacterTheme,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
import { RollType, RollKind, IRollContext } from "@dndbeyond/dice";
|
||||
import { GameLogContext } from "@dndbeyond/game-log-components";
|
||||
import { HealingIcon } from "../Icons";
|
||||
import { DiceComponentUtils } from "../utils";
|
||||
import { DigitalDiceWrapper } from "../Dice";
|
||||
import Damage from "../Damage";
|
||||
|
||||
interface Props {
|
||||
spell: Spell;
|
||||
castLevel: number;
|
||||
characterLevel: number;
|
||||
ruleData: RuleData;
|
||||
diceEnabled: boolean;
|
||||
theme: CharacterTheme;
|
||||
isCriticalHit?: boolean;
|
||||
rollContext: IRollContext;
|
||||
}
|
||||
class SpellDamageEffect extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
diceEnabled: false,
|
||||
};
|
||||
|
||||
getPoints = (
|
||||
atHigherLevels: HigherLevelContract | null
|
||||
): Array<HigherLevelEntryContract> => {
|
||||
let points: Array<HigherLevelEntryContract> = [];
|
||||
if (atHigherLevels && atHigherLevels.points !== null) {
|
||||
points = atHigherLevels.points;
|
||||
}
|
||||
return points;
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
spell,
|
||||
castLevel,
|
||||
characterLevel,
|
||||
ruleData,
|
||||
diceEnabled,
|
||||
theme,
|
||||
isCriticalHit,
|
||||
rollContext,
|
||||
} = this.props;
|
||||
|
||||
const [{ messageTargetOptions, defaultMessageTargetOption, userId }] =
|
||||
this.context;
|
||||
|
||||
let isScaled: boolean = false;
|
||||
const modifiers = SpellUtils.getModifiers(spell);
|
||||
const tags = SpellUtils.getTags(spell);
|
||||
const conditions = SpellUtils.getConditions(spell);
|
||||
|
||||
let displayNode: React.ReactNode;
|
||||
let damageModifiers = modifiers.filter((modifier) =>
|
||||
ModifierUtils.isSpellDamageModifier(modifier)
|
||||
);
|
||||
if (damageModifiers.length) {
|
||||
let modifier: SpellModifierContract = damageModifiers[0];
|
||||
const friendlySubtypeName =
|
||||
ModifierUtils.getFriendlySubtypeName(modifier);
|
||||
const atHigherLevels = ModifierUtils.getAtHigherLevels(modifier);
|
||||
let scaleType = SpellUtils.getScaleType(spell);
|
||||
let points = this.getPoints(atHigherLevels);
|
||||
let atHigherDamage = SpellUtils.getSpellScaledAtHigher(
|
||||
spell,
|
||||
scaleType,
|
||||
points,
|
||||
characterLevel,
|
||||
castLevel
|
||||
);
|
||||
let scaledDamageDie = SpellUtils.getSpellFinalScaledDie(
|
||||
spell,
|
||||
modifier,
|
||||
atHigherDamage
|
||||
);
|
||||
isScaled =
|
||||
isScaled ||
|
||||
SpellUtils.isSpellScaledByCastLevel(
|
||||
spell,
|
||||
scaleType,
|
||||
points,
|
||||
castLevel
|
||||
);
|
||||
|
||||
displayNode = (
|
||||
<span className="ddbc-spell-damage-effect__damages">
|
||||
<DigitalDiceWrapper
|
||||
diceNotation={DiceUtils.renderDice(scaledDamageDie)}
|
||||
rollType={RollType.Damage}
|
||||
rollAction={SpellUtils.getName(spell)}
|
||||
rollKind={isCriticalHit ? RollKind.CriticalHit : RollKind.None}
|
||||
diceEnabled={diceEnabled}
|
||||
themeColor={theme.themeColor}
|
||||
rollContext={rollContext}
|
||||
rollTargetOptions={
|
||||
messageTargetOptions
|
||||
? Object.values(messageTargetOptions?.entities)
|
||||
: undefined
|
||||
}
|
||||
rollTargetDefault={defaultMessageTargetOption}
|
||||
userId={userId}
|
||||
>
|
||||
<Damage
|
||||
damage={DiceComponentUtils.getDamageDiceNotation(
|
||||
scaledDamageDie,
|
||||
isCriticalHit
|
||||
)}
|
||||
type={friendlySubtypeName || ""}
|
||||
showInfoTooltip={false}
|
||||
theme={theme}
|
||||
/>
|
||||
</DigitalDiceWrapper>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
let hitPointHealingModifiers = modifiers.filter((modifier) =>
|
||||
ModifierUtils.isSpellHealingHitPointsModifier(modifier)
|
||||
);
|
||||
if (!displayNode && hitPointHealingModifiers.length) {
|
||||
let modifier: SpellModifierContract = hitPointHealingModifiers[0];
|
||||
const atHigherLevels = ModifierUtils.getAtHigherLevels(modifier);
|
||||
let scaleType = SpellUtils.getScaleType(spell);
|
||||
let points = this.getPoints(atHigherLevels);
|
||||
let atHigherHealing = SpellUtils.getSpellScaledAtHigher(
|
||||
spell,
|
||||
scaleType,
|
||||
points,
|
||||
characterLevel,
|
||||
castLevel
|
||||
);
|
||||
let scaledHealingDie = SpellUtils.getSpellFinalScaledDie(
|
||||
spell,
|
||||
modifier,
|
||||
atHigherHealing,
|
||||
castLevel
|
||||
);
|
||||
isScaled =
|
||||
isScaled ||
|
||||
SpellUtils.isSpellScaledByCastLevel(
|
||||
spell,
|
||||
scaleType,
|
||||
points,
|
||||
castLevel
|
||||
);
|
||||
|
||||
displayNode = (
|
||||
<span className="ddbc-spell-damage-effect__healing ddbc-spell-damage-effect__healing--hp">
|
||||
<DigitalDiceWrapper
|
||||
useAdvancedMenu={false}
|
||||
diceNotation={DiceUtils.renderDice(scaledHealingDie)}
|
||||
rollType={RollType.Heal}
|
||||
rollAction={SpellUtils.getName(spell)}
|
||||
diceEnabled={diceEnabled}
|
||||
rollContext={rollContext}
|
||||
rollTargetOptions={
|
||||
messageTargetOptions
|
||||
? Object.values(messageTargetOptions?.entities)
|
||||
: undefined
|
||||
}
|
||||
rollTargetDefault={defaultMessageTargetOption}
|
||||
userId={userId}
|
||||
>
|
||||
{DiceUtils.renderDice(scaledHealingDie)}{" "}
|
||||
<HealingIcon theme={theme} isHp={true} />
|
||||
</DigitalDiceWrapper>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const tempHitPointHealingModifiers = modifiers.filter((modifier) =>
|
||||
ModifierUtils.isSpellHealingTempHitPointsModifier(modifier)
|
||||
);
|
||||
if (!displayNode && tempHitPointHealingModifiers.length) {
|
||||
let modifier = tempHitPointHealingModifiers[0];
|
||||
const atHigherLevels = ModifierUtils.getAtHigherLevels(modifier);
|
||||
let scaleType = SpellUtils.getScaleType(spell);
|
||||
let points = this.getPoints(atHigherLevels);
|
||||
let atHigherHealing = SpellUtils.getSpellScaledAtHigher(
|
||||
spell,
|
||||
scaleType,
|
||||
points,
|
||||
characterLevel,
|
||||
castLevel
|
||||
);
|
||||
let scaledHealingDie = SpellUtils.getSpellFinalScaledDie(
|
||||
spell,
|
||||
modifier,
|
||||
atHigherHealing,
|
||||
castLevel
|
||||
);
|
||||
isScaled =
|
||||
isScaled ||
|
||||
SpellUtils.isSpellScaledByCastLevel(
|
||||
spell,
|
||||
scaleType,
|
||||
points,
|
||||
castLevel
|
||||
);
|
||||
|
||||
displayNode = (
|
||||
<span className="ddbc-spell-damage-effect__healing ddbc-spell-damage-effect__healing--temp">
|
||||
<DigitalDiceWrapper
|
||||
useAdvancedMenu={false}
|
||||
diceNotation={DiceUtils.renderDice(scaledHealingDie)}
|
||||
rollType={RollType.Heal}
|
||||
rollAction={SpellUtils.getName(spell)}
|
||||
diceEnabled={diceEnabled}
|
||||
rollContext={rollContext}
|
||||
rollTargetOptions={
|
||||
messageTargetOptions
|
||||
? Object.values(messageTargetOptions?.entities)
|
||||
: undefined
|
||||
}
|
||||
rollTargetDefault={defaultMessageTargetOption}
|
||||
userId={userId}
|
||||
>
|
||||
{DiceUtils.renderDice(scaledHealingDie)}{" "}
|
||||
<HealingIcon theme={theme} isTemp={true} />
|
||||
</DigitalDiceWrapper>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (!displayNode && conditions.length) {
|
||||
let spellCondition: SpellConditionContract = conditions[0];
|
||||
let condition = RuleDataUtils.getCondition(
|
||||
spellCondition.conditionId,
|
||||
ruleData
|
||||
);
|
||||
let name: string =
|
||||
condition === null ? "" : ConditionUtils.getName(condition);
|
||||
displayNode = (
|
||||
<span
|
||||
className={`ddbc-spell-damage-effect__conditions ${
|
||||
theme.isDarkMode
|
||||
? "ddbc-spell-damage-effect__conditions--dark-mode"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<Tooltip
|
||||
isDarkMode={theme.isDarkMode}
|
||||
title={`${name}${
|
||||
spellCondition.exception ? `, ${spellCondition.exception}` : ""
|
||||
}`}
|
||||
>
|
||||
{name}
|
||||
</Tooltip>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (!displayNode && tags.length) {
|
||||
displayNode = (
|
||||
<span
|
||||
className={`ddbc-spell-damage-effect__tags ${
|
||||
theme.isDarkMode ? "ddbc-spell-damage-effect__tags--dark-mode" : ""
|
||||
}`}
|
||||
>
|
||||
{tags[0]}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
let hasMore: boolean = damageModifiers.length > 1;
|
||||
hasMore = hasMore || hitPointHealingModifiers.length > 1;
|
||||
hasMore = hasMore || tempHitPointHealingModifiers.length > 1;
|
||||
hasMore = hasMore || conditions.length > 1;
|
||||
hasMore = hasMore || tags.length > 1;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`ddbc-spell-damage-effect ${
|
||||
isScaled ? "ddbc-spell-damage-effect--scaled" : ""
|
||||
} ${theme.isDarkMode ? "ddbc-spell-damage-effect--dark-mode" : ""}`}
|
||||
>
|
||||
{displayNode}
|
||||
{hasMore ? "*" : ""}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SpellDamageEffect.contextType = GameLogContext;
|
||||
|
||||
export default SpellDamageEffect;
|
||||
@@ -0,0 +1,4 @@
|
||||
import SpellDamageEffect from "./SpellDamageEffect";
|
||||
|
||||
export default SpellDamageEffect;
|
||||
export { SpellDamageEffect };
|
||||
Reference in New Issue
Block a user