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,42 @@
import { ActionAccessors } from '../../Action';
import { ActivationAccessors } from '../../Activation';
import { ActivatableTypeEnum } from '../../Core';
import { OptionAccessors } from '../../Option';
/**
*
* @param options
* @param parentEntity
*/
export function deriveActivatableOptions(options, parentEntity) {
const activatables = [];
options.forEach((option) => {
const actions = OptionAccessors.getActions(option);
if (actions.length) {
activatables.push(...deriveActivatableActions(actions, parentEntity));
}
});
return activatables;
}
/**
*
* @param actions
* @param parentEntity
*/
export function deriveActivatableActions(actions, parentEntity) {
const activatables = [];
actions.forEach((action) => {
const activation = ActionAccessors.getActivation(action);
if (activation !== null && ActivationAccessors.getType(activation) !== null) {
activatables.push({
type: ActivatableTypeEnum.ACTION,
sortText: ActionAccessors.getName(action),
activation,
key: ActionAccessors.getUniqueKey(action),
limitedUse: ActionAccessors.getLimitedUse(action),
entity: action,
parentEntity,
});
}
});
return activatables;
}
@@ -0,0 +1,13 @@
/**
*
* @param armorClassSources
* @param initialValue
*/
export function deriveArmorClassSupplierTotal(armorClassSources, initialValue = 0) {
return armorClassSources.reduce((acc, armorClassSource) => {
if (armorClassSource.amount) {
acc += armorClassSource.amount;
}
return acc;
}, initialValue);
}
@@ -0,0 +1,45 @@
import { AbilityAccessors } from '../../Ability';
import { ModifierDerivers, ModifierValidators } from '../../Modifier';
/**
*
* @param proficiencyBonus
* @param abilityModifier
*/
export function deriveAttackSaveValue(proficiencyBonus, abilityModifier) {
return 8 + proficiencyBonus + abilityModifier;
}
/**
*
* @param proficiencyBonus
* @param abilityModifier
*/
export function deriveAttackModifier(proficiencyBonus, abilityModifier) {
return proficiencyBonus + abilityModifier;
}
/**
*
* @param availableAbilities
* @param modifiers
* @param proficiencyBonus
* @param abilityLookup
*/
export function deriveAttackAbilityPossibilities(availableAbilities, modifiers, proficiencyBonus, abilityLookup) {
return availableAbilities.map((abilityId) => {
const ability = abilityLookup[abilityId];
// get bonus stat attack modifiers
const bonusStatToHitModifiers = modifiers.filter((modifier) => ModifierValidators.isValidBonusStatAttackModifier(modifier, abilityId));
const bonusStatToHitModifierTotal = ModifierDerivers.sumModifiers(bonusStatToHitModifiers, abilityLookup);
// get damage stat attack modifiers
const damageStatAttackModifiers = modifiers.filter((modifier) => ModifierValidators.isValidDamageStatAttackModifier(modifier, abilityId));
const damageStatAttackModifierTotal = ModifierDerivers.sumModifiers(damageStatAttackModifiers, abilityLookup);
const abilityModifier = ability ? AbilityAccessors.getModifier(ability) : null;
const modifier = abilityModifier ? abilityModifier : 0;
const toHit = modifier + proficiencyBonus + bonusStatToHitModifierTotal;
return {
abilityId,
toHit,
modifier,
damageBonus: damageStatAttackModifierTotal + modifier,
};
});
}
@@ -0,0 +1,20 @@
import { DiceAdjustmentTypeEnum } from '../../Dice';
import { ModifierDerivers, ModifierValidators } from '../../Modifier';
/**
*
* @param modifiers
*/
export function deriveAdvantageDeathSavesAdjustments(modifiers) {
return modifiers
.filter((modifier) => ModifierValidators.isAdvantageDeathSavesModifier(modifier))
.map((modifier) => ModifierDerivers.deriveDiceAdjustment(modifier, DiceAdjustmentTypeEnum.ADVANTAGE));
}
/**
*
* @param modifiers
*/
export function deriveDisadvantageDeathSavesAdjustments(modifiers) {
return modifiers
.filter((modifier) => ModifierValidators.isDisadvantageDeathSavesModifier(modifier))
.map((modifier) => ModifierDerivers.deriveDiceAdjustment(modifier, DiceAdjustmentTypeEnum.DISADVANTAGE));
}
@@ -0,0 +1,15 @@
import { DataOriginGenerators, DataOriginTypeEnum } from '../../DataOrigin';
/**
*
* @param adjustment
*/
export function deriveCustomDefenseAdjustmentDataOrigin(adjustment) {
return DataOriginGenerators.generateDataOrigin(DataOriginTypeEnum.CUSTOM, adjustment.source ? adjustment.source : 'Custom');
}
/**
*
* @param adjustment
*/
export function deriveCustomConditionDefenseAdjustmentDataOrigin(adjustment) {
return DataOriginGenerators.generateDataOrigin(DataOriginTypeEnum.CUSTOM, adjustment.source ? adjustment.source : 'Custom');
}
@@ -0,0 +1,43 @@
import { ItemAccessors, ItemValidators } from '../../Item';
import { LimitedUseDerivers } from '../../LimitedUse';
import { ModifierAccessors } from '../../Modifier';
import { ProtectionAvailabilityStatusEnum } from '../constants';
/**
*
* @param limitedUse
* @param abilityLookup
* @param ruleData
* @param proficiencyBonus
*/
export function deriveProtectionSupplierAvailabilityStatus(limitedUse, abilityLookup, ruleData, proficiencyBonus) {
let availabilityStatus = ProtectionAvailabilityStatusEnum.AVAILABLE;
if (!LimitedUseDerivers.deriveHasUsesAvailable(limitedUse, abilityLookup, ruleData, proficiencyBonus)) {
availabilityStatus = ProtectionAvailabilityStatusEnum.NO_LIMITED_USE_REMAINING;
}
return availabilityStatus;
}
/**
*
* @param item
* @param modifier
* @param limitedUse
* @param abilityLookup
* @param ruleData
* @param proficiencyBonus
* @param characterId
*/
export function deriveItemProtectionSupplierAvailabilityStatus(item, modifier, limitedUse, abilityLookup, ruleData, proficiencyBonus, characterId) {
if (ItemAccessors.canEquip(item)) {
const isEquippedToCurrentCharacter = ItemValidators.isEquippedToCurrentCharacter(item, characterId);
if (!isEquippedToCurrentCharacter) {
return ProtectionAvailabilityStatusEnum.ITEM_NOT_EQUIPPED;
}
if (ModifierAccessors.requiresAttunement(modifier) && !ItemAccessors.isAttuned(item)) {
return ProtectionAvailabilityStatusEnum.ITEM_NOT_ATTUNED;
}
}
if (!LimitedUseDerivers.deriveHasUsesAvailable(limitedUse, abilityLookup, ruleData, proficiencyBonus)) {
return ProtectionAvailabilityStatusEnum.NO_LIMITED_USE_REMAINING;
}
return ProtectionAvailabilityStatusEnum.AVAILABLE;
}
@@ -0,0 +1,43 @@
import { ProficiencyLevelEnum, ProficiencyRoundingEnum } from '../../Core';
import { ModifierDerivers, ModifierValidators } from '../../Modifier';
import { RuleDataUtils } from '../../RuleData';
/**
*
* @param level
* @param modifiers
* @param ruleData
*/
export function deriveProficiencyBonus(level, modifiers, ruleData) {
const levelBonus = RuleDataUtils.getLevelProficiencyBonus(level, ruleData);
const bonusProficiencyBonusModifiers = modifiers.filter((modifier) => ModifierValidators.isBonusProficiencyBonusModifier(modifier));
const modifierBonusTotal = ModifierDerivers.sumModifiers(bonusProficiencyBonusModifiers);
return levelBonus + modifierBonusTotal;
}
/**
*
* @param proficiencyLevel
* @param proficiencyBonus
* @param proficiencyRounding
*/
export function deriveProficiencyBonusAmount(proficiencyLevel, proficiencyBonus, proficiencyRounding = ProficiencyRoundingEnum.DOWN) {
let proficiencyBonusAmount = 0;
switch (proficiencyLevel) {
case ProficiencyLevelEnum.EXPERT:
proficiencyBonusAmount = proficiencyBonus * 2;
break;
case ProficiencyLevelEnum.FULL:
proficiencyBonusAmount = proficiencyBonus;
break;
case ProficiencyLevelEnum.HALF:
if (proficiencyRounding === ProficiencyRoundingEnum.UP) {
proficiencyBonusAmount = Math.ceil(proficiencyBonus / 2);
}
else {
proficiencyBonusAmount = Math.floor(proficiencyBonus / 2);
}
break;
default:
// not implemented
}
return proficiencyBonusAmount;
}
@@ -0,0 +1,48 @@
import { RuleDataAccessors } from '../../RuleData';
/**
*
* @param xp
* @param ruleData
*/
export function deriveXpLevel(xp, ruleData) {
let level = 0;
if (xp === 0) {
return 1;
}
if (xp >= deriveMaxXp(ruleData)) {
return RuleDataAccessors.getMaxCharacterLevel(ruleData);
}
const levelExperiencePoints = RuleDataAccessors.getLevelExperiencePoints(ruleData);
levelExperiencePoints.forEach((levelXpAmount, levelIdx) => {
if (level === 0 && xp < levelXpAmount) {
level = levelIdx;
}
});
return level;
}
/**
*
* @param level
* @param ruleData
*/
export function deriveCurrentLevelXp(level, ruleData) {
const levelExperiencePoints = RuleDataAccessors.getLevelExperiencePoints(ruleData);
return levelExperiencePoints[Math.max(0, level - 1)];
}
/**
*
* @param level
* @param ruleData
*/
export function deriveNextLevelXp(level, ruleData) {
const levelExperiencePoints = RuleDataAccessors.getLevelExperiencePoints(ruleData);
return levelExperiencePoints[Math.min(levelExperiencePoints.length - 1, level)];
}
/**
*
* @param ruleData
*/
export function deriveMaxXp(ruleData) {
const levelExperiencePoints = RuleDataAccessors.getLevelExperiencePoints(ruleData);
return levelExperiencePoints[levelExperiencePoints.length - 1];
}
@@ -0,0 +1,22 @@
import { SaveTypeEnum } from '../../Core';
/**
*
* @param type
*/
export function deriveSaveTypeName(type) {
let name = '';
switch (type) {
case SaveTypeEnum.ADVANTAGE:
name = 'Advantage';
break;
case SaveTypeEnum.DISADVANTAGE:
name = 'Disadvantage';
break;
case SaveTypeEnum.BONUS:
name = 'Bonus';
break;
default:
//not implemented
}
return name;
}
@@ -0,0 +1,59 @@
import { AbilitySkillEnum } from '../../Core';
import { ModifierDerivers, ModifierValidators } from '../../Modifier';
import { SkillAccessors } from '../../Skill';
/**
*
* @param skillModifier
* @param bonuses
*/
export function derivePassiveSkill(skillModifier, bonuses = 0) {
return 10 + skillModifier + bonuses;
}
/**
*
* @param skills
* @param modifiers
* @param abilityLookup
*/
export function derivePassivePerception(skills, modifiers, abilityLookup) {
const skill = skills.find((skill) => SkillAccessors.getId(skill) === AbilitySkillEnum.PERCEPTION);
const skillModifier = skill ? SkillAccessors.getModifier(skill) : null;
if (!skill || skillModifier === null) {
return 0;
}
const bonusModifiers = modifiers.filter((modifier) => ModifierValidators.isBonusPassivePerceptionModifier(modifier));
const bonusModifierTotal = ModifierDerivers.sumModifiers(bonusModifiers, abilityLookup);
return derivePassiveSkill(skillModifier, bonusModifierTotal);
}
/**
*
* @param skills
* @param modifiers
* @param abilityLookup
*/
export function derivePassiveInvestigation(skills, modifiers, abilityLookup) {
const skill = skills.find((skill) => SkillAccessors.getId(skill) === AbilitySkillEnum.INVESTIGATION);
const skillModifier = skill ? SkillAccessors.getModifier(skill) : null;
if (!skill || skillModifier === null) {
return 0;
}
const bonusModifiers = modifiers.filter((modifier) => ModifierValidators.isBonusPassiveInvestigationModifier(modifier));
const bonusModifierTotal = ModifierDerivers.sumModifiers(bonusModifiers, abilityLookup);
return derivePassiveSkill(skillModifier, bonusModifierTotal);
}
/**
*
* @param skills
* @param modifiers
* @param abilityLookup
*/
export function derivePassiveInsight(skills, modifiers, abilityLookup) {
const skill = skills.find((skill) => SkillAccessors.getId(skill) === AbilitySkillEnum.INSIGHT);
const skillModifier = skill ? SkillAccessors.getModifier(skill) : null;
if (!skill || skillModifier === null) {
return 0;
}
const bonusModifiers = modifiers.filter((modifier) => ModifierValidators.isBonusPassiveInsightModifier(modifier));
const bonusModifierTotal = ModifierDerivers.sumModifiers(bonusModifiers, abilityLookup);
return derivePassiveSkill(skillModifier, bonusModifierTotal);
}
@@ -0,0 +1,28 @@
import { PreferenceEncumbranceTypeEnum, WeightSpeedTypeEnum } from '../../Core';
import { getCarryCapacity, getEncumberedWeight, getHeavilyEncumberedWeight } from '../utils';
/**
*
* @param currentWeight
* @param strScore
* @param size
* @param preferences
* @param modifiers
*/
export function deriveCurrentWeightSpeedType(currentWeight, strScore, size, preferences, modifiers) {
if (preferences !== null) {
if (preferences.encumbranceType === PreferenceEncumbranceTypeEnum.VARIANT) {
if (currentWeight > getHeavilyEncumberedWeight(strScore, size, modifiers)) {
return WeightSpeedTypeEnum.HEAVILY_ENCUMBERED;
}
else if (currentWeight > getEncumberedWeight(strScore, size, modifiers)) {
return WeightSpeedTypeEnum.ENCUMBERED;
}
}
else if (preferences.encumbranceType === PreferenceEncumbranceTypeEnum.ENCUMBRANCE) {
if (currentWeight > getCarryCapacity(strScore, size, modifiers)) {
return WeightSpeedTypeEnum.OVER_CARRYING_CAPACITY;
}
}
}
return WeightSpeedTypeEnum.NORMAL;
}