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,849 @@
import { StatBlockTypeEnum } from './constants';
/**
*
* @param creature
*/
export function getUniqueKey(creature) {
return `${getMappingId(creature)}-${getMappingEntityTypeId(creature)}`;
}
/**
*
* @param creature
*/
export function getMappingId(creature) {
return creature.id;
}
/**
*
* @param creature
*/
export function getMappingEntityTypeId(creature) {
return creature.entityTypeId;
}
/**
*
* @param creature
*/
export function isActive(creature) {
return creature.isActive;
}
/**
*
* @param creature
*/
export function getRemoveHitPoints(creature) {
return creature.removedHitPoints;
}
/**
*
* @param creature
*/
export function getTemporaryHitPoints(creature) {
var _a;
return (_a = creature.temporaryHitPoints) !== null && _a !== void 0 ? _a : 0;
}
/**
*
* @param creature
*/
export function getGroupId(creature) {
return creature.groupId;
}
/**
*
* @param creature
*/
export function getId(creature) {
return getDefinitionId(creature);
}
/**
*
* @param creature
*/
export function getDefinitionId(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : -1;
}
/**
*
* @param creature
*/
export function getEntityTypeId(creature) {
return getDefinitionEntityTypeId(creature);
}
/**
*
* @param creature
*/
export function getDefinitionEntityTypeId(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.entityTypeId) !== null && _b !== void 0 ? _b : -1;
}
/**
*
* @param creature
*/
export function getName(creature) {
var _a;
return (_a = creature.name) !== null && _a !== void 0 ? _a : getDefinitionName(creature);
}
/**
*
* @param creature
*/
export function getDefinitionAlignmentId(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.alignmentId) !== null && _b !== void 0 ? _b : -1;
}
/**
*
* @param creature
*/
export function getAlignmentId(creature) {
return creature.alignmentId;
}
/**
*
* @param creature
*/
export function getDefinitionSizeId(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.sizeId) !== null && _b !== void 0 ? _b : -1;
}
/**
*
* @param creature
*/
export function getSizeId(creature) {
return creature.sizeId;
}
/**
*
* @param creature
*/
export function getSizeInfo(creature) {
return creature.sizeInfo;
}
export function getDefinitionTypeId(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.typeId) !== null && _b !== void 0 ? _b : -1;
}
/**
*
* @param creature
*/
export function getTypeId(creature) {
return creature.typeId;
}
/**
*
* @param creature
*/
export function getDefinitionArmorClass(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.armorClass) !== null && _b !== void 0 ? _b : 0;
}
/**
*
* @param creature
*/
export function getDefinitionName(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : '';
}
export function getArmorClassDescription(creature) {
return getDefinitionArmorClassDescription(creature);
}
/**
*
* @param creature
*/
export function getDefinitionArmorClassDescription(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.armorClassDescription) !== null && _b !== void 0 ? _b : null;
}
export function getAverageHitPoints(creature) {
return getDefinitionAverageHitPoints(creature);
}
/**
*
* @param creature
*/
export function getDefinitionAverageHitPoints(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.averageHitPoints) !== null && _b !== void 0 ? _b : 0;
}
/**
*
* @param creature
*/
export function getDefinitionStats(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.stats) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getStats(creature) {
return creature.stats;
}
/**
*
* @param creature
*/
export function getChallengeInfo(creature) {
return creature.challengeInfo;
}
export function getLairChallengeInfo(creature) {
return creature.lairChallengeInfo;
}
/**
*
* @param creature
* @param fallback
*/
export function getChallengeProficiencyBonus(creature, fallback = 0) {
var _a;
const challengeInfo = getChallengeInfo(creature);
return (_a = challengeInfo === null || challengeInfo === void 0 ? void 0 : challengeInfo.proficiencyBonus) !== null && _a !== void 0 ? _a : fallback;
}
/**
*
* @param creature
*/
export function getHitPointDice(creature) {
return getDefinitionHitPointDice(creature);
}
/**
*
* @param creature
*/
export function getDefinitionHitPointDice(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.hitPointDice) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getMovements(creature) {
return getDefinitionMovements(creature);
}
/**
*
* @param creature
*/
export function getDefinitionMovements(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.movements) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getMovementIds(creature) {
return creature.movementIds;
}
export function getMovementNames(creature) {
return creature.movementNames;
}
/**
*
* @param creature
*/
export function getDefinitionDamageAdjustments(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.damageAdjustments) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getDamageAdjustments(creature) {
return creature.damageAdjustments;
}
/**
*
* @param creature
*/
export function getDamageVulnerabilities(creature) {
return creature.damageVulnerabilities;
}
/**
*
* @param creature
*/
export function getDamageImmunities(creature) {
return creature.damageImmunities;
}
/**
*
* @param creature
*/
export function getDamageResistances(creature) {
return creature.damageResistances;
}
/**
*
* @param creature
*/
export function getDefinitionConditionImmunities(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.conditionImmunities) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getConditionImmunities(creature) {
return creature.conditionImmunities;
}
/**
*
* @param creature
*/
export function getDefinitionSubTypes(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.subTypes) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getSubTypes(creature) {
return creature.subTypes;
}
/**
*
* @param creature
*/
export function getEnvironments(creature) {
return getDefinitionEnvironments(creature);
}
/**
*
* @param creature
*/
export function getDefinitionEnvironments(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.environments) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getTags(creature) {
return getDefinitionTags(creature);
}
/**
*
* @param creature
*/
export function getDefinitionTags(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.tags) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getSwarmInfo(creature) {
return getDefinitionSwarmInfo(creature);
}
/**
*
* @param creature
*/
export function getDefinitionSwarmInfo(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.swarm) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getDefinitionSkills(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.skills) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getSkills(creature) {
return creature.skills;
}
/**
*
* @param creature
*/
export function getDefinitionSavingThrows(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.savingThrows) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getSavingThrows(creature) {
return creature.savingThrows;
}
/**
*
* @param creature
*/
export function getSenses(creature) {
return getDefinitionSenses(creature);
}
/**
*
* @param creature
*/
export function getDefinitionSenses(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.senses) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getDefinitionPassivePerception(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.passivePerception) !== null && _b !== void 0 ? _b : 0;
}
/**
*
* @param creature
*/
export function getPassivePerception(creature) {
return creature.passivePerception;
}
/**
*
* @param creature
*/
export function getLanguageDescription(creature) {
return getDefinitionLanguageDescription(creature);
}
/**
*
* @param creature
*/
export function getDefinitionLanguageDescription(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.languageDescription) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getLanguageNote(creature) {
return getDefinitionLanguageNote(creature);
}
/**
*
* @param creature
*/
export function getDefinitionLanguageNote(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.languageNote) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getLanguages(creature) {
return getDefinitionLanguages(creature);
}
/**
*
* @param creature
*/
export function getDefinitionLanguages(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.languages) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function isHomebrew(creature) {
return getDefinitionIsHomebrew(creature);
}
/**
*
* @param creature
*/
export function getDefinitionIsHomebrew(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.isHomebrew) !== null && _b !== void 0 ? _b : false;
}
/**
*
* @param creature
*/
export function getVersion(creature) {
return getDefinitionVersion(creature);
}
/**
*
* @param creature
*/
export function getDefinitionVersion(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.version) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getChallengeRatingId(creature) {
return getDefinitionChallengeRatingId(creature);
}
/**
*
* @param creature
*/
export function getDefinitionChallengeRatingId(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.challengeRatingId) !== null && _b !== void 0 ? _b : -1;
}
export function getLairChallengeRatingId(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.lairChallengeRatingId) !== null && _b !== void 0 ? _b : -1;
}
export function getInitiative(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.initiative) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function isSwarm(creature) {
return getSwarmInfo(creature) !== null;
}
/**
*
* @param creature
*/
export function isLegendary(creature) {
return getDefinitionIsLegendary(creature);
}
/**
*
* @param creature
*/
export function getDefinitionIsLegendary(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.isLegendary) !== null && _b !== void 0 ? _b : false;
}
/**
*
* @param creature
*/
export function hasLair(creature) {
return getDefinitionHasLair(creature);
}
/**
*
* @param creature
*/
export function getDefinitionHasLair(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.hasLair) !== null && _b !== void 0 ? _b : false;
}
/**
*
* @param creature
*/
export function getAvatarUrl(creature) {
return getDefinitionAvatarUrl(creature);
}
/**
*
* @param creature
*/
export function getDefinitionAvatarUrl(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.avatarUrl) !== null && _b !== void 0 ? _b : '';
}
/**
*
* @param creature
*/
export function getLargeAvatarUrl(creature) {
return getDefinitionLargeAvatarUrl(creature);
}
/**
*
* @param creature
*/
export function getDefinitionLargeAvatarUrl(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.largeAvatarUrl) !== null && _b !== void 0 ? _b : '';
}
/**
*
* @param creature
*/
export function getBasicAvatarUrl(creature) {
return getDefinitionBasicAvatarUrl(creature);
}
/**
*
* @param creature
*/
export function getDefinitionBasicAvatarUrl(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.basicAvatarUrl) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getSpecialTraitsDescription(creature) {
return getDefinitionSpecialTraitsDescription(creature);
}
/**
*
* @param creature
*/
export function getDefinitionSpecialTraitsDescription(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.specialTraitsDescription) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getActionsDescription(creature) {
return getDefinitionActionsDescription(creature);
}
/**
*
* @param creature
*/
export function getDefinitionActionsDescription(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.actionsDescription) !== null && _b !== void 0 ? _b : null;
}
export function getBonusActionsDescription(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.bonusActionsDescription) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getReactionsDescription(creature) {
return getDefinitionReactionsDescription(creature);
}
/**
*
* @param creature
*/
export function getDefinitionReactionsDescription(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.reactionsDescription) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getLegendaryActionsDescription(creature) {
return getDefinitionLegendaryActionsDescription(creature);
}
/**
*
* @param creature
*/
export function getDefinitionLegendaryActionsDescription(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.legendaryActionsDescription) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getCharacteristicsDescription(creature) {
return getDefinitionCharacteristicsDescription(creature);
}
/**
*
* @param creature
*/
export function getDefinitionCharacteristicsDescription(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.characteristicsDescription) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getLairDescription(creature) {
return getDefinitionLairDescription(creature);
}
/**
*
* @param creature
*/
export function getDefinitionLairDescription(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.lairDescription) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getArmorClass(creature) {
return creature.armorClass;
}
/**
*
* @param creature
*/
export function getGroupInfo(creature) {
return creature.groupInfo;
}
/**
*
* @param creature
*/
export function getEnvironmentTags(creature) {
return creature.environmentTags;
}
/**
*
* @param creature
*/
export function getSubTypeTags(creature) {
return creature.subTypeTags;
}
/**
*
* @param creature
*/
export function getTypeTag(creature) {
return creature.typeTag;
}
/**
*
* @param creature
*/
export function getHitPointInfo(creature) {
return creature.hitPointInfo;
}
/**
*
* @param creature
*/
export function getNotes(creature) {
return creature.notes;
}
/**
*
* @param creature
*/
export function getGroupActionSnippet(creature) {
var _a;
const groupInfo = getGroupInfo(creature);
return (_a = groupInfo === null || groupInfo === void 0 ? void 0 : groupInfo.actionSnippet) !== null && _a !== void 0 ? _a : null;
}
/**
*
* @param creature
*/
export function getLevel(creature) {
return creature.level;
}
/**
*
* @param creature
*/
export function getInfusion(creature) {
return creature.infusion;
}
/**
*
* @param creature
*/
export function getFlags(creature) {
return creature.flags;
}
/**
*
* @param creature
*/
export function getDefinitionSources(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.sources) !== null && _b !== void 0 ? _b : [];
}
/**
*
* @param creature
*/
export function getSources(creature) {
return getDefinitionSources(creature);
}
/**
*
* @param creature
*/
export function isCustomized(creature) {
return creature.isCustomized;
}
/**
*
* @param creature
*/
export function getDefinitionHideCr(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.hideCr) !== null && _b !== void 0 ? _b : false;
}
/**
*
* @param creature
*/
export function getHideCr(creature) {
return getDefinitionHideCr(creature);
}
/**
*
* @param creature
*/
export function getGear(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.gear) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getSlug(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.slug) !== null && _b !== void 0 ? _b : null;
}
/**
*
* @param creature
*/
export function getStatBlockType(creature) {
var _a, _b;
return (_b = (_a = creature.definition) === null || _a === void 0 ? void 0 : _a.statBlockType) !== null && _b !== void 0 ? _b : StatBlockTypeEnum.CORE_RULES_2014;
}
/**
*
* @param creature
*/
export function getInitialTempHp(creature) {
return creature.initialTempHp;
}
/**
*
* @param creature
*/
export function getUseOwnerHp(creature) {
return creature.useOwnerHp;
}
@@ -0,0 +1,41 @@
import { AdjustmentTypeEnum } from '../Value';
export var CreatureGroupFlagEnum;
(function (CreatureGroupFlagEnum) {
CreatureGroupFlagEnum["ARMOR_ADD_PROFICIENCY_BONUS"] = "ACPB";
CreatureGroupFlagEnum["ATTACK_ROLLS_ADD_PROFICIENCY_BONUS"] = "ARPB";
CreatureGroupFlagEnum["DAMAGE_ROLLS_ADD_PROFICIENCY_BONUS"] = "DRPB";
CreatureGroupFlagEnum["PROFICIENT_SKILLS_ADD_PROFICIENCY_BONUS"] = "PSPB";
CreatureGroupFlagEnum["PROFICIENT_SAVING_THROWS_ADD_PROFICIENCY_BONUS"] = "STPB";
CreatureGroupFlagEnum["MAX_HIT_POINTS_LEVEL_MULTIPLIER_OPTION"] = "HPLM";
CreatureGroupFlagEnum["EVALUATE_OWNER_SKILL_PROFICIENCIES"] = "EOSKP";
CreatureGroupFlagEnum["EVALUATE_OWNER_SAVE_PROFICIENCIES"] = "EOSVP";
CreatureGroupFlagEnum["EVALUATE_OWNER_PASSIVE_PERCEPTION"] = "EOPP";
CreatureGroupFlagEnum["EVALUATE_UPDATED_PASSIVE_PERCEPTION"] = "EUPP";
CreatureGroupFlagEnum["CANNOT_BE_SWARM"] = "CBS";
CreatureGroupFlagEnum["CANNOT_USE_LEGENDARY_ACTIONS"] = "CULGA";
CreatureGroupFlagEnum["CANNOT_USE_LAIR_ACTIONS"] = "CULRA";
CreatureGroupFlagEnum["ARTIFICER_HP_MULTIPLIER"] = "AHM";
CreatureGroupFlagEnum["MAX_HIT_POINTS_ADD_INT_MODIFIER"] = "MHPAIM";
CreatureGroupFlagEnum["MAX_HIT_POINTS_ADD_MONSTER_CON_MODIFIER"] = "MHPAMCM";
CreatureGroupFlagEnum["USE_CHALLENGE_RATING_AS_LEVEL"] = "UCRAL";
CreatureGroupFlagEnum["MAX_HIT_POINTS_BASE_ARTIFICER_LEVEL"] = "MHPBAL";
CreatureGroupFlagEnum["USE_OWNER_MAX_HIT_POINTS"] = "UOMHP";
CreatureGroupFlagEnum["TEMP_HIT_POINTS_BASE_DRUID_LEVEL"] = "THPBDL";
CreatureGroupFlagEnum["TEMP_HIT_POINTS_BASE_DRUID_LEVEL_MULTIPLIER"] = "THPBDLM";
CreatureGroupFlagEnum["ARMOR_ADD_OWNER_WIS_PLUS_FIXED_VALUE"] = "AAOWPFV";
})(CreatureGroupFlagEnum || (CreatureGroupFlagEnum = {}));
export const CREATURE_CUSTOMIZATION_ADJUSTMENT_TYPES = [
AdjustmentTypeEnum.CREATURE_SIZE,
AdjustmentTypeEnum.CREATURE_TYPE_OVERRIDE,
AdjustmentTypeEnum.CREATURE_ALIGNMENT,
AdjustmentTypeEnum.CREATURE_AC,
AdjustmentTypeEnum.CREATURE_HIT_POINTS,
AdjustmentTypeEnum.CREATURE_NOTES,
];
export const DB_STRING_GROUP_SIDEKICK = 'Sidekick';
export const DB_STRING_TAG_SIDEKICK = 'Sidekick';
export var StatBlockTypeEnum;
(function (StatBlockTypeEnum) {
StatBlockTypeEnum[StatBlockTypeEnum["CORE_RULES_2014"] = 0] = "CORE_RULES_2014";
StatBlockTypeEnum[StatBlockTypeEnum["CORE_RULES_2024"] = 1] = "CORE_RULES_2024";
})(StatBlockTypeEnum || (StatBlockTypeEnum = {}));
@@ -0,0 +1,653 @@
import { TypeScriptUtils } from '../../utils';
import { AbilityAccessors, AbilityUtils } from '../Ability';
import { CharacterDerivers } from '../Character';
import { AbilitySkillEnum, AbilityStatEnum, ProficiencyLevelEnum, } from '../Core';
import { HelperUtils } from '../Helper';
import { InfusionAccessors } from '../Infusion';
import { RuleDataAccessors, RuleDataUtils } from '../RuleData';
import { SkillAccessors } from '../Skill';
import { AdjustmentTypeEnum, ValueHacks, ValueUtils, ValueValidators } from '../Value';
import { getAverageHitPoints, getChallengeProficiencyBonus, getChallengeRatingId, getDamageAdjustments, getDefinitionAlignmentId, getDefinitionArmorClass, getDefinitionConditionImmunities, getDefinitionDamageAdjustments, getDefinitionPassivePerception, getDefinitionSavingThrows, getDefinitionSizeId, getDefinitionSkills, getDefinitionStats, getDefinitionSubTypes, getDefinitionTypeId, getEnvironments, getId, getLairChallengeRatingId, getMappingEntityTypeId, getMappingId, getMovements, getRemoveHitPoints, getTemporaryHitPoints, getTypeId, } from './accessors';
import { CREATURE_CUSTOMIZATION_ADJUSTMENT_TYPES, CreatureGroupFlagEnum } from './constants';
import { getStatInfo, hasGroupFlag, shouldReplaceWithOwnerStat } from './utils';
/**
*
* @param creature
*/
export function derivePreOwnerHitPointInfo(creature) {
const finalTotalHp = Math.max(getAverageHitPoints(creature), 0);
const finalBaseHp = finalTotalHp;
const finalRemovedHp = Math.min(finalTotalHp, getRemoveHitPoints(creature));
return {
baseHp: finalBaseHp,
tempHp: 0,
removedHp: finalRemovedHp,
bonusHp: 0,
overrideHp: 0,
totalHp: finalTotalHp,
remainingHp: finalTotalHp - finalRemovedHp,
};
}
/**
*
* @param creature
* @param ownerData
* @param valueLookup
* @param ruleData
*/
export function deriveHitPointInfo(creature, ownerData, valueLookup, ruleData) {
const flagLevelMultiplierHpPossibilities = [];
if (hasGroupFlag(creature, CreatureGroupFlagEnum.MAX_HIT_POINTS_LEVEL_MULTIPLIER_OPTION)) {
const flagInfo = RuleDataUtils.getCreatureGroupFlagInfo(CreatureGroupFlagEnum.MAX_HIT_POINTS_LEVEL_MULTIPLIER_OPTION, ruleData);
if (flagInfo) {
const contextClassLevel = flagInfo.valueContextId === null ? 0 : ownerData.classLevelLookup[flagInfo.valueContextId];
const contextValue = flagInfo.value === null ? 1 : flagInfo.value;
flagLevelMultiplierHpPossibilities.push((contextClassLevel ? contextClassLevel : 0) * contextValue);
}
}
if (hasGroupFlag(creature, CreatureGroupFlagEnum.ARTIFICER_HP_MULTIPLIER)) {
const flagInfo = RuleDataUtils.getCreatureGroupFlagInfo(CreatureGroupFlagEnum.ARTIFICER_HP_MULTIPLIER, ruleData);
if (flagInfo) {
const contextClassLevel = flagInfo.valueContextId === null ? 0 : ownerData.classLevelLookup[flagInfo.valueContextId];
const contextValue = flagInfo.value === null ? 1 : flagInfo.value;
flagLevelMultiplierHpPossibilities.push((contextClassLevel ? contextClassLevel : 0) * contextValue);
}
}
const definitionTotalHp = getAverageHitPoints(creature);
let finalTotalHp = Math.max(definitionTotalHp, ...flagLevelMultiplierHpPossibilities);
if (hasGroupFlag(creature, CreatureGroupFlagEnum.MAX_HIT_POINTS_BASE_ARTIFICER_LEVEL)) {
const flagInfo = RuleDataUtils.getCreatureGroupFlagInfo(CreatureGroupFlagEnum.MAX_HIT_POINTS_BASE_ARTIFICER_LEVEL, ruleData);
if (flagInfo && flagInfo.valueContextId !== null) {
finalTotalHp = HelperUtils.lookupDataOrFallback(ownerData.classLevelLookup, flagInfo.valueContextId, finalTotalHp);
}
}
if (hasGroupFlag(creature, CreatureGroupFlagEnum.MAX_HIT_POINTS_ADD_INT_MODIFIER)) {
const flagInfo = RuleDataUtils.getCreatureGroupFlagInfo(CreatureGroupFlagEnum.MAX_HIT_POINTS_ADD_INT_MODIFIER, ruleData);
if (flagInfo) {
const contextStatModifier = flagInfo.valueContextId === null ? null : ownerData.abilityLookup[flagInfo.valueContextId];
let finalModifier = 0;
if (contextStatModifier && contextStatModifier.modifier) {
finalModifier = contextStatModifier.modifier;
}
finalTotalHp = HelperUtils.clampInt(finalTotalHp + finalModifier, RuleDataAccessors.getMinimumHpTotal(ruleData));
}
}
if (hasGroupFlag(creature, CreatureGroupFlagEnum.MAX_HIT_POINTS_ADD_MONSTER_CON_MODIFIER)) {
const flagInfo = RuleDataUtils.getCreatureGroupFlagInfo(CreatureGroupFlagEnum.MAX_HIT_POINTS_ADD_MONSTER_CON_MODIFIER, ruleData);
if (flagInfo !== null && flagInfo.valueContextId) {
let contextStatModifier = 0;
const contextStatInfo = getStatInfo(creature, flagInfo.valueContextId);
if (contextStatInfo !== null && contextStatInfo.modifier !== null) {
contextStatModifier = contextStatInfo.modifier;
}
finalTotalHp = HelperUtils.clampInt(finalTotalHp + contextStatModifier, ruleData.minimumHpTotal);
}
}
//if there is an override for the creature's hit points, use that instead
const hpOverride = deriveOverridenValue(creature, AdjustmentTypeEnum.CREATURE_HIT_POINTS, null, valueLookup);
if (hpOverride) {
finalTotalHp = hpOverride;
}
const tempHp = getTemporaryHitPoints(creature);
const finalRemovedHp = Math.min(finalTotalHp, getRemoveHitPoints(creature));
return {
baseHp: finalTotalHp,
tempHp,
removedHp: finalRemovedHp,
bonusHp: 0,
overrideHp: 0,
totalHp: finalTotalHp,
remainingHp: finalTotalHp - finalRemovedHp,
};
}
/**
*
* @param creature
* @param ownerData
* @param ruleData
*/
export function deriveInitialTempHp(creature, ownerData, ruleData) {
let initialTempHp = 0;
if (hasGroupFlag(creature, CreatureGroupFlagEnum.TEMP_HIT_POINTS_BASE_DRUID_LEVEL)) {
const flagInfo = RuleDataUtils.getCreatureGroupFlagInfo(CreatureGroupFlagEnum.TEMP_HIT_POINTS_BASE_DRUID_LEVEL, ruleData);
if (flagInfo) {
//find the level of the class or subclass id that matches the valueContextId and use it as the initial temp hp
const contextClassLevel = flagInfo.valueContextId === null ? 0 : ownerData.classLevelLookup[flagInfo.valueContextId];
initialTempHp = contextClassLevel;
}
}
if (hasGroupFlag(creature, CreatureGroupFlagEnum.TEMP_HIT_POINTS_BASE_DRUID_LEVEL_MULTIPLIER)) {
const flagInfo = RuleDataUtils.getCreatureGroupFlagInfo(CreatureGroupFlagEnum.TEMP_HIT_POINTS_BASE_DRUID_LEVEL_MULTIPLIER, ruleData);
if (flagInfo) {
//find the level of the class or subclass id that matches the valueContextId and multiply it by the contextValue
const contextClassLevel = flagInfo.valueContextId === null ? 0 : ownerData.classLevelLookup[flagInfo.valueContextId];
//only multiply the tempHp if the there is a contextClassLevel
if (contextClassLevel > 0) {
const contextValue = flagInfo.value === null ? 1 : flagInfo.value;
initialTempHp = contextClassLevel * contextValue;
}
}
}
return initialTempHp;
}
/**
*
* @param creature
*/
export function deriveUseOwnerHp(creature) {
//If this is true, the CreaturePane will use the player HP tracker instead of the Creature HP tracker and MaxHP override should be hidden from creature customization
return hasGroupFlag(creature, CreatureGroupFlagEnum.USE_OWNER_MAX_HIT_POINTS);
}
/**
*
* @param creature
* @param skill
* @param ownerData
* @param ruleData
*/
export function deriveOwnerSkillModifier(creature, skill, ownerData, ruleData) {
var _a, _b, _c;
const skillInfo = RuleDataUtils.getSkillInfo(skill.id, ruleData);
let statModifier = 0;
let proficiencyBonus = ownerData.proficiencyBonus;
let otherBonuses = 0;
if (skillInfo) {
const statInfo = getStatInfo(creature, skillInfo.stat);
const ownerSkill = HelperUtils.lookupDataOrFallback(ownerData.skillLookup, skill.id);
statModifier = (_a = statInfo === null || statInfo === void 0 ? void 0 : statInfo.monster.modifier) !== null && _a !== void 0 ? _a : 0;
if (ownerSkill !== null) {
const ownerProficiencyLevel = SkillAccessors.getProficiencyLevel(ownerSkill);
// Creature gives proficiency bonus if the owner doesn't have any
let proficiencyLevel = ProficiencyLevelEnum.FULL;
if (ownerProficiencyLevel !== ProficiencyLevelEnum.NONE) {
proficiencyLevel = ownerProficiencyLevel;
}
proficiencyBonus = CharacterDerivers.deriveProficiencyBonusAmount(proficiencyLevel, ownerData.proficiencyBonus);
if (shouldReplaceWithOwnerStat(creature, skillInfo.stat)) {
if (SkillAccessors.getIsOverridden(ownerSkill)) {
statModifier = (_b = SkillAccessors.getModifier(ownerSkill)) !== null && _b !== void 0 ? _b : 0;
proficiencyBonus = 0;
}
else {
statModifier = SkillAccessors.getStatModifier(ownerSkill);
otherBonuses = SkillAccessors.getModifierBonuses(ownerSkill);
}
}
else {
const statInfo = getStatInfo(creature, skillInfo.stat);
statModifier = (_c = statInfo === null || statInfo === void 0 ? void 0 : statInfo.monster.modifier) !== null && _c !== void 0 ? _c : 0;
}
}
}
return statModifier + proficiencyBonus + otherBonuses;
}
/**
*
* @param creature
* @param stat
* @param ownerData
*/
export function deriveOwnerSaveModifier(creature, stat, ownerData) {
var _a, _b, _c;
const statInfo = getStatInfo(creature, stat.id);
let statModifier = 0;
let proficiencyBonus = ownerData.proficiencyBonus;
let otherBonuses = 0;
const ownerAbility = HelperUtils.lookupDataOrFallback(ownerData.abilityLookup, stat.id);
if (ownerAbility !== null) {
const ownerProficiencyLevel = AbilityAccessors.getProficiencyLevel(ownerAbility);
// Creature gives proficiency bonus if the owner doesn't have any
let proficiencyLevel = ProficiencyLevelEnum.FULL;
if (ownerProficiencyLevel !== ProficiencyLevelEnum.NONE) {
proficiencyLevel = ownerProficiencyLevel;
}
proficiencyBonus = CharacterDerivers.deriveProficiencyBonusAmount(proficiencyLevel, ownerData.proficiencyBonus);
if (shouldReplaceWithOwnerStat(creature, stat.id)) {
if (AbilityAccessors.getIsSaveOverridden(ownerAbility)) {
statModifier = (_a = AbilityAccessors.getSave(ownerAbility)) !== null && _a !== void 0 ? _a : 0;
proficiencyBonus = 0;
}
else {
statModifier = (_b = AbilityAccessors.getModifier(ownerAbility)) !== null && _b !== void 0 ? _b : 0;
otherBonuses = AbilityAccessors.getSaveBonuses(ownerAbility);
}
}
else {
statModifier = (_c = statInfo === null || statInfo === void 0 ? void 0 : statInfo.monster.modifier) !== null && _c !== void 0 ? _c : 0;
}
}
return statModifier + proficiencyBonus + otherBonuses;
}
/**
*
* @param creature
* @param skill
* @param ruleData
*/
export function deriveCreatureSkillModifier(creature, skill, ruleData) {
var _a, _b;
const skillInfo = RuleDataUtils.getSkillInfo(skill.skillId, ruleData);
let statModifier = 0;
if (skillInfo) {
const statInfo = getStatInfo(creature, skillInfo.stat);
statModifier = (_a = statInfo === null || statInfo === void 0 ? void 0 : statInfo.monster.modifier) !== null && _a !== void 0 ? _a : 0;
}
const proficiencyBonus = getChallengeProficiencyBonus(creature);
const otherBonuses = (_b = skill.additionalBonus) !== null && _b !== void 0 ? _b : 0;
return statModifier + proficiencyBonus + otherBonuses;
}
/**
*
* @param creature
* @param savingThrow
*/
export function deriveCreatureSaveModifier(creature, savingThrow) {
var _a, _b;
const statInfo = getStatInfo(creature, savingThrow.statId);
const statModifier = (_a = statInfo === null || statInfo === void 0 ? void 0 : statInfo.monster.modifier) !== null && _a !== void 0 ? _a : 0;
const proficiencyBonus = getChallengeProficiencyBonus(creature);
const otherBonuses = (_b = savingThrow.bonusModifier) !== null && _b !== void 0 ? _b : 0;
return statModifier + proficiencyBonus + otherBonuses;
}
/**
*
* @param creature
* @param ownerData
* @param ruleData
*/
export function deriveSkills(creature, ownerData, ruleData) {
const skills = RuleDataAccessors.getAbilitySkills(ruleData);
return skills
.map((skillInfo) => {
var _a;
const statInfo = RuleDataUtils.getStatInfo(skillInfo.stat, ruleData);
const creatureSkill = getDefinitionSkills(creature).find((skill) => skill.skillId === skillInfo.id);
const isCreatureProficient = !!creatureSkill;
const potentialModifiers = [];
if (hasGroupFlag(creature, CreatureGroupFlagEnum.EVALUATE_OWNER_SKILL_PROFICIENCIES)) {
const ownerSkill = HelperUtils.lookupDataOrFallback(ownerData.skillLookup, skillInfo.id);
const isOwnerProficient = ownerSkill !== null && SkillAccessors.getProficiencyLevel(ownerSkill) !== ProficiencyLevelEnum.NONE;
if (isCreatureProficient || isOwnerProficient) {
potentialModifiers.push(deriveOwnerSkillModifier(creature, skillInfo, ownerData, ruleData));
}
// Can potentially use creatures modifier if the owner is "proficient"
if (creatureSkill && isCreatureProficient && isOwnerProficient) {
potentialModifiers.push(deriveCreatureSkillModifier(creature, creatureSkill, ruleData));
}
}
else if (creatureSkill && isCreatureProficient) {
potentialModifiers.push(deriveCreatureSkillModifier(creature, creatureSkill, ruleData));
}
// if we didn't generate any potential modifiers, exit early and null will be filtered out
if (!potentialModifiers.length) {
return null;
}
const modifier = Math.max(...potentialModifiers);
let bonuses = 0;
if (hasGroupFlag(creature, CreatureGroupFlagEnum.PROFICIENT_SKILLS_ADD_PROFICIENCY_BONUS)) {
bonuses += ownerData.proficiencyBonus;
}
return {
id: skillInfo.id,
modifier: modifier + bonuses,
statKey: (_a = statInfo === null || statInfo === void 0 ? void 0 : statInfo.key) !== null && _a !== void 0 ? _a : 'UNK',
};
})
.filter(TypeScriptUtils.isNotNullOrUndefined);
}
/**
*
* @param creature
* @param ownerData
* @param ruleData
*/
export function deriveSavingThrows(creature, ownerData, ruleData) {
const stats = RuleDataAccessors.getStats(ruleData);
return stats
.map((stat) => {
var _a;
const creatureSavingThrow = getDefinitionSavingThrows(creature).find((savingThrow) => savingThrow.statId === stat.id);
const isCreatureProficient = !!creatureSavingThrow;
const potentialModifiers = [];
if (hasGroupFlag(creature, CreatureGroupFlagEnum.EVALUATE_OWNER_SAVE_PROFICIENCIES)) {
const ownerAbility = HelperUtils.lookupDataOrFallback(ownerData.abilityLookup, stat.id);
const isOwnerProficient = ownerAbility !== null &&
AbilityAccessors.getProficiencyLevel(ownerAbility) !== ProficiencyLevelEnum.NONE;
if (isCreatureProficient || isOwnerProficient) {
potentialModifiers.push(deriveOwnerSaveModifier(creature, stat, ownerData));
}
// Can potentially use creatures modifier if the owner is "proficient"
if (creatureSavingThrow && isCreatureProficient && isOwnerProficient) {
potentialModifiers.push(deriveCreatureSaveModifier(creature, creatureSavingThrow));
}
}
else if (creatureSavingThrow && isCreatureProficient) {
potentialModifiers.push(deriveCreatureSaveModifier(creature, creatureSavingThrow));
}
// if we didn't generate any potential modifiers, exit early and null will be filtered out
if (!potentialModifiers.length) {
return null;
}
const modifier = Math.max(...potentialModifiers);
let bonuses = 0;
if (hasGroupFlag(creature, CreatureGroupFlagEnum.PROFICIENT_SAVING_THROWS_ADD_PROFICIENCY_BONUS)) {
bonuses += ownerData.proficiencyBonus;
}
return {
statId: stat.id,
modifier: modifier + bonuses,
statKey: (_a = stat.key) !== null && _a !== void 0 ? _a : '',
};
})
.filter(TypeScriptUtils.isNotNullOrUndefined);
}
/**
*
* @param creature
* @param ownerData
* @param ruleData
*/
export function deriveStats(creature, ownerData, ruleData) {
return getDefinitionStats(creature).map((stat) => {
var _a;
const originalScore = stat.value;
let score = stat.value;
if (shouldReplaceWithOwnerStat(creature, stat.statId)) {
const ownerAbility = HelperUtils.lookupDataOrFallback(ownerData.abilityLookup, stat.statId);
if (ownerAbility !== null) {
score = AbilityAccessors.getScore(ownerAbility);
}
}
const statInfo = RuleDataUtils.getStatInfo(stat.statId, ruleData);
const statKey = (_a = statInfo === null || statInfo === void 0 ? void 0 : statInfo.key) !== null && _a !== void 0 ? _a : null;
const modifier = score === null ? null : AbilityUtils.getStatScoreModifier(score, ruleData);
const originalModifier = originalScore === null ? null : AbilityUtils.getStatScoreModifier(originalScore, ruleData);
return {
id: stat.statId,
score,
modifier,
statKey,
monster: {
score: originalScore,
modifier: originalModifier,
},
};
});
}
/**
*
* @param creature
* @param ruleData
*/
export function deriveDamageAdjustments(creature, ruleData) {
return getDefinitionDamageAdjustments(creature)
.map((damageAdjustmentId) => RuleDataUtils.getDamageAdjustmentInfo(damageAdjustmentId, ruleData))
.filter(TypeScriptUtils.isNotNullOrUndefined);
}
/**
*
* @param creature
* @param ruleData
*/
export function deriveConditionImmunities(creature, ruleData) {
return getDefinitionConditionImmunities(creature)
.map((conditionId) => RuleDataUtils.getConditionInfo(conditionId, ruleData))
.filter(TypeScriptUtils.isNotNullOrUndefined);
}
/**
*
* @param damageAdjustmentType
* @param creature
*/
export function deriveDamageAdjustmentType(damageAdjustmentType, creature) {
return getDamageAdjustments(creature).filter((damageAdjustment) => damageAdjustment.type === damageAdjustmentType);
}
/**
*
* @param creature
* @param ruleData
*/
export function deriveSubTypes(creature, ruleData) {
const subTypes = getDefinitionSubTypes(creature);
return subTypes
.map((subTypeId) => RuleDataUtils.getMonsterSubTypeInfo(subTypeId, ruleData))
.filter(TypeScriptUtils.isNotNullOrUndefined);
}
/**
*
* @param creature
* @param ownerData
* @param skillLookup
* @param ruleData
*/
export function derivePassivePerception(creature, ownerData, skillLookup, ruleData) {
if (!hasGroupFlag(creature, CreatureGroupFlagEnum.EVALUATE_UPDATED_PASSIVE_PERCEPTION)) {
return getDefinitionPassivePerception(creature);
}
let skillModifier = 0;
const perceptionInfo = skillLookup[AbilitySkillEnum.PERCEPTION];
if (perceptionInfo) {
skillModifier = perceptionInfo.modifier;
}
else {
// fallback to perception's stat modifier if perception isn't called out
const skillInfo = RuleDataUtils.getSkillInfo(AbilitySkillEnum.PERCEPTION, ruleData);
if (skillInfo) {
const statInfo = getStatInfo(creature, skillInfo.stat);
skillModifier = statInfo && statInfo.modifier !== null ? statInfo.modifier : 0;
}
}
const derivedPassivePerception = CharacterDerivers.derivePassiveSkill(skillModifier);
const passivePerceptionPossibilities = [derivedPassivePerception];
if (hasGroupFlag(creature, CreatureGroupFlagEnum.EVALUATE_OWNER_PASSIVE_PERCEPTION)) {
if (ownerData.passivePerception !== null) {
passivePerceptionPossibilities.push(ownerData.passivePerception);
}
}
return Math.max(...passivePerceptionPossibilities);
}
/**
*
* @param creature
* @param ruleData
*/
export function deriveEnvironmentTags(creature, ruleData) {
const envs = getEnvironments(creature);
return envs
.map((envId) => {
const envInfo = RuleDataUtils.getEnvironmentInfo(envId, ruleData);
if (envInfo) {
return envInfo.name;
}
return null;
})
.filter(TypeScriptUtils.isNotNullOrUndefined);
}
/**
*
* @param creature
* @param ruleData
*/
export function deriveSubTypeTags(creature, ruleData) {
const subTypes = getDefinitionSubTypes(creature);
return subTypes
.map((subTypeId) => {
const info = RuleDataUtils.getMonsterSubTypeInfo(subTypeId, ruleData);
if (info) {
return info.name;
}
return null;
})
.filter(TypeScriptUtils.isNotNullOrUndefined);
}
/**
*
* @param creature
* @param ruleData
*/
export function deriveTypeTag(creature, ruleData) {
return RuleDataUtils.getMonsterTypeName(getTypeId(creature), ruleData, null);
}
/**
*
* @param creature
*/
export function deriveMovementIds(creature) {
return getMovements(creature).map((movement) => movement.movementId);
}
/**
*
* @param creature
* @param ruleData
*/
export function deriveMovementNames(creature, ruleData) {
return getMovements(creature).map((movement) => RuleDataUtils.getMovementDescription(movement.movementId, ruleData));
}
/**
*
* @param creature
* @param ownerData
* @param valueLookup
*/
export function deriveArmorClass(creature, ownerData, valueLookup, ruleData) {
var _a;
const armorOverride = deriveOverridenValue(creature, AdjustmentTypeEnum.CREATURE_AC, null, valueLookup);
if (armorOverride) {
return armorOverride;
}
let bonuses = 0;
if (hasGroupFlag(creature, CreatureGroupFlagEnum.ARMOR_ADD_PROFICIENCY_BONUS)) {
bonuses += ownerData.proficiencyBonus;
}
let armorClass = getDefinitionArmorClass(creature);
if (hasGroupFlag(creature, CreatureGroupFlagEnum.ARMOR_ADD_OWNER_WIS_PLUS_FIXED_VALUE)) {
const flagInfo = RuleDataUtils.getCreatureGroupFlagInfo(CreatureGroupFlagEnum.ARMOR_ADD_OWNER_WIS_PLUS_FIXED_VALUE, ruleData);
if (flagInfo) {
const contextClassLevel = flagInfo.valueContextId === null ? 0 : ownerData.classLevelLookup[flagInfo.valueContextId];
//Check if the owner has a matching class or subclass to the contextValueId
if (contextClassLevel > 0) {
const ownerWisdomModifier = (_a = ownerData.abilityLookup[AbilityStatEnum.WISDOM].modifier) !== null && _a !== void 0 ? _a : 0;
const contextValue = flagInfo.value === null ? 0 : flagInfo.value;
//AC will should be the highest value between the current AC and the owner's wisdom modifier + the context value
armorClass = Math.max(armorClass, contextValue + ownerWisdomModifier);
}
}
}
//Add any final bonuses to the AC;
return armorClass + bonuses;
}
/**
*
* @param creature
* @param valueTypeId
* @param fallback
* @param valueLookup
*/
function deriveOverridenValue(creature, valueTypeId, fallback, valueLookup) {
if (valueLookup) {
const override = ValueUtils.getKeyValue(valueLookup, valueTypeId, ValueHacks.hack__toString(getMappingId(creature)), ValueHacks.hack__toString(getMappingEntityTypeId(creature)));
if (override) {
return override;
}
}
return fallback;
}
/**
*
* @param creature
* @param valueLookup
*/
export function deriveSizeId(creature, valueLookup) {
return deriveOverridenValue(creature, AdjustmentTypeEnum.CREATURE_SIZE, getDefinitionSizeId(creature), valueLookup);
}
/**
*
* @param creature
* @param valueLookup
*/
export function deriveTypeId(creature, valueLookup) {
return deriveOverridenValue(creature, AdjustmentTypeEnum.CREATURE_TYPE_OVERRIDE, getDefinitionTypeId(creature), valueLookup);
}
/**
*
* @param creature
* @param valueLookup
*/
export function deriveAlignmentId(creature, valueLookup) {
return deriveOverridenValue(creature, AdjustmentTypeEnum.CREATURE_ALIGNMENT, getDefinitionAlignmentId(creature), valueLookup);
}
/**
*
* @param creature
* @param valueLookup
*/
export function deriveNotes(creature, valueLookup) {
return deriveOverridenValue(creature, AdjustmentTypeEnum.CREATURE_NOTES, null, valueLookup);
}
/**
*
* @param creature
* @param ruleData
*/
export function deriveLevel(creature, ruleData) {
if (hasGroupFlag(creature, CreatureGroupFlagEnum.USE_CHALLENGE_RATING_AS_LEVEL)) {
const challengeInfo = RuleDataUtils.getChallengeInfo(getChallengeRatingId(creature), ruleData);
const level = challengeInfo ? challengeInfo.value : 0;
const maxCharLevel = RuleDataAccessors.getMaxCharacterLevel(ruleData);
return HelperUtils.clampInt(level, 1, maxCharLevel);
}
return null;
}
/**
*
* @param creature
* @param ruleData
*/
export function deriveChallengeInfo(creature, ruleData) {
if (hasGroupFlag(creature, CreatureGroupFlagEnum.USE_CHALLENGE_RATING_AS_LEVEL)) {
return null;
}
return RuleDataUtils.getChallengeInfo(getChallengeRatingId(creature), ruleData);
}
export function deriveLairChallengeInfo(creature, ruleData) {
if (hasGroupFlag(creature, CreatureGroupFlagEnum.USE_CHALLENGE_RATING_AS_LEVEL)) {
return null;
}
return RuleDataUtils.getChallengeInfo(getLairChallengeRatingId(creature), ruleData);
}
/**
*
* @param creature
* @param groupInfo
* @param infusion
*/
export function deriveFlags(creature, groupInfo, infusion) {
const flags = [];
if (groupInfo && groupInfo.flags !== null) {
flags.push(...groupInfo.flags);
}
if (infusion) {
const creatureData = InfusionAccessors.getCreatureData(infusion);
if (creatureData) {
const foundCreatureData = creatureData.find((creatureDataEntry) => creatureDataEntry.monsterId === getId(creature));
if (foundCreatureData && foundCreatureData.flags !== null) {
flags.push(...foundCreatureData.flags);
}
}
}
return flags;
}
/**
*
* @param creature
* @param valueLookup
*/
export function deriveIsCustomized(creature, valueLookup) {
let isCustomized = ValueValidators.validateHasCustomization(CREATURE_CUSTOMIZATION_ADJUSTMENT_TYPES, valueLookup, ValueHacks.hack__toString(getMappingId(creature)), ValueHacks.hack__toString(getMappingEntityTypeId(creature)));
if (!isCustomized) {
if (creature.name !== null && creature.name !== '') {
isCustomized = true;
}
}
return isCustomized;
}
@@ -0,0 +1,78 @@
import { keyBy } from 'lodash';
import { ClassGenerators } from '../Class';
import { DamageAdjustmentTypeEnum } from '../Core';
import { HelperUtils } from '../Helper';
import { RuleDataUtils } from '../RuleData';
import { getDefinitionArmorClass, getGroupId, getMappingId } from './accessors';
import { deriveAlignmentId, deriveArmorClass, deriveChallengeInfo, deriveConditionImmunities, deriveDamageAdjustments, deriveDamageAdjustmentType, deriveEnvironmentTags, deriveFlags, deriveHitPointInfo, deriveInitialTempHp, deriveUseOwnerHp, deriveIsCustomized, deriveLairChallengeInfo, deriveLevel, deriveMovementIds, deriveMovementNames, deriveNotes, derivePassivePerception, derivePreOwnerHitPointInfo, deriveSavingThrows, deriveSizeId, deriveSkills, deriveStats, deriveSubTypes, deriveSubTypeTags, deriveTypeId, deriveTypeTag, } from './derivers';
/**
*
* @param creatures
* @param ownerData
* @param valueLookup
* @param creatureInfusionLookup
* @param ruleData
*/
export function generateCreatures(creatures, ownerData, valueLookup, creatureInfusionLookup, ruleData) {
return creatures.map((creature) => generateCreature(creature, ownerData, valueLookup, creatureInfusionLookup, ruleData));
}
/**
*
* @param creature
* @param ruleData
* @param valueLookup
* @param creatureInfusionLookup
*/
export function generateBaseCreature(creature, ruleData, valueLookup = {}, creatureInfusionLookup = {}) {
const sizeId = deriveSizeId(creature, valueLookup);
const groupInfo = RuleDataUtils.getCreatureGroupInfo(getGroupId(creature), ruleData);
const infusion = HelperUtils.lookupDataOrFallback(creatureInfusionLookup, getMappingId(creature));
return Object.assign(Object.assign({}, creature), { sizeId,
infusion,
groupInfo, typeId: deriveTypeId(creature, valueLookup), alignmentId: deriveAlignmentId(creature, valueLookup), flags: deriveFlags(creature, groupInfo, infusion), sizeInfo: RuleDataUtils.getCreatureSizeInfo(sizeId, ruleData), damageAdjustments: deriveDamageAdjustments(creature, ruleData), conditionImmunities: deriveConditionImmunities(creature, ruleData), subTypes: deriveSubTypes(creature, ruleData), environmentTags: deriveEnvironmentTags(creature, ruleData), subTypeTags: deriveSubTypeTags(creature, ruleData), hitPointInfo: derivePreOwnerHitPointInfo(creature), movementIds: deriveMovementIds(creature), movementNames: deriveMovementNames(creature, ruleData), armorClass: getDefinitionArmorClass(creature), notes: deriveNotes(creature, valueLookup) });
}
/**
*
* @param creature
* @param ownerData
* @param valueLookup
* @param creatureInfusionLookup
* @param ruleData
*/
export function generateCreature(creature, ownerData, valueLookup, creatureInfusionLookup, ruleData) {
// Generate all base non dependent, but still relevant data on the creature
const baseCreature = generateBaseCreature(creature, ruleData, valueLookup, creatureInfusionLookup);
// Generate all dependent data that is used to derive other properties
const stats = deriveStats(baseCreature, ownerData, ruleData);
const creatureStageOne = Object.assign(Object.assign({}, baseCreature), { stats, statLookup: keyBy(stats, 'id'), level: deriveLevel(baseCreature, ruleData), challengeInfo: deriveChallengeInfo(baseCreature, ruleData), lairChallengeInfo: deriveLairChallengeInfo(baseCreature, ruleData), typeTag: deriveTypeTag(baseCreature, ruleData) });
const savingThrows = deriveSavingThrows(creatureStageOne, ownerData, ruleData);
const skills = deriveSkills(creatureStageOne, ownerData, ruleData);
const skillLookup = keyBy(skills, 'id');
// return final generated creature with full derived data
return Object.assign(Object.assign({}, creatureStageOne), { damageVulnerabilities: deriveDamageAdjustmentType(DamageAdjustmentTypeEnum.VULNERABILITY, creatureStageOne), damageResistances: deriveDamageAdjustmentType(DamageAdjustmentTypeEnum.RESISTANCE, creatureStageOne), damageImmunities: deriveDamageAdjustmentType(DamageAdjustmentTypeEnum.IMMUNITY, creatureStageOne), savingThrows, savingThrowLookup: keyBy(savingThrows, 'statId'), skills,
skillLookup, passivePerception: derivePassivePerception(creatureStageOne, ownerData, skillLookup, ruleData), armorClass: deriveArmorClass(creatureStageOne, ownerData, valueLookup, ruleData), hitPointInfo: deriveHitPointInfo(creatureStageOne, ownerData, valueLookup, ruleData), initialTempHp: deriveInitialTempHp(creatureStageOne, ownerData, ruleData), useOwnerHp: deriveUseOwnerHp(creatureStageOne), isCustomized: deriveIsCustomized(creatureStageOne, valueLookup) });
}
/**
*
* @param classLevelLookup
* @param skillLookup
* @param proficiencyBonus
* @param abilityLookup
* @param passivePerception
*/
export function generateCreatureOwnerData(classes, skillLookup, proficiencyBonus, abilityLookup, passivePerception) {
return {
abilityLookup,
proficiencyBonus,
skillLookup,
classLevelLookup: ClassGenerators.generateClassLevelLookup(classes),
passivePerception,
};
}
/**
*
* @param creatures
*/
export function generateCreatureLookup(creatures) {
return keyBy(creatures, (creature) => getMappingId(creature));
}
@@ -0,0 +1,13 @@
import * as CreatureAccessors from './accessors';
import * as CreatureConstants from './constants';
import * as CreatureDerivers from './derivers';
import * as CreatureGenerators from './generators';
import * as CreatureNotes from './notes';
import * as CreatureRenderers from './renderers';
import * as CreatureSimulators from './simulators';
import * as CreatureTypings from './typings';
import * as CreatureUtils from './utils';
export * from './typings';
export * from './constants';
export { CreatureAccessors, CreatureDerivers, CreatureGenerators, CreatureNotes, CreatureSimulators, CreatureUtils };
export default Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, CreatureAccessors), CreatureConstants), CreatureDerivers), CreatureGenerators), CreatureNotes), CreatureTypings), CreatureSimulators), CreatureUtils), CreatureRenderers);
@@ -0,0 +1,34 @@
import { TypeScriptUtils } from '../../utils';
import { InfusionAccessors } from '../Infusion';
import { NoteGenerators } from '../Note';
import { getEnvironmentTags, getInfusion, getNotes, getTags } from './accessors';
export function getTagNoteComponents(creature) {
const tags = getTags(creature);
return NoteGenerators.createGroup(tags.map((tag) => NoteGenerators.createPlainText(tag)), ', ');
}
export function getEnvironmentNoteComponents(creature) {
const envTags = getEnvironmentTags(creature);
return NoteGenerators.createGroup(envTags.map((tag) => NoteGenerators.createPlainText(tag)), ', ');
}
function getUserNoteComponent(creature) {
const notes = getNotes(creature);
if (notes) {
return NoteGenerators.createPlainText(notes);
}
return null;
}
function getInfusionNoteComponent(creature) {
const infusion = getInfusion(creature);
if (infusion) {
return NoteGenerators.createPlainText(`Infusion: ${InfusionAccessors.getName(infusion)}`);
}
return null;
}
export function getNoteComponents(creature, ruleData) {
const notes = [];
notes.push(getUserNoteComponent(creature));
notes.push(getInfusionNoteComponent(creature));
notes.push(getTagNoteComponents(creature));
notes.push(getEnvironmentNoteComponents(creature));
return notes.filter(TypeScriptUtils.isNotNullOrUndefined);
}
@@ -0,0 +1,166 @@
import { DiceRenderers } from '../Dice';
import { FormatUtils } from '../Format';
import { RuleDataUtils } from '../RuleData';
import { getAlignmentId, getArmorClass, getArmorClassDescription, getChallengeInfo, getDefinitionName, getHideCr, getHitPointDice, getHitPointInfo, getInitiative, getLairChallengeInfo, getLanguageNote, getLanguages, getLevel, getMovements, getName, getPassivePerception, getSavingThrows, getSenses, getSizeId, getSkills, getStatBlockType, getSubTypes, getTypeId, } from './accessors';
import { StatBlockTypeEnum } from './constants';
import { getTypeName } from './utils';
//Render a formatted meta text string for a given Creature
export function renderMetaText(creature, ruleData, useBaseMonsterType) {
var _a, _b;
//CreatureLevel
const creatureLevel = getLevel(creature);
const level = creatureLevel !== null ? `${FormatUtils.ordinalize(creatureLevel)}-level` : '';
//CreatureSize
const sizeInfo = RuleDataUtils.getCreatureSizeInfo(getSizeId(creature), ruleData);
const size = (_a = sizeInfo === null || sizeInfo === void 0 ? void 0 : sizeInfo.name) !== null && _a !== void 0 ? _a : '';
//CreatureType
let type = '';
if (useBaseMonsterType) {
const typeInfo = RuleDataUtils.getMonsterTypeInfo(getTypeId(creature), ruleData);
if (typeInfo === null || typeInfo === void 0 ? void 0 : typeInfo.name) {
type = typeInfo.name;
}
}
else {
type = getTypeName(creature, ruleData);
}
//CreatureAlignment
const alignmentInfo = RuleDataUtils.getAlignmentInfo(getAlignmentId(creature), ruleData);
const alignment = (_b = alignmentInfo === null || alignmentInfo === void 0 ? void 0 : alignmentInfo.name) !== null && _b !== void 0 ? _b : '';
//Extra Text
let extraTextChunks = [];
//If the creature has a customized name that is differenct than the definition name, add the definition name
if (getName(creature) !== getDefinitionName(creature)) {
extraTextChunks.push(getDefinitionName(creature));
}
//Add any subtypes
const subTypes = getSubTypes(creature);
if (subTypes.length) {
subTypes.forEach((monsterInfo) => {
if (monsterInfo.name !== null) {
extraTextChunks.push(monsterInfo.name);
}
});
}
const extraText = extraTextChunks.join(', ');
return `${level} ${size} ${type}${extraText ? ` (${extraText})` : ''}${alignment ? `, ${alignment}` : ''}`.trim();
}
//Render a Creature's Armor Class with any additional description added
export function renderArmorClass(creature) {
return `${getArmorClass(creature)} ${getArmorClassDescription(creature)}`.trim();
}
//Render a Creature's initative info: bonus (score)
export function renderInitiativeInfo(creature) {
const initiativeInfo = getInitiative(creature);
if (initiativeInfo === null || initiativeInfo === void 0 ? void 0 : initiativeInfo.bonus) {
const { bonus, score } = initiativeInfo;
return `${FormatUtils.renderSignedNumber(bonus)} ${score ? `(${initiativeInfo.score})` : ''}`.trim();
}
return null;
}
//Render a Creature's total Hit Points and Hit Point Dice
export function renderHitPointInfo(creature) {
const totalHp = getHitPointInfo(creature).totalHp;
const hitPointDice = getHitPointDice(creature);
const hpDiceText = hitPointDice ? ` (${DiceRenderers.renderDice(getHitPointDice(creature))})` : '';
return `${totalHp}${hpDiceText}`;
}
//Render a Creature's Speed info
export function renderSpeedInfo(creature, ruleData) {
const movements = getMovements(creature);
if (movements.length) {
const movementDisplays = movements.map((movement, idx) => {
let label = '';
if (idx !== 0) {
label = RuleDataUtils.getMovementName(movement.movementId, ruleData);
}
return `${label} ${FormatUtils.renderDistance(movement.speed)} ${movement.notes ? movement.notes : ''}`.trim();
});
return movementDisplays.join(', ');
}
return '--';
}
//Render a Creature's Saving Throws info
export function renderSavingThrows(creature) {
const savingThrows = getSavingThrows(creature);
if (!savingThrows.length) {
return null;
}
const savingThrowDisplays = savingThrows.map((savingThrow) => {
return `${savingThrow.statKey} ${FormatUtils.renderSignedNumber(savingThrow.modifier)}`;
});
return savingThrowDisplays.join(', ');
}
//Render a Creature's Skills info
export function renderSkills(creature, ruleData) {
const skills = getSkills(creature);
if (!skills.length) {
return null;
}
const skillDisplays = skills.map((skill) => {
const skillInfo = RuleDataUtils.getSkillInfo(skill.id, ruleData);
const name = (skillInfo === null || skillInfo === void 0 ? void 0 : skillInfo.name) ? skillInfo.name : '';
const modifier = skill.modifier;
return `${name} ${FormatUtils.renderSignedNumber(modifier)}`;
});
return skillDisplays.join(', ');
}
//Render a Creature's Senses info
export function renderSensesInfo(creature, ruleData) {
const senses = getSenses(creature);
const senseDisplays = senses.map((sense) => {
const senseInfo = RuleDataUtils.getSenseInfo(sense.senseId, ruleData);
const senseName = senseInfo ? senseInfo.name : '';
return `${senseName} ${sense.notes}`;
});
const senseDisplay = senseDisplays.length ? `${senseDisplays.join(', ')}, ` : '';
const passivePerception = getPassivePerception(creature);
return `${senseDisplay}Passive Perception ${passivePerception}`;
}
//Render a Creature's Languages info
export function renderLanguages(creature, ruleData) {
const languages = getLanguages(creature);
const languageNote = getLanguageNote(creature);
let languageText = '';
if (languages.length || languageNote) {
let languageDisplays = languages.map((language) => {
const name = RuleDataUtils.getLanguageName(language.languageId, ruleData);
return `${name} ${language.notes}`.trim();
});
if (languageNote) {
languageDisplays.push(languageNote);
}
languageText = languageDisplays.join(', ');
}
else {
languageText = '--';
}
return languageText;
}
//Render a Creature's Challenge Rating info, adjusted for 2014 vs 2024 version
export function renderChallengeRatingInfo(creature) {
const challengeInfo = getChallengeInfo(creature);
const hideCr = getHideCr(creature);
const statBlockType = getStatBlockType(creature);
if (!challengeInfo || hideCr) {
return null;
}
if (statBlockType === StatBlockTypeEnum.CORE_RULES_2024) {
const PBtext = `; PB ${FormatUtils.renderSignedNumber(challengeInfo.proficiencyBonus)}`;
const lairChallengeInfo = getLairChallengeInfo(creature);
const lairCRText = (lairChallengeInfo === null || lairChallengeInfo === void 0 ? void 0 : lairChallengeInfo.xp)
? `, or ${FormatUtils.renderLocaleNumber(lairChallengeInfo.xp)} in lair`
: '';
return `${FormatUtils.renderChallengeRating(challengeInfo.value)} (XP ${FormatUtils.renderLocaleNumber(challengeInfo.xp)}${lairCRText}${PBtext})`;
}
return `${FormatUtils.renderChallengeRating(challengeInfo.value)} (${FormatUtils.renderLocaleNumber(challengeInfo.xp)} XP)`;
}
//render a Creature's Proficiency Bonus
export function renderProficiencyBonus(creature) {
const challengeInfo = getChallengeInfo(creature);
const hideCr = getHideCr(creature);
if (!challengeInfo || hideCr) {
return null;
}
return FormatUtils.renderSignedNumber(challengeInfo.proficiencyBonus);
}
@@ -0,0 +1,23 @@
import { deriveChallengeInfo, deriveLairChallengeInfo, deriveLevel, deriveTypeTag } from './derivers';
import { generateBaseCreature } from './generators';
/**
*
* @param creatureDefinition
* @param groupId
* @param ruleData
*/
export function simulateCreature(creatureDefinition, groupId, ruleData) {
const creature = {
definition: Object.assign({}, creatureDefinition),
description: null,
entityTypeId: -1,
groupId,
id: -1,
isActive: false,
name: null,
removedHitPoints: 0,
temporaryHitPoints: 0,
};
const baseCreature = generateBaseCreature(creature, ruleData);
return Object.assign(Object.assign({}, baseCreature), { level: deriveLevel(baseCreature, ruleData), challengeInfo: deriveChallengeInfo(baseCreature, ruleData), lairChallengeInfo: deriveLairChallengeInfo(baseCreature, ruleData), typeTag: deriveTypeTag(baseCreature, ruleData), statLookup: {}, stats: [], damageImmunities: [], damageResistances: [], damageVulnerabilities: [], passivePerception: null, savingThrowLookup: {}, savingThrows: [], skillLookup: {}, skills: [], isCustomized: false, hitPointInfo: Object.assign({}, baseCreature.hitPointInfo), initialTempHp: 0, useOwnerHp: false });
}
@@ -0,0 +1,174 @@
import { orderBy } from 'lodash';
import { HelperUtils } from '../Helper';
import { InfusionAccessors } from '../Infusion';
import { RuleDataUtils } from '../RuleData';
import { getEnvironmentTags, getFlags, getGroupInfo, getInfusion, getMovements, getSavingThrows, getStats, getSubTypeTags, getSwarmInfo, getTags, getTypeId, getTypeTag, isSwarm, } from './accessors';
import { CreatureGroupFlagEnum } from './constants';
/**
*
* @param creature
* @param ruleData
* @param includeMultiParenthesis
*/
export function getTypeName(creature, ruleData, includeMultiParenthesis = true) {
const groupInfo = getGroupInfo(creature);
const typeId = getTypeId(creature);
let prefix = '';
let typeName = RuleDataUtils.getMonsterTypeName(typeId, ruleData);
if (!typeName) {
typeName = '';
}
if (isSwarm(creature)) {
const swarmInfo = getSwarmInfo(creature);
if (swarmInfo) {
const sizeInfo = RuleDataUtils.getCreatureSizeInfo(swarmInfo.sizeId, ruleData);
typeName = RuleDataUtils.getMonsterTypeName(swarmInfo.typeId, ruleData, undefined, true);
if (!typeName) {
typeName = '';
}
if (sizeInfo) {
prefix = `swarm of ${sizeInfo.name} `;
}
}
}
if (groupInfo && groupInfo.monsterTypes !== null && groupInfo.monsterTypes.length) {
if (groupInfo.monsterTypes.includes(typeId)) {
typeName = RuleDataUtils.getMonsterTypeName(typeId, ruleData, undefined, isSwarm(creature));
if (!typeName) {
typeName = '';
}
}
else {
let displayName = '';
groupInfo.monsterTypes.forEach((monsterTypeId, idx) => {
const parts = [];
if (idx !== 0) {
parts.push(', ');
}
if (groupInfo && groupInfo.monsterTypes !== null && idx === groupInfo.monsterTypes.length - 1) {
parts.push('or ');
}
const monsterTypeName = RuleDataUtils.getMonsterTypeName(monsterTypeId, ruleData, undefined, isSwarm(creature));
if (monsterTypeName) {
parts.push(monsterTypeName);
}
displayName += parts.join('');
});
if (includeMultiParenthesis) {
typeName = `(${displayName})`;
}
else {
typeName = displayName;
}
}
}
return `${prefix}${typeName}`.trim();
}
/**
*
* @param creature
*/
export function getHighestMovementInfo(creature) {
return HelperUtils.getLast(getMovements(creature), 'speed');
}
/**
*
* @param creature
*/
export function getSearchTags(creature) {
const tags = [...getEnvironmentTags(creature), ...getTags(creature), ...getSubTypeTags(creature)];
const typeTag = getTypeTag(creature);
if (typeTag) {
tags.push(typeTag);
}
return tags;
}
/**
*
* @param creature
* @param flag
*/
export function hasGroupFlag(creature, flag) {
return getFlags(creature).includes(flag);
}
/**
*
* @param creature
* @param stat
*/
export function shouldReplaceWithOwnerStat(creature, stat) {
var _a, _b;
const groupInfo = getGroupInfo(creature);
return (_b = (_a = groupInfo === null || groupInfo === void 0 ? void 0 : groupInfo.ownerStats) === null || _a === void 0 ? void 0 : _a.includes(stat)) !== null && _b !== void 0 ? _b : false;
}
/**
*
* @param creature
* @param inventoryLookup
*/
export function getInfusionItem(creature, inventoryLookup) {
const infusion = getInfusion(creature);
if (infusion) {
return HelperUtils.lookupDataOrFallback(inventoryLookup, InfusionAccessors.getInventoryMappingId(infusion));
}
return null;
}
/**
*
* @param creature
* @param statId
*/
export function getStatInfo(creature, statId) {
return HelperUtils.lookupDataOrFallback(creature.statLookup, statId);
}
/**
*
* @param creature
* @param skillId
*/
export function getSkill(creature, skillId) {
return HelperUtils.lookupDataOrFallback(creature.skillLookup, skillId);
}
/**
*
* @param flagKey
* @param creature
*/
export function hasFlag(flagKey, creature) {
const groupInfo = getGroupInfo(creature);
if (groupInfo !== null) {
return Boolean(HelperUtils.lookupDataOrFallback(groupInfo.flagInfoLookup, flagKey));
}
return false;
}
/**
*
* @param creature
*/
export function canUseLairActions(creature) {
return !hasFlag(CreatureGroupFlagEnum.CANNOT_USE_LAIR_ACTIONS, creature);
}
/**
*
* @param creature
*/
export function canUseLegendaryActions(creature) {
return !hasFlag(CreatureGroupFlagEnum.CANNOT_USE_LEGENDARY_ACTIONS, creature);
}
export function getAbilities(creature) {
const stats = getStats(creature);
const savingThrows = getSavingThrows(creature);
const abilities = stats.map((stat) => {
var _a, _b;
const { id, modifier, score, statKey } = stat;
const saveModifier = (_b = (_a = savingThrows.find((save) => save.statId === id)) === null || _a === void 0 ? void 0 : _a.modifier) !== null && _b !== void 0 ? _b : modifier;
return {
id,
modifier: modifier !== null && modifier !== void 0 ? modifier : 0,
score: score !== null && score !== void 0 ? score : 0,
statKey: statKey !== null && statKey !== void 0 ? statKey : '',
saveModifier: saveModifier !== null && saveModifier !== void 0 ? saveModifier : 0,
};
});
return orderBy(abilities, 'id');
}