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:
2025-05-28 11:50:03 -07:00
commit 8df9031d27
3592 changed files with 319051 additions and 0 deletions
@@ -0,0 +1,526 @@
/**
*
* @param action
*/
export function getDefinitionName(action) {
return action.definition.name;
}
/**
*
* @param action
*/
export function getDefinitionAbilityModifierStatId(action) {
return action.definition.abilityModifierStatId;
}
/**
*
* @param action
*/
export function getAbilityModifierStatId(action) {
return getDefinitionAbilityModifierStatId(action);
}
/**
*
* @param action
*/
export function getDefinitionAttackSubtypeId(action) {
return action.definition.attackSubtype;
}
/**
*
* @param action
*/
export function getAttackSubtypeId(action) {
return getDefinitionAttackSubtypeId(action);
}
/**
*
* @param action
*/
export function getDefinitionAttackRangeId(action) {
return action.definition.attackTypeRange;
}
/**
*
* @param action
*/
export function getAttackRangeId(action) {
return getDefinitionAttackRangeId(action);
}
/**
*
* @param action
*/
export function getDefinitionActivation(action) {
return action.definition.activation;
}
/**
*
* @param action
*/
export function getActivation(action) {
return getDefinitionActivation(action);
}
/**
*
* @param action
*/
export function getDefinitionActionTypeId(action) {
return action.definition.actionType;
}
/**
*
* @param action
*/
export function getActionTypeId(action) {
return getDefinitionActionTypeId(action);
}
/**
*
* @param action
*/
export function getDefinitionDamageTypeId(action) {
return action.definition.damageTypeId;
}
/**
*
* @param action
*/
export function getDamageTypeId(action) {
return getDefinitionDamageTypeId(action);
}
/**
*
* @param action
*/
export function getDefinitionDescription(action) {
return action.definition.description;
}
/**
*
* @param action
*/
export function getDescription(action) {
return getDefinitionDescription(action);
}
/**
*
* @param action
*/
export function getDefinitionSnippet(action) {
return action.definition.snippet;
}
/**
*
* @param action
*/
export function getSnippet(action) {
return getDefinitionSnippet(action);
}
/**
*
* @param action
*/
export function getDefinitionDice(action) {
return action.definition.dice;
}
/**
*
* @param action
*/
export function getDice(action) {
return getDefinitionDice(action);
}
/**
*
* @param action
*/
export function getDefinitionIsMartialArts(action) {
return action.definition.isMartialArts;
}
/**
*
* @param action
*/
export function getIsMartialArts(action) {
return getDefinitionIsMartialArts(action);
}
/**
*
* @param action
*/
export function getDefinitionIsProficienct(action) {
return action.definition.isProficient;
}
/**
*
* @param action
*/
export function getIsProficienct(action) {
return getDefinitionIsProficienct(action);
}
/**
*
* @param action
*/
export function getDefinitionOnMissDescription(action) {
return action.definition.onMissDescription;
}
/**
*
* @param action
*/
export function getOnMissDescription(action) {
return getDefinitionOnMissDescription(action);
}
/**
*
* @param action
*/
export function getDefinitionRange(action) {
return action.definition.range;
}
/**
*
* @param action
*/
export function getDefinitionFixedSaveDc(action) {
return action.definition.fixedSaveDc;
}
/**
*
* @param action
*/
export function getFixedSaveDc(action) {
return getDefinitionFixedSaveDc(action);
}
/**
*
* @param action
*/
export function getDefinitionSaveFailDescription(action) {
return action.definition.saveFailDescription;
}
/**
*
* @param action
*/
export function getSaveFailDescription(action) {
return getDefinitionSaveFailDescription(action);
}
/**
*
* @param action
*/
export function getDefinitionSaveStatId(action) {
return action.definition.saveStatId;
}
/**
*
* @param action
*/
export function getSaveStatId(action) {
return getDefinitionSaveStatId(action);
}
/**
*
* @param action
*/
export function getDefinitionSaveSuccessDescription(action) {
return action.definition.saveSuccessDescription;
}
/**
*
* @param action
*/
export function getSaveSuccessDescription(action) {
return getDefinitionSaveSuccessDescription(action);
}
/**
*
* @param action
*/
export function getDefinitionDisplayAsAttack(action) {
return action.definition.displayAsAttack;
}
/**
*
* @param action
*/
export function getDisplayAsAttack(action) {
return getDefinitionDisplayAsAttack(action);
}
/**
*
* @param action
*/
export function getDefinitionSpellRangeType(action) {
return action.definition.spellRangeType;
}
/**
*
* @param action
*/
export function getSpellRangeType(action) {
return getDefinitionSpellRangeType(action);
}
/**
*
* @param action
*/
export function getDefinitionFixedValue(action) {
return action.definition.value;
}
/**
*
* @param action
*/
export function getFixedValue(action) {
return getDefinitionFixedValue(action);
}
/**
*
* @param action
*/
export function getFixedToHit(action) {
return getDefinitionFixedToHit(action);
}
/**
*
* @param action
*/
export function getDefinitionFixedToHit(action) {
return action.definition.fixedToHit;
}
/**
*
* @param action
*/
export function getDefinitionNumberOfTargets(action) {
return action.definition.numberOfTargets;
}
/**
*
* @param action
*/
export function getAmmunition(action) {
return getDefinitionAmmunition(action);
}
/**
*
* @param action
*/
export function getDefinitionAmmunition(action) {
return action.definition.ammunition;
}
/**
*
* @param action
*/
export function getNumberOfTargets(action) {
return getDefinitionNumberOfTargets(action);
}
/**
*
* @param action
*/
export function getDefinition(action) {
return action.definition;
}
/**
*
* @param action
*/
export function getComponentId(action) {
return action.componentId;
}
/**
*
* @param action
*/
export function getComponentTypeId(action) {
return action.componentTypeId;
}
/**
*
* @param action
*/
export function getEntityTypeId(action) {
return getMappingEntityTypeId(action);
}
/**
*
* @param action
*/
export function getMappingEntityTypeId(action) {
return action.entityTypeId;
}
/**
*
* @param action
*/
export function getId(action) {
return getMappingId(action);
}
/**
*
* @param action
*/
export function getMappingId(action) {
return action.id;
}
/**
*
* @param action
*/
export function getLimitedUse(action) {
return action.limitedUse;
}
/**
*
* @param action
*/
export function displayAsAttack(action) {
return action.displayAsAttack;
}
/**
*
* @param action
*/
export function getName(action) {
return action.name;
}
/**
*
* @param action
*/
export function getNotes(action) {
return action.notes;
}
/**
*
* @param action
*/
export function getOriginalContract(action) {
return action.originalContract;
}
/**
*
* @param action
*/
export function isProficient(action) {
return action.proficiency;
}
/**
*
* @param action
*/
export function requiresAttackRoll(action) {
return action.requiresAttackRoll;
}
/**
*
* @param action
*/
export function requiresSavingThrow(action) {
return action.requiresSavingThrow;
}
/**
*
* @param action
*/
export function getUniqueKey(action) {
return action.uniqueKey;
}
/**
*
* @param action
*/
export function getDataOrigin(action) {
return action.dataOrigin;
}
/**
*
* @param action
*/
export function getDataOriginType(action) {
const dataOrigin = getDataOrigin(action);
return dataOrigin.type;
}
/**
*
* @param action
*/
export function getAttackSaveValue(action) {
return action.attackSaveValue;
}
/**
*
* @param action
*/
export function getAttackSubtypeName(action) {
return action.attackSubtypeName;
}
/**
*
* @param action
*/
export function getDamage(action) {
return action.damage;
}
/**
*
* @param action
*/
export function getRange(action) {
return action.range;
}
/**
*
* @param action
*/
export function getReach(action) {
return action.reach;
}
/**
*
* @param action
*/
export function getStatId(action) {
return action.statId;
}
/**
*
* @param action
*/
export function getToHit(action) {
return action.toHit;
}
/**
*
* @param action
*/
export function isOffhand(action) {
return action.isOffhand;
}
/**
*
* @param action
*/
export function isSilvered(action) {
return action.isSilvered;
}
/**
*
* @param action
*/
export function isDefaultDisplayAsAttack(action) {
return action.isDefaultDisplayAsAttack;
}
/**
*
* @param action
*/
export function isCustomized(action) {
return action.isCustomized;
}
@@ -0,0 +1,21 @@
import { AdjustmentTypeEnum } from '../Value';
export var ActionTypeEnum;
(function (ActionTypeEnum) {
ActionTypeEnum[ActionTypeEnum["WEAPON"] = 1] = "WEAPON";
ActionTypeEnum[ActionTypeEnum["SPELL"] = 2] = "SPELL";
ActionTypeEnum[ActionTypeEnum["GENERAL"] = 3] = "GENERAL";
})(ActionTypeEnum || (ActionTypeEnum = {}));
export var AttackSubtypeEnum;
(function (AttackSubtypeEnum) {
AttackSubtypeEnum[AttackSubtypeEnum["MANUFACTURED"] = 1] = "MANUFACTURED";
AttackSubtypeEnum[AttackSubtypeEnum["NATURAL"] = 2] = "NATURAL";
AttackSubtypeEnum[AttackSubtypeEnum["UNARMED"] = 3] = "UNARMED";
})(AttackSubtypeEnum || (AttackSubtypeEnum = {}));
export const ACTION_CUSTOMIZATION_ADJUSTMENT_TYPES = [
AdjustmentTypeEnum.TO_HIT_OVERRIDE,
AdjustmentTypeEnum.TO_HIT_BONUS,
AdjustmentTypeEnum.FIXED_VALUE_BONUS,
AdjustmentTypeEnum.DISPLAY_AS_ATTACK,
AdjustmentTypeEnum.NAME_OVERRIDE,
AdjustmentTypeEnum.NOTES,
];
@@ -0,0 +1,467 @@
import { TypeScriptUtils } from '../../utils';
import { AbilityAccessors } from '../Ability';
import { CharacterDerivers } from '../Character';
import { ClassAccessors } from '../Class';
import { AbilityStatEnum, AttackTypeRangeEnum } from '../Core';
import { DataOriginTypeEnum } from '../DataOrigin';
import { DiceAccessors, DiceDerivers, DiceUtils } from '../Dice';
import { HelperUtils } from '../Helper';
import { ModifierAccessors, ModifierDerivers, ModifierValidators } from '../Modifier';
import { RuleDataAccessors, RuleDataUtils } from '../RuleData';
import { AdjustmentTypeEnum, ValueUtils, ValueValidators } from '../Value';
import { getAbilityModifierStatId, getActionTypeId, getAttackRangeId, getAttackSubtypeId, getDamageTypeId, getDataOrigin, getDataOriginType, getDefinitionName, getDefinitionRange, getDice, getDisplayAsAttack, getEntityTypeId, getFixedSaveDc, getFixedToHit, getId, getIsMartialArts, getIsProficienct, getMappingEntityTypeId, getMappingId, getSaveStatId, getSpellRangeType, requiresAttackRoll, } from './accessors';
import { ACTION_CUSTOMIZATION_ADJUSTMENT_TYPES, ActionTypeEnum, AttackSubtypeEnum } from './constants';
/**
*
* @param action
*/
export function deriveUniqueKey(action) {
return `${getId(action)}-${getEntityTypeId(action)}`;
}
/**
*
* @param action
*/
export function deriveRequiresAttackRoll(action) {
return getAttackRangeId(action) !== null;
}
/**
*
* @param action
*/
export function deriveRequiresSavingThrow(action) {
return getSaveStatId(action) !== null;
}
/**
*
* @param action
*/
export function deriveIsDefaultDisplayAsAttack(action) {
const displayAsAttack = getDisplayAsAttack(action);
if (displayAsAttack !== null) {
return displayAsAttack;
}
return deriveRequiresAttackRoll(action);
}
/**
*
* @param action
*/
export function deriveAttackSubtypeName(action) {
switch (getAttackSubtypeId(action)) {
case AttackSubtypeEnum.UNARMED:
return 'Unarmed Strike';
case AttackSubtypeEnum.NATURAL:
return 'Natural Attack';
}
return null;
}
/**
*
* @param action
* @param martialArtsLevelScale
*/
export function deriveIsMartialArtsAvailable(action, martialArtsLevelScale) {
const isMartialArtsEnabled = getIsMartialArts(action);
const attackSubtype = getAttackSubtypeId(action);
if (martialArtsLevelScale !== null && (attackSubtype === AttackSubtypeEnum.UNARMED || isMartialArtsEnabled)) {
return true;
}
return false;
}
/**
*
* @param action
* @param ruleData
*/
export function deriveFallbackAbilityIds(action, ruleData) {
const actionType = getActionTypeId(action);
const attackTypeRange = getAttackRangeId(action);
const availableAbilities = [];
if (actionType === ActionTypeEnum.WEAPON) {
if (attackTypeRange === AttackTypeRangeEnum.RANGED) {
availableAbilities.push(AbilityStatEnum.DEXTERITY);
}
else {
availableAbilities.push(AbilityStatEnum.STRENGTH);
}
}
else {
const dataOrigin = getDataOrigin(action);
const dataOriginType = getDataOriginType(action);
switch (dataOriginType) {
case DataOriginTypeEnum.CLASS_FEATURE:
const primaryAbilities = ClassAccessors.getPrimaryAbilities(dataOrigin.parent);
if (primaryAbilities.length) {
availableAbilities.push(...primaryAbilities);
}
break;
}
}
return availableAbilities;
}
/**
*
* @param action
* @param abilityLookup
* @param ruleData
*/
export function deriveBestFallbackAbility(action, abilityLookup, ruleData) {
const fallbackAbilityIds = deriveFallbackAbilityIds(action, ruleData);
const fallbackAbilities = fallbackAbilityIds.map((id) => abilityLookup[id]);
return HelperUtils.getLast(fallbackAbilities, 'modifier');
}
/**
*
* @param action
* @param martialArtsLevelScale
* @param ruleData
* @param includeFallbacks
*/
export function deriveAvailableAbilities(action, martialArtsLevelScale, ruleData, includeFallbacks = true) {
let attackStat = null;
if (requiresAttackRoll(action)) {
attackStat = getAbilityModifierStatId(action);
}
const availableAbilities = [];
if (attackStat) {
availableAbilities.push(attackStat);
}
else if (includeFallbacks) {
availableAbilities.push(...deriveFallbackAbilityIds(action, ruleData));
}
if (deriveIsMartialArtsAvailable(action, martialArtsLevelScale) &&
!availableAbilities.includes(AbilityStatEnum.DEXTERITY)) {
availableAbilities.push(AbilityStatEnum.DEXTERITY);
}
return availableAbilities;
}
/**
*
* @param action
* @param abilityLookup
* @param proficiencyBonus
* @param valueLookup
* @param ruleData
*/
export function deriveAttackSaveValue(action, abilityLookup, proficiencyBonus, valueLookup, ruleData) {
const id = getMappingId(action);
const entityId = getMappingEntityTypeId(action);
if (getSaveStatId(action) === null) {
return null;
}
const fixedSaveDc = getFixedSaveDc(action);
if (fixedSaveDc) {
return fixedSaveDc;
}
const saveDcOverride = ValueUtils.getKeyValue(valueLookup, AdjustmentTypeEnum.SAVE_DC_OVERRIDE, id, entityId);
if (saveDcOverride !== null) {
return saveDcOverride;
}
let attackSaveAbility = null;
const abilityModifierStatId = getAbilityModifierStatId(action);
if (abilityModifierStatId) {
attackSaveAbility = abilityLookup[abilityModifierStatId];
}
else {
attackSaveAbility = deriveBestFallbackAbility(action, abilityLookup, ruleData);
}
if (!attackSaveAbility) {
return null;
}
const abilityModifier = AbilityAccessors.getModifier(attackSaveAbility);
const attackSaveAbilityModifier = abilityModifier ? abilityModifier : 0;
let saveDc = CharacterDerivers.deriveAttackSaveValue(proficiencyBonus, attackSaveAbilityModifier);
saveDc += ValueUtils.getKeyValue(valueLookup, AdjustmentTypeEnum.SAVE_DC_BONUS, id, entityId, 0);
return saveDc;
}
/**
*
* @param bestAbilityInfo
* @param action
* @param modifiers
* @param abilityLookup
* @param valueLookup
*/
export function deriveToHit(bestAbilityInfo, action, modifiers, abilityLookup, valueLookup) {
const actionType = getActionTypeId(action);
let toHit = null;
if (bestAbilityInfo && getAttackRangeId(action) !== null) {
const id = getMappingId(action);
const entityId = getMappingEntityTypeId(action);
const toHitOverride = ValueUtils.getKeyValue(valueLookup, AdjustmentTypeEnum.TO_HIT_OVERRIDE, id, entityId);
if (toHitOverride !== null) {
return toHitOverride;
}
let bonusToHitModifiers = null;
let bonusToHitModifierTotal = 0;
if (actionType === ActionTypeEnum.SPELL) {
bonusToHitModifiers = modifiers.filter((modifier) => ModifierValidators.isValidBonusActionSpellToHitModifier(modifier, action));
}
else if (actionType === ActionTypeEnum.WEAPON) {
bonusToHitModifiers = modifiers.filter((modifier) => ModifierValidators.isValidBonusActionWeaponToHitModifier(modifier, action));
}
if (bonusToHitModifiers !== null) {
bonusToHitModifierTotal = ModifierDerivers.sumModifiers(bonusToHitModifiers, abilityLookup);
}
const toHitCustomBonus = ValueUtils.getKeyValue(valueLookup, AdjustmentTypeEnum.TO_HIT_BONUS, id, entityId, 0);
toHit = bestAbilityInfo.toHit + bonusToHitModifierTotal + toHitCustomBonus;
}
const fixedToHit = getFixedToHit(action);
if (fixedToHit !== null) {
toHit = fixedToHit;
}
return toHit;
}
/**
*
* @param action
* @param baseDamage
* @param fixedDamageBonuses
* @param valueLookup
* @param ruleData
*/
export function deriveDamage(action, baseDamage, fixedDamageBonuses, valueLookup, ruleData) {
const id = getMappingId(action);
const entityId = getMappingEntityTypeId(action);
const damageTypeId = getDamageTypeId(action);
let type = null;
let value = null;
let dataOrigin = null;
let isMartialArts = false;
const damageCustomBonus = ValueUtils.getKeyValue(valueLookup, AdjustmentTypeEnum.FIXED_VALUE_BONUS, id, entityId, 0);
const fixedDamage = fixedDamageBonuses + damageCustomBonus;
if (baseDamage !== null) {
if (typeof baseDamage === 'number') {
value = Math.max(0, baseDamage + fixedDamage);
}
else if (baseDamage.isMartialArts !== undefined) {
if (baseDamage.dataOrigin) {
dataOrigin = baseDamage.dataOrigin;
}
else if (baseDamage.isMartialArts) {
isMartialArts = true;
}
const fixedValue = DiceAccessors.getFixedValue(baseDamage);
value = Object.assign(Object.assign({}, baseDamage), { fixedValue: (fixedValue ? fixedValue : 0) + fixedDamage });
}
}
if (damageTypeId) {
type = RuleDataUtils.getDamageType(damageTypeId, ruleData);
}
return {
type,
value,
dataOrigin,
isMartialArts,
};
}
/**
*
* @param action
* @param valueLookup
*/
export function deriveName(action, valueLookup) {
const id = getMappingId(action);
const entityId = getMappingEntityTypeId(action);
let derivedName = getDefinitionName(action);
const nameOverride = ValueUtils.getKeyValue(valueLookup, AdjustmentTypeEnum.NAME_OVERRIDE, id, entityId);
if (nameOverride) {
derivedName = nameOverride;
}
if (derivedName === null) {
derivedName = '';
}
return derivedName;
}
/**
*
* @param action
* @param modifiers
*/
export function deriveLabel(action, modifiers) {
const masteryModifiers = modifiers.filter((modifier) => ModifierValidators.isValidWeaponMasteryModifier(modifier));
const masteryModifier = masteryModifiers.find((modifier) => modifier.componentId === action.componentId);
if (masteryModifier) {
return ModifierAccessors.getFriendlySubtypeName(masteryModifier);
}
return null;
}
/**
*
* @param action
* @param proficiencyBonus
*/
export function deriveProficiencyBonus(action, proficiencyBonus) {
let bonus = 0;
if (getIsProficienct(action)) {
bonus = proficiencyBonus;
}
return bonus;
}
/**
*
* @param action
*/
export function deriveProficiency(action) {
return getIsProficienct(action);
}
/**
*
* @param action
* @param valueLookup
*/
export function deriveDisplayAsAttack(action, valueLookup) {
const id = getMappingId(action);
const entityId = getMappingEntityTypeId(action);
const displayAsAttackOverride = ValueUtils.getKeyValue(valueLookup, AdjustmentTypeEnum.DISPLAY_AS_ATTACK, id, entityId);
if (displayAsAttackOverride !== null) {
return displayAsAttackOverride;
}
return deriveIsDefaultDisplayAsAttack(action);
}
/**
*
* @param action
* @param modifiers
* @param modifierData
* @param ruleData
*/
export function deriveReach(action, modifiers, modifierData, ruleData) {
let baseReach = null;
if (getActionTypeId(action) === ActionTypeEnum.SPELL) {
return null;
}
// Reach is null if it isn't a melee attack
if (getAttackRangeId(action) !== AttackTypeRangeEnum.MELEE) {
return null;
}
// Figure out base reach based on initial data
const range = getDefinitionRange(action);
if (range) {
baseReach = range.range;
}
if (baseReach === null) {
baseReach = RuleDataAccessors.getBaseWeaponReach(ruleData);
}
const bonusReachModifiers = modifiers.filter((modifier) => ModifierValidators.isBonusMeleeReachModifier(modifier));
const bonusReachModifierTotal = ModifierDerivers.deriveTotalValue(bonusReachModifiers, modifierData);
return baseReach + bonusReachModifierTotal;
}
/**
*
* @param action
* @param martialArtsLevelScale
* @param modifiers
*/
export function deriveHighestDamageDie(action, martialArtsLevelScale, modifiers) {
const actionType = getActionTypeId(action);
const baseDice = getDice(action);
const attackSubtype = getAttackSubtypeId(action);
const isMartialArtsAvailable = deriveIsMartialArtsAvailable(action, martialArtsLevelScale);
const allDamageDice = [];
if (baseDice) {
allDamageDice.push(Object.assign(Object.assign({}, baseDice), { isMartialArts: false, dataOrigin: null }));
}
if (actionType === ActionTypeEnum.WEAPON && attackSubtype === AttackSubtypeEnum.UNARMED) {
const setDamageDieModifiers = modifiers.filter((modifier) => ModifierValidators.isSetUnarmedDamageDieModifier(modifier));
const setDamageDice = setDamageDieModifiers
.map((modifier) => {
const modifierDice = ModifierAccessors.getDice(modifier);
if (modifierDice === null) {
return null;
}
return Object.assign(Object.assign({}, modifierDice), { isMartialArts: false, dataOrigin: ModifierAccessors.getDataOrigin(modifier) });
})
.filter(TypeScriptUtils.isNotNullOrUndefined);
allDamageDice.push(...setDamageDice);
}
if (martialArtsLevelScale !== null && isMartialArtsAvailable) {
const martialArtsDie = DiceDerivers.deriveMartialArtsDamageDie(martialArtsLevelScale);
allDamageDice.push(Object.assign(Object.assign({}, martialArtsDie), { isMartialArts: true, dataOrigin: null }));
}
return DiceUtils.getHighestDie(allDamageDice);
}
/**
*
* @param bestAbilityInfo
* @param action
* @param modifiers
* @param abilityLookup
*/
export function deriveFixedDamageBonuses(bestAbilityInfo, action, modifiers, abilityLookup) {
const actionType = getActionTypeId(action);
let damageModifiers = [];
let damageModifierTotal = 0;
if (actionType === ActionTypeEnum.SPELL) {
damageModifiers = modifiers.filter((modifier) => ModifierValidators.isValidDamageActionSpellModifier(modifier, action));
}
else if (actionType === ActionTypeEnum.WEAPON) {
damageModifiers = modifiers.filter((modifier) => ModifierValidators.isValidDamageActionWeaponModifier(modifier, action));
}
if (damageModifiers.length) {
damageModifierTotal = ModifierDerivers.sumModifiers(damageModifiers, abilityLookup);
}
return damageModifierTotal + (bestAbilityInfo ? bestAbilityInfo.damageBonus : 0);
}
/**
*
* @param action
* @param modifiers
* @param abilityLookup
*/
export function deriveRange(action, modifiers, abilityLookup) {
const actionType = getActionTypeId(action);
const definitionRange = getDefinitionRange(action);
if (definitionRange === null) {
return definitionRange;
}
let range = Object.assign(Object.assign({}, definitionRange), { origin: null });
if (actionType === ActionTypeEnum.SPELL) {
const attackTypeRange = getAttackRangeId(action);
let newRange = definitionRange.range;
if (attackTypeRange !== null && newRange) {
const spellAttackRangeMultiplierModifiers = modifiers.filter((modifier) => ModifierValidators.isBonusSpellAttackRangeMultiplierModifier(modifier));
const spellAttackRangeMultiplierTotal = Math.max(1, ModifierDerivers.sumModifiers(spellAttackRangeMultiplierModifiers, abilityLookup, 1));
newRange *= spellAttackRangeMultiplierTotal;
}
range = Object.assign(Object.assign({}, definitionRange), { range: newRange, origin: getSpellRangeType(action) });
}
return range;
}
/**
*
* @param action
* @param valueLookup
*/
export function deriveIsOffhand(action, valueLookup) {
let isOffhand = false;
if (getActionTypeId(action) === ActionTypeEnum.WEAPON) {
const id = getMappingId(action);
const entityId = getMappingEntityTypeId(action);
isOffhand = ValueUtils.getKeyValue(valueLookup, AdjustmentTypeEnum.IS_OFFHAND, id, entityId, false);
}
return isOffhand;
}
/**
*
* @param action
* @param valueLookup
*/
export function deriveIsSilvered(action, valueLookup) {
let isSilvered = false;
if (getActionTypeId(action) === ActionTypeEnum.WEAPON) {
const id = getMappingId(action);
const entityId = getMappingEntityTypeId(action);
isSilvered = ValueUtils.getKeyValue(valueLookup, AdjustmentTypeEnum.IS_SILVER, id, entityId, false);
}
return isSilvered;
}
/**
*
* @param action
* @param valueLookup
*/
export function deriveIsCustomized(action, valueLookup) {
return ValueValidators.validateHasCustomization(ACTION_CUSTOMIZATION_ADJUSTMENT_TYPES, valueLookup, getMappingId(action), getMappingEntityTypeId(action));
}
@@ -0,0 +1,237 @@
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { groupBy, keyBy } from 'lodash';
import { CharacterDerivers } from '../Character';
import { ClassAccessors } from '../Class';
import { DataOriginGenerators, DataOriginTypeEnum } from '../DataOrigin';
import { FeatAccessors } from '../Feat';
import { HelperUtils } from '../Helper';
import { ItemAccessors } from '../Item';
import { OptionAccessors } from '../Option';
import { RaceAccessors } from '../Race';
import { RuleDataAccessors } from '../RuleData';
import { AdjustmentTypeEnum, ValueUtils } from '../Value';
import { getActionTypeId, getDisplayAsAttack, getFixedValue, getUniqueKey } from './accessors';
import { ActionTypeEnum } from './constants';
import { deriveAttackSaveValue, deriveAttackSubtypeName, deriveAvailableAbilities, deriveDamage, deriveDisplayAsAttack, deriveFixedDamageBonuses, deriveHighestDamageDie, deriveIsCustomized, deriveIsDefaultDisplayAsAttack, deriveIsOffhand, deriveIsSilvered, deriveName, deriveProficiency, deriveProficiencyBonus, deriveRange, deriveReach, deriveRequiresAttackRoll, deriveRequiresSavingThrow, deriveToHit, deriveUniqueKey, } from './derivers';
/**
*
* @param action
*/
export function generateDataOriginKey(action) {
return DataOriginGenerators.generateDataOriginKey(action.componentId, action.componentTypeId);
}
/**
*
* @param id
* @param entityTypeId
* @param actionLookup
* @param valueLookup
* @param dataOriginType
* @param primary
* @param parent
*/
export function generateBaseActions(id, entityTypeId, actionLookup, valueLookup, dataOriginType, primary, parent = null) {
const actions = HelperUtils.lookupDataOrFallback(actionLookup, DataOriginGenerators.generateDataOriginKey(id, entityTypeId));
if (!actions) {
return [];
}
return actions.map((action) => generateDataOriginBaseAction(action, valueLookup, dataOriginType, primary, parent));
}
/**
*
* @param action
* @param valueLookup
*/
export function generateBaseAction(action, valueLookup) {
const { componentId, componentTypeId, displayAsAttack, entityTypeId, id, limitedUse, name } = action, definitionProps = __rest(action, ["componentId", "componentTypeId", "displayAsAttack", "entityTypeId", "id", "limitedUse", "name"]);
const simulatedAction = {
definition: Object.assign(Object.assign({}, definitionProps), { displayAsAttack,
name }),
componentId,
componentTypeId,
entityTypeId,
id,
limitedUse,
};
return Object.assign(Object.assign({}, simulatedAction), { displayAsAttack: deriveDisplayAsAttack(simulatedAction, valueLookup), name: deriveName(simulatedAction, valueLookup), notes: ValueUtils.getKeyValue(valueLookup, AdjustmentTypeEnum.NOTES, id, entityTypeId), originalContract: action, proficiency: deriveProficiency(simulatedAction), requiresAttackRoll: deriveRequiresAttackRoll(simulatedAction), requiresSavingThrow: deriveRequiresSavingThrow(simulatedAction), isDefaultDisplayAsAttack: deriveIsDefaultDisplayAsAttack(simulatedAction), uniqueKey: deriveUniqueKey(simulatedAction) });
}
/**
*
* @param actions
* @param valueLookup
* @param type
* @param primary
* @param parent
*/
export function generateDataOriginBaseActions(actions, valueLookup, type, primary = null, parent = null) {
return actions.map((action) => generateDataOriginBaseAction(action, valueLookup, type, primary, parent));
}
/**
*
* @param action
* @param valueLookup
* @param dataOriginType
* @param primary
* @param parent
*/
export function generateDataOriginBaseAction(action, valueLookup, dataOriginType, primary, parent) {
const dataOrigin = DataOriginGenerators.generateDataOrigin(dataOriginType, primary, parent);
return Object.assign(Object.assign({}, generateBaseAction(action, valueLookup)), { dataOrigin });
}
/**
*
* @param action
* @param valueLookup
*/
export function generateInnateNaturalDataOriginBaseAction(action, valueLookup) {
return generateDataOriginBaseAction(action, valueLookup, DataOriginTypeEnum.RULE_DATA, null, null);
}
/**
*
* @param baseAction
* @param proficiencyBonus
* @param abilityLookup
* @param modifiers
* @param valueLookup
* @param martialArtsLevelScale
* @param ruleData
* @param modifierData
*/
export function generateAction(baseAction, proficiencyBonus, abilityLookup, modifiers, valueLookup, martialArtsLevelScale, ruleData, modifierData) {
const actionType = getActionTypeId(baseAction);
const fixedValue = getFixedValue(baseAction);
const highestDamageDie = deriveHighestDamageDie(baseAction, martialArtsLevelScale, modifiers);
const includeFallback = actionType !== ActionTypeEnum.GENERAL;
const availableAbilities = deriveAvailableAbilities(baseAction, martialArtsLevelScale, ruleData, includeFallback);
const attackProficiencyBonus = deriveProficiencyBonus(baseAction, proficiencyBonus);
const abilityPossibilities = CharacterDerivers.deriveAttackAbilityPossibilities(availableAbilities, modifiers, attackProficiencyBonus, abilityLookup);
const bestAbilityInfo = HelperUtils.getLast(abilityPossibilities, ['toHit', 'modifier']);
const fixedDamageBonuses = deriveFixedDamageBonuses(bestAbilityInfo, baseAction, modifiers, abilityLookup);
const damage = deriveDamage(baseAction, highestDamageDie ? highestDamageDie : fixedValue, fixedDamageBonuses, valueLookup, ruleData);
return Object.assign(Object.assign({}, baseAction), { attackSaveValue: deriveAttackSaveValue(baseAction, abilityLookup, proficiencyBonus, valueLookup, ruleData), attackSubtypeName: deriveAttackSubtypeName(baseAction), damage, range: deriveRange(baseAction, modifiers, abilityLookup), reach: deriveReach(baseAction, modifiers, modifierData, ruleData), statId: bestAbilityInfo ? bestAbilityInfo.abilityId : null, toHit: deriveToHit(bestAbilityInfo, baseAction, modifiers, abilityLookup, valueLookup), isOffhand: deriveIsOffhand(baseAction, valueLookup), isSilvered: deriveIsSilvered(baseAction, valueLookup), isCustomized: deriveIsCustomized(baseAction, valueLookup) });
}
/**
*
* @param actions
*/
export function generateActionComponentLookup(actions) {
return groupBy(actions, (action) => generateDataOriginKey(action));
}
/**
*
* @param actions
*/
export function generateActionLookup(actions) {
return keyBy(actions, (action) => getUniqueKey(action));
}
/**
*
* @param feats
* @param race
* @param classes
* @param innateNaturalActions
* @param inventory
* @param proficiencyBonus
* @param abilityLookup
* @param modifiers
* @param martialArtsLevel
* @param ruleData
* @param modifierData
* @param valueLookup
*/
export function generateAggregatedActions(feats, race, classes, innateNaturalActions, inventory, proficiencyBonus, abilityLookup, modifiers, martialArtsLevelScale, ruleData, modifierData, valueLookup) {
const actions = [];
actions.push(...innateNaturalActions);
if (race) {
actions.push(...RaceAccessors.getActions(race));
}
classes.forEach((charClass) => {
actions.push(...ClassAccessors.getActions(charClass));
});
feats.forEach((feat) => {
actions.push(...FeatAccessors.getActions(feat));
FeatAccessors.getOptions(feat).forEach((option) => {
actions.push(...OptionAccessors.getActions(option));
});
});
inventory.forEach((item) => {
actions.push(...ItemAccessors.getInfusionActions(item));
});
return actions.map((baseAction) => generateAction(baseAction, proficiencyBonus, abilityLookup, modifiers, valueLookup, martialArtsLevelScale, ruleData, modifierData));
}
/**
*
* @param customActions
* @param proficiencyBonus
* @param abilityLookup
* @param valueLookup
* @param modifiers
* @param martialArtsLevel
* @param ruleData
* @param modifierData
*/
export function generateCustomActions(customActions, proficiencyBonus, abilityLookup, valueLookup, modifiers, martialArtsLevelScale, ruleData, modifierData) {
return customActions.map((customAction) => generateCustomAction(customAction, proficiencyBonus, abilityLookup, valueLookup, modifiers, martialArtsLevelScale, ruleData, modifierData));
}
/**
*
* @param customAction
* @param proficiencyBonus
* @param abilityLookup
* @param valueLookup
* @param modifiers
* @param martialArtsLevelScale
* @param ruleData
* @param modifierData
*/
export function generateCustomAction(customAction, proficiencyBonus, abilityLookup, valueLookup, modifiers, martialArtsLevelScale, ruleData, modifierData) {
const { aoeSize, aoeType, longRange, range, activationTime, activationType, diceCount, diceType, fixedValue, rangeId, statId, displayAsAttack, id, isSilvered, isOffhand } = customAction, similarActionProps = __rest(customAction, ["aoeSize", "aoeType", "longRange", "range", "activationTime", "activationType", "diceCount", "diceType", "fixedValue", "rangeId", "statId", "displayAsAttack", "id", "isSilvered", "isOffhand"]);
let dice = null;
let value = null;
if (diceType) {
dice = {
diceCount: diceCount ? diceCount : 1,
diceValue: diceType,
fixedValue,
diceMultiplier: null,
diceString: null,
};
}
else {
value = fixedValue;
}
const actionLike = Object.assign(Object.assign({}, similarActionProps), { id, range: {
range,
longRange,
aoeSize,
aoeType,
minimumRange: null,
hasAoeSpecialDescription: false, // default
}, activation: {
activationType,
activationTime,
}, abilityModifierStatId: statId, attackTypeRange: rangeId, dice,
value, limitedUse: null, displayAsAttack: null, componentId: -1, componentTypeId: -1, fixedToHit: null, numberOfTargets: null, ammunition: null });
const dataOriginBaseAction = generateDataOriginBaseAction(actionLike, valueLookup, DataOriginTypeEnum.CUSTOM, null, null);
const generatedAction = generateAction(dataOriginBaseAction, proficiencyBonus, abilityLookup, modifiers, valueLookup, martialArtsLevelScale, ruleData, modifierData);
const generatedDisplayAsAttack = getDisplayAsAttack(generatedAction);
return Object.assign(Object.assign({}, generatedAction), { displayAsAttack: displayAsAttack === null ? (generatedDisplayAsAttack ? generatedDisplayAsAttack : false) : displayAsAttack, isSilvered, isOffhand: isOffhand === null ? false : isOffhand });
}
/**
*
* @param ruleData
* @param valueLookup
*/
export function generateInnateBaseActions(ruleData, valueLookup) {
return RuleDataAccessors.getNaturalActions(ruleData).map((action) => generateInnateNaturalDataOriginBaseAction(action, valueLookup));
}
@@ -0,0 +1,11 @@
import * as ActionAccessors from './accessors';
import * as ActionConstants from './constants';
import * as ActionDerivers from './derivers';
import * as ActionGenerators from './generators';
import * as ActionNotes from './notes';
import * as ActionTypings from './typings';
import * as ActionValidators from './validators';
export * from './typings';
export * from './constants';
export { ActionAccessors, ActionDerivers, ActionValidators, ActionGenerators, ActionNotes };
export default Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, ActionAccessors), ActionConstants), ActionDerivers), ActionValidators), ActionGenerators), ActionNotes), ActionTypings);
@@ -0,0 +1,56 @@
import { TypeScriptUtils } from '../../utils';
import { LimitedUseAccessors, LimitedUseDerivers, LimitedUseRenderers } from '../LimitedUse';
import { NoteGenerators } from '../Note';
import { RuleDataUtils } from '../RuleData';
import { getLimitedUse, getNotes } from './accessors';
/**
*
* @param action
*/
function getUserNoteComponent(action) {
const notes = getNotes(action);
if (notes) {
return NoteGenerators.createPlainText(notes);
}
return null;
}
/**
*
* @param action
* @param ruleData
* @param abilityLookup
* @param proficiencyBonus
*/
function getLimitedUseNoteComponent(action, ruleData, abilityLookup, proficiencyBonus) {
const limitedUse = getLimitedUse(action);
if (!limitedUse) {
return null;
}
const numberConsumed = LimitedUseAccessors.getMinNumberConsumed(limitedUse);
const maxUses = LimitedUseDerivers.deriveMaxUses(limitedUse, abilityLookup, ruleData, proficiencyBonus);
const numberUsed = LimitedUseAccessors.getNumberUsed(limitedUse);
const numberRemaining = maxUses - numberUsed;
if (maxUses === 1) {
const resetType = LimitedUseAccessors.getResetType(limitedUse);
const resetTypeAbbr = LimitedUseRenderers.renderLimitedUseResetAbbreviation(resetType);
const isUsed = numberUsed === 1;
const limitedUseResetTypeName = resetType === null ? '' : RuleDataUtils.getLimitedUseResetTypeName(resetType, ruleData);
return NoteGenerators.createTooltip(`1/${resetTypeAbbr}${isUsed ? ' (Used)' : ''}`, `Once per ${limitedUseResetTypeName}${isUsed ? ' (Used)' : ''}`, {
dynamicTitle: true,
});
}
return NoteGenerators.createPlainText(`${numberConsumed} Use${numberConsumed !== 1 ? 's' : ''} (${numberRemaining}/${maxUses})`);
}
/**
*
* @param action
* @param ruleData
* @param abilityLookup
* @param proficiencyBonus
*/
export function getNoteComponents(action, ruleData, abilityLookup, proficiencyBonus) {
const notes = [];
notes.push(getLimitedUseNoteComponent(action, ruleData, abilityLookup, proficiencyBonus));
notes.push(getUserNoteComponent(action));
return notes.filter(TypeScriptUtils.isNotNullOrUndefined);
}
@@ -0,0 +1,14 @@
import { ActivationAccessors } from '../Activation';
import { getActivation } from './accessors';
/**
*
* @param action
* @param activationType
*/
export function validateIsActivationType(action, activationType) {
const activation = getActivation(action);
if (activation === null) {
return false;
}
return activationType === ActivationAccessors.getType(activation);
}