New source found from dndbeyond.com

This commit is contained in:
2026-07-08 01:00:09 -07:00
parent 9a983a6d7b
commit dcefa0d2f2
2865 changed files with 222467 additions and 49053 deletions
@@ -1,4 +1,3 @@
import { PartyInventorySharingStateEnum } from './constants';
/**
*
* @param campaign
@@ -75,10 +74,10 @@ export function getPartyBaseInventoryContracts(partyInfo) {
/**
*
* @param partyInfo
* @return {Array<PartyInventoryRestrictionContract>}
*/
export function getSharingState(partyInfo) {
var _a;
return (_a = partyInfo.sharingState) !== null && _a !== void 0 ? _a : PartyInventorySharingStateEnum.OFF;
export function getPartyInventoryRestrictions(partyInfo) {
return partyInfo.partyRestrictions;
}
/**
*
@@ -1,6 +1,5 @@
export var PartyInventorySharingStateEnum;
(function (PartyInventorySharingStateEnum) {
PartyInventorySharingStateEnum[PartyInventorySharingStateEnum["OFF"] = 0] = "OFF";
PartyInventorySharingStateEnum[PartyInventorySharingStateEnum["ON"] = 1] = "ON";
PartyInventorySharingStateEnum[PartyInventorySharingStateEnum["DELETE_ONLY"] = 2] = "DELETE_ONLY";
})(PartyInventorySharingStateEnum || (PartyInventorySharingStateEnum = {}));
export var PartyRestrictionTypeEnum;
(function (PartyRestrictionTypeEnum) {
PartyRestrictionTypeEnum[PartyRestrictionTypeEnum["INFUSION"] = 0] = "INFUSION";
PartyRestrictionTypeEnum[PartyRestrictionTypeEnum["REPLICATED"] = 1] = "REPLICATED";
})(PartyRestrictionTypeEnum || (PartyRestrictionTypeEnum = {}));
@@ -1,3 +1,4 @@
import { CampaignAccessors } from '../Campaign';
import { ItemGenerators } from '../Item';
import { getPartyBaseInventoryContracts } from './accessors';
/**
@@ -11,6 +12,6 @@ import { getPartyBaseInventoryContracts } from './accessors';
*/
export function generateBasePartyInventory(partyInfo, modifierLookup, spellLookup, valueLookup, inventoryInfusionLookup, ruleData) {
return partyInfo
? ItemGenerators.generateBaseItems(getPartyBaseInventoryContracts(partyInfo), modifierLookup, spellLookup, valueLookup, inventoryInfusionLookup, ruleData)
? ItemGenerators.generateBaseItems(getPartyBaseInventoryContracts(partyInfo), modifierLookup, spellLookup, valueLookup, inventoryInfusionLookup, ruleData, CampaignAccessors.getPartyInventoryRestrictions(partyInfo))
: [];
}
@@ -1,23 +1,4 @@
import { getCharacters } from './accessors';
import { PartyInventorySharingStateEnum } from './constants';
/**
*
* @param sharingState
* @returns {Boolean}
* @description Returns true as long as the sharing state is not OFF. WARNING: DELETE_ONLY overlaps with the inactive sharing state
*/
export function isSharingStateActive(sharingState) {
return sharingState !== PartyInventorySharingStateEnum.OFF;
}
/**
*
* @param sharingState
* @returns {Boolean}
* @description Returns true as long as the sharing state is not ON. WARNING: DELETE_ONLY overlaps with the active sharing state
*/
export function isSharingStateInactive(sharingState) {
return sharingState !== PartyInventorySharingStateEnum.ON;
}
/**
*
* @param campaign
@@ -1,4 +1,4 @@
import { MovementTypeEnum, PreferenceAbilityScoreDisplayTypeEnum, PreferenceEncumbranceTypeEnum, PreferenceHitPointTypeEnum, PreferencePrivacyTypeEnum, PreferenceProgressionTypeEnum, PreferenceSharingTypeEnum, SenseTypeEnum, } from '../../Core';
import { MovementTypeEnum, PreferenceAbilityScoreDisplayTypeEnum, PreferenceEncumbranceTypeEnum, PreferenceHitPointTypeEnum, PreferenceLongRestTypeEnum, PreferencePrivacyTypeEnum, PreferenceProgressionTypeEnum, PreferenceSharingTypeEnum, SenseTypeEnum, } from '../../Core';
/**
*
* @param race
@@ -56,6 +56,7 @@ export function generateCharacterPreferences(preferencesContract, featureFlagInf
enableDarkMode: false,
useHomebrewContent: true,
enableContainerCurrency: false,
longRestType: PreferenceLongRestTypeEnum.HALF,
};
}
/**
@@ -24,6 +24,8 @@ export function getPreferenceKey(preKey) {
return preKey;
case 'ignoreCoinWeight':
return preKey;
case 'longRestType':
return preKey;
case 'primaryMovement':
return preKey;
case 'primarySense':
@@ -121,3 +121,6 @@ export function getTagConstraints(choice) {
var _a;
return (_a = choice.tagConstraints) !== null && _a !== void 0 ? _a : [];
}
export function getItemDefinitionKey(choice) {
return choice.itemDefinitionKey;
}
@@ -1,6 +1,5 @@
import { orderBy } from 'lodash';
import { TypeScriptUtils } from "../../utils";
import { ChoiceAccessors } from '.';
import { ClassAccessors } from '../Class';
import { AbilityStatEnum, BuilderChoiceSubtypeEnum, BuilderChoiceTypeEnum, } from '../Core';
import { DataOriginTypeEnum } from '../DataOrigin';
@@ -12,7 +11,7 @@ import { PrerequisiteValidators } from '../Prerequisite';
import { RuleDataAccessors } from '../RuleData';
import { SourceUtils } from '../Source';
import { SpellUtils } from '../Spell';
import { getDefaultSubtypes, getOptions, getOptionValue, isOptional } from './accessors';
import { getDefaultSubtypes, getItemDefinitionKey, getOptions, getOptionValue, getTagConstraints, getType, isOptional, } from './accessors';
export function isOnlyDefaultSelected(choice) {
const defaultSubtypes = getDefaultSubtypes(choice);
if (defaultSubtypes.length !== 1) {
@@ -71,15 +70,17 @@ export function getSortedChoiceOptionsForFeatsInfo(featId, choice, ruleData, ent
//used in FeatureChoice for all choices
// extracted from FeatureChoice.tsx
// TODO needs to be broken down into smaller utils and simplified
export function getSortedChoiceOptionsForFeaturesInfo(choice, fetchedFeats, featLookup, charClass, fetchedSubclasses, characterPreferences, prerequisiteData, ruleData, entityRestrictionData) {
var _a, _b;
export function getSortedChoiceOptionsForFeaturesInfo(choice, fetchedFeats, featLookup, charClass, fetchedSubclasses, itemShoppe, characterPreferences, prerequisiteData, ruleData, entityRestrictionData) {
var _a, _b, _c, _d;
let description;
let introDescription;
let availableOptions;
let featSubChoices;
const optionValue = ChoiceAccessors.getOptionValue(choice);
const options = ChoiceAccessors.getOptions(choice);
const type = ChoiceAccessors.getType(choice);
const tagConstraints = ChoiceAccessors.getTagConstraints(choice);
const optionValue = getOptionValue(choice);
const options = getOptions(choice);
const type = getType(choice);
const tagConstraints = getTagConstraints(choice);
const itemDefinitionKey = getItemDefinitionKey(choice);
switch (type) {
case BuilderChoiceTypeEnum.FEAT_CHOICE_OPTION:
const availableFeats = getAvailableFeatChoices(optionValue, fetchedFeats, featLookup);
@@ -153,12 +154,12 @@ export function getSortedChoiceOptionsForFeaturesInfo(choice, fetchedFeats, feat
.filter(TypeScriptUtils.isNotNullOrUndefined)
: [];
sources.forEach((source) => {
var _a, _b;
var _a;
if ((_a = source.sourceCategory) === null || _a === void 0 ? void 0 : _a.isToggleable) {
description += source.sourceCategory.description ? source.sourceCategory.description : '';
}
description += (_b = chosenSubclass.description) !== null && _b !== void 0 ? _b : '';
});
description += (_b = chosenSubclass.description) !== null && _b !== void 0 ? _b : '';
}
break;
case BuilderChoiceTypeEnum.ENTITY_SPELL_OPTION:
@@ -168,17 +169,39 @@ export function getSortedChoiceOptionsForFeaturesInfo(choice, fetchedFeats, feat
// If there is a chosen spell, set detailChoiceDesc to its description.
const chosenSpell = spellOptions.find((spell) => spell.id === optionValue);
if (chosenSpell) {
description = (_b = chosenSpell.description) !== null && _b !== void 0 ? _b : '';
description = (_c = chosenSpell.description) !== null && _c !== void 0 ? _c : '';
}
break;
default:
availableOptions = options.map((option) => (Object.assign(Object.assign({}, option), { value: option.id })));
// If every option in the array has a null sourceId, ignore sorting by sourceId.
// If any option has a non-null sourceId, sort by sourceId.
const shouldSortBySourceId = options.some((option) => option.hasOwnProperty('sourceId') && option.sourceId !== null);
if (shouldSortBySourceId) {
const optionsToGroup = SourceUtils.getSimpleSourcedDefinitionContracts(options);
availableOptions = SourceUtils.getGroupedOptionsBySourceCategory(optionsToGroup, ruleData, optionValue, entityRestrictionData);
const chosenOption = optionsToGroup.find((option) => option.id === optionValue);
if (chosenOption) {
description = (_d = chosenOption.description) !== null && _d !== void 0 ? _d : '';
}
}
else {
availableOptions = options.map((option) => (Object.assign(Object.assign({}, option), { value: option.id })));
}
}
if (itemDefinitionKey !== null && optionValue !== null) {
const item = itemShoppe === null || itemShoppe === void 0 ? void 0 : itemShoppe.getInventoryItems().items.find((item) => item.getDefinitionKey() === itemDefinitionKey);
//If there is a chosen item mapping and it exists in the item shoppe, set the choice description to the item's description. and return the intro text to display as well.
if (item) {
description = item.getDescription() || '';
introDescription = item.getIntroText();
}
}
return {
choice,
options: availableOptions,
featSubChoices,
description,
introDescription,
};
}
// filter Choice options based on modifiers and default subtypes that identify when a user has made a choice from another source. We filter those options out or we append the source data origin name next to the option label
@@ -388,6 +388,9 @@ export function getEnablesPactWeapon(charClass) {
export function getEnablesDedicatedWeapon(charClass) {
return charClass.enablesDedicatedWeapon;
}
export function getEnablesReplicateMagicItem(charClass) {
return charClass.enablesReplicateMagicItem;
}
/**
*
* @param charClass
@@ -7,7 +7,7 @@ import { HelperUtils } from '../Helper';
import { ModifierAccessors, ModifierValidators } from '../Modifier';
import { OptionalClassFeatureAccessors } from '../OptionalClassFeature';
import { DefaultSpellCastingLearningStyle, SpellDerivers } from '../Spell';
import { getActiveId, getDefinitionClassFeatures, getDefinitionSpellcastingStatId, getId, getLevel, getMappingId, getSubclass, getClassFeatures, getDefinitionSpellCastingLearningStyle, } from './accessors';
import { getActiveId, getDefinitionClassFeatures, getDefinitionSpellcastingStatId, getId, getLevel, getMappingId, getSubclass, getClassFeatures, getDefinitionSpellCastingLearningStyle, getEnablesReplicateMagicItem, } from './accessors';
/**
*
* @param charClass
@@ -183,10 +183,11 @@ export function deriveReplacementWeaponAbilityStats(classModifiers) {
*
* @param classFeatures
*/
export function deriveDedicatedHexAndPactWeaponEnabled(classFeatures, classModifiers) {
export function deriveFeaturesEnabled(classFeatures, classModifiers) {
let enablesHexWeapon = false;
let enablesPactWeapon = false;
let enablesDedicatedWeapon = false;
let enablesReplicateMagicItem = false;
classModifiers.forEach((modifier) => {
if (!enablesPactWeapon && ModifierValidators.isEnablePactWeaponModifier(modifier)) {
enablesPactWeapon = true;
@@ -196,6 +197,10 @@ export function deriveDedicatedHexAndPactWeaponEnabled(classFeatures, classModif
enablesHexWeapon = true;
return;
}
if (!enablesReplicateMagicItem && ModifierValidators.isEnableReplicateMagicItemModifier(modifier)) {
enablesReplicateMagicItem = true;
return;
}
});
//TODO remove this once we have dedicated weapon driven by modifiers
classFeatures.forEach((feature) => {
@@ -207,6 +212,7 @@ export function deriveDedicatedHexAndPactWeaponEnabled(classFeatures, classModif
enablesHexWeapon,
enablesPactWeapon,
enablesDedicatedWeapon,
enablesReplicateMagicItem,
};
}
/**
@@ -310,3 +316,20 @@ export function deriveMaxInfusions(charClass) {
}
return null;
}
//Derives the maximum number of replicated magic items based on if the class enables the replicate magic item feature and if any of its class features have item mappings.
// It sums up the level scale fixed values and returns the total as the maximum number of replicated magic items.
export function deriveMaxReplicatedMagicItems(charClass) {
const enablesReplicateMagicItem = getEnablesReplicateMagicItem(charClass);
const features = getClassFeatures(charClass);
const replicateFeatures = features.filter((classFeature) => ClassFeatureAccessors.getHasItemMappings(classFeature));
if (enablesReplicateMagicItem) {
let maxCount = 0;
replicateFeatures.forEach((replicateFeature) => {
var _a, _b;
const levelScale = (_b = (_a = ClassFeatureAccessors.getLevelScale(replicateFeature)) === null || _a === void 0 ? void 0 : _a.fixedValue) !== null && _b !== void 0 ? _b : 0;
maxCount += levelScale;
});
return maxCount;
}
return null;
}
@@ -9,7 +9,7 @@ import { ModifierDerivers, ModifierValidators } from '../Modifier';
import { OptionAccessors } from '../Option';
import { SpellAccessors, SpellDerivers, SpellGenerators, } from '../Spell';
import { getActiveId, getBaseClassSpells, getClassFeatures, getDefinitionClassFeatures, getEnablesDedicatedWeapon, getEnablesHexWeapon, getEnablesPactWeapon, getId, getLevel, getMappingId, getName, getReplacementWeaponAbilityStats, getSlug, getSpellPrepareType, getSpellRules, getSpells, getSubclass, isPactMagicActive, isSpellcastingActive, isStartingClass, } from './accessors';
import { deriveActiveId, deriveClassFeatureGroups, deriveConsolidatedClassFeatures, deriveDedicatedHexAndPactWeaponEnabled, deriveIsPactMagicActive, deriveIsSpellcastingActive, deriveReplacementWeaponAbilityStats, deriveSpellCastingLearningStyle, deriveSpellListIds, deriveSpellRules, deriveSpells, deriveUniqueKey, } from './derivers';
import { deriveActiveId, deriveClassFeatureGroups, deriveConsolidatedClassFeatures, deriveFeaturesEnabled, deriveIsPactMagicActive, deriveIsSpellcastingActive, deriveReplacementWeaponAbilityStats, deriveSpellCastingLearningStyle, deriveSpellListIds, deriveSpellRules, deriveSpells, deriveUniqueKey, } from './derivers';
export function generateBaseCharClasses(charClasses, optionalClassFeatures, allClassSpells, allClassAlwaysPreparedSpells, allClassAlwaysKnownSpells, appContext, ruleData, classesLookupData, definitionPool, characterPreferences, characterId, choiceComponents, baseFeats) {
const orderedClasses = orderBy(charClasses, [(charClass) => isStartingClass(charClass), (charClass) => getName(charClass)], ['desc', 'asc']);
const hack__baseCharClasses = orderedClasses.map((charClass) => hack__generateHackBaseCharClass(charClass, optionalClassFeatures, ruleData, classesLookupData, characterPreferences.enableOptionalClassFeatures));
@@ -65,12 +65,13 @@ export function generateBaseCharClass(charClass, optionalClassFeatures, allClass
const { activeFeatures, visibleFeatures, orderedFeatures, uniqueFeatures, higherLevelFeatures } = deriveClassFeatureGroups(charClass, updatedFeatures, appContext);
// do any class features or modifiers enable hex, pact or dedicated weapons
//TODO eventually should just be able to use modifiers here and not have to check class feature names
const { enablesHexWeapon, enablesPactWeapon, enablesDedicatedWeapon } = deriveDedicatedHexAndPactWeaponEnabled(updatedFeatures, classModifiers);
const { enablesHexWeapon, enablesPactWeapon, enablesDedicatedWeapon, enablesReplicateMagicItem } = deriveFeaturesEnabled(updatedFeatures, classModifiers);
return Object.assign(Object.assign({}, charClass), { activeId: deriveActiveId(charClass), spells: SpellGenerators.updateClassSpells(featureSpells, classSpells), modifiers: classModifiers, featureSpells, classFeatures: updatedFeatures, optionalClassFeatures, activeClassFeatures: activeFeatures, visibleClassFeatures: visibleFeatures, orderedClassFeatures: orderedFeatures, uniqueClassFeatures: uniqueFeatures, higherLevelClassFeatures: higherLevelFeatures, feats,
actions,
enablesDedicatedWeapon,
enablesHexWeapon,
enablesPactWeapon, slug: FormatUtils.cobaltSlugify(getName(charClass)), spellListIds: deriveSpellListIds(updatedFeatures, getLevel(charClass)), spellCastingLearningStyle: deriveSpellCastingLearningStyle(charClass), replacementWeaponAbilityStats: deriveReplacementWeaponAbilityStats(classModifiers) });
enablesPactWeapon,
enablesReplicateMagicItem, slug: FormatUtils.cobaltSlugify(getName(charClass)), spellListIds: deriveSpellListIds(updatedFeatures, getLevel(charClass)), spellCastingLearningStyle: deriveSpellCastingLearningStyle(charClass), replacementWeaponAbilityStats: deriveReplacementWeaponAbilityStats(classModifiers) });
}
export function generateClassFeatureLookup(baseCharClasses) {
const lookup = {};
@@ -416,6 +416,9 @@ export function getInfusionRules(feature) {
var _a, _b;
return (_b = (_a = getDefinition(feature)) === null || _a === void 0 ? void 0 : _a.infusionRules) !== null && _b !== void 0 ? _b : [];
}
export function getItemPlans(feature) {
return feature.itemPlans;
}
/**
*
* @param feature
@@ -427,3 +430,7 @@ export function getFeatListContracts(featureContract) {
var _a, _b;
return (_b = (_a = getDefinition(featureContract)) === null || _a === void 0 ? void 0 : _a.grantedFeats) !== null && _b !== void 0 ? _b : [];
}
export function getHasItemMappings(feature) {
var _a, _b;
return (_b = (_a = getDefinition(feature)) === null || _a === void 0 ? void 0 : _a.hasItemMappings) !== null && _b !== void 0 ? _b : false;
}
@@ -7,10 +7,11 @@ import { DefinitionPoolUtils } from '../DefinitionPool';
import { FeatGenerators } from '../Feat';
import { FeatList } from '../FeatList';
import { InfusionChoiceGenerators } from '../InfusionChoice';
import { ItemPlanGenerators } from '../ItemPlan';
import { ModifierGenerators } from '../Modifier';
import { OptionAccessors, OptionGenerators } from '../Option';
import { SpellGenerators } from '../Spell';
import { getCreatureRules, getDefinitionKey, getEntityTypeId, getFeatListContracts, getId, getInfusionRules, getOptions, getUniqueKey, } from './accessors';
import { getCreatureRules, getDefinitionKey, getEntityTypeId, getFeatListContracts, getHasItemMappings, getId, getInfusionRules, getOptions, getUniqueKey, } from './accessors';
export function generateClassFeature(charClass, classFeature, ruleData, classesLookupData, definitionPool, characterId, choiceComponents, baseFeats) {
const id = getId(classFeature);
const entityTypeId = getEntityTypeId(classFeature);
@@ -22,6 +23,9 @@ export function generateClassFeature(charClass, classFeature, ruleData, classesL
const feats = FeatGenerators.generateDataOriginFeats(id, entityTypeId, featLookup, DataOriginTypeEnum.CLASS_FEATURE, classFeature, charClass);
const options = generateClassFeatureOptions(classFeature, charClass, featLookup, actionLookup, spellLookup, optionLookup, modifierLookup, valueLookup, spellListDataOriginLookup, ruleData);
const infusionChoices = InfusionChoiceGenerators.generateInfusionChoices(getInfusionRules(classFeature), DataOriginTypeEnum.CLASS_FEATURE, classFeature, charClass, infusionChoiceInfusionLookup, knownInfusionLookupByChoiceKey, characterId);
const itemPlans = getHasItemMappings(classFeature)
? ItemPlanGenerators.generateItemPlans(choices, options, DataOriginTypeEnum.CLASS_FEATURE, classFeature, charClass)
: [];
const featLists = getFeatListContracts(classFeature).map((contract) => new FeatList(contract, choiceComponents.definitionKeyNameMap, baseFeats));
return Object.assign(Object.assign({}, classFeature), { actions,
choices,
@@ -29,7 +33,8 @@ export function generateClassFeature(charClass, classFeature, ruleData, classesL
modifiers,
spells,
options,
infusionChoices, accessType: DefinitionPoolUtils.getDefinitionAccessType(getDefinitionKey(classFeature), definitionPool), featLists });
infusionChoices,
itemPlans, accessType: DefinitionPoolUtils.getDefinitionAccessType(getDefinitionKey(classFeature), definitionPool), featLists });
}
/**
*
@@ -31,7 +31,7 @@ classes, choiceComponents, baseFeats) {
const featLists = choiceComponents && baseFeats
? getFeatListContracts(classFeatureMapping).map((contract) => new FeatList(contract, choiceComponents.definitionKeyNameMap, baseFeats))
: [];
return Object.assign(Object.assign({}, classFeatureMapping), { actions: [], choices: [], feats: [], modifiers: [], options: [], spells: [], infusionChoices: [], accessType: DefinitionPoolUtils.getDefinitionAccessType(definitionKey, definitionPool), featLists });
return Object.assign(Object.assign({}, classFeatureMapping), { actions: [], choices: [], feats: [], modifiers: [], options: [], spells: [], infusionChoices: [], accessType: DefinitionPoolUtils.getDefinitionAccessType(definitionKey, definitionPool), featLists, itemPlans: [] });
}
/**
*
@@ -1,9 +1,8 @@
import { keyBy, sortBy } from 'lodash';
import { ConfigUtils } from '../../config';
import { CampaignAccessors, CampaignUtils } from '../Campaign';
import { CampaignAccessors } from '../Campaign';
import { generateCoinWeight } from '../Character/generators';
import { DefinitionHacks } from '../Definition';
import { FeatureFlagEnum, FeatureFlagInfoUtils } from '../FeatureFlagInfo';
import { ItemAccessors, ItemDerivers, ItemValidators } from '../Item';
import { getDefinitionKey, getName, isShared } from './accessors';
import { ContainerTypeEnum } from './constants';
@@ -23,18 +22,12 @@ function generateInitialCoins() {
* @param characterId
* @param partyInfo
* @param partyInventory
* @param featureFlagInfo
* @param characterCoin
* @param preferences
* @param ruleData
*/
export function generateContainers(items, customItems, characterId, partyInfo, partyInventory, featureFlagInfo, characterCoin, preferences, ruleData) {
let sharingStateActive = false;
if (partyInfo && CampaignUtils.isSharingStateActive(CampaignAccessors.getSharingState(partyInfo))) {
sharingStateActive = true;
}
const partyInventoryActive = FeatureFlagInfoUtils.getFeatureFlagInfoValue(FeatureFlagEnum.RELEASE_GATE_IMS, featureFlagInfo) &&
sharingStateActive;
export function generateContainers(items, customItems, characterId, partyInfo, partyInventory, characterCoin, preferences, ruleData) {
const partyInventoryActive = partyInfo !== null;
const rulesEngineConfig = ConfigUtils.getCurrentRulesEngineConfig();
// Do we want to display Cointainers? You betcha!
const canCointainer = (preferences === null || preferences === void 0 ? void 0 : preferences.enableContainerCurrency) && (rulesEngineConfig === null || rulesEngineConfig === void 0 ? void 0 : rulesEngineConfig.canUseCurrencyContainers);
@@ -64,8 +57,9 @@ export function generateContainers(items, customItems, characterId, partyInfo, p
});
}
const playerContainers = sortBy(itemContainers, (container) => getName(container));
const sortedPartyContainers = sortBy(partyContainers, (container) => getName(container));
return partyInventoryActive && partyEquipmentContainer
? [equipmentContainer, ...playerContainers, partyEquipmentContainer, ...partyContainers]
? [equipmentContainer, ...playerContainers, partyEquipmentContainer, ...sortedPartyContainers]
: [equipmentContainer, ...playerContainers];
}
/**
@@ -1,7 +1,5 @@
import { ContainerAccessors } from '.';
import { PartyInventorySharingStateEnum } from '../Campaign';
import { ItemAccessors } from '../Item';
import { getDefinitionKey, getItemMappingIds, getName } from './accessors';
import { getDefinitionKey, getItemMappingIds, getName, isShared } from './accessors';
import { ContainerTypeEnum } from './constants';
/**
*
@@ -51,14 +49,14 @@ export function getInventoryItems(container, inventory) {
* @param containers
* @returns {Array<MenuOption>}
*/
export function getGroupedOptions(currentContainerDefinitionKey, containers, label, sharingState) {
export function getGroupedOptions(currentContainerDefinitionKey, containers, label) {
const excludedKeys = [];
if (currentContainerDefinitionKey) {
excludedKeys.push(currentContainerDefinitionKey);
}
const availableContainers = getAvailableContainers(containers, excludedKeys);
const characterContainers = availableContainers.filter((container) => !ContainerAccessors.isShared(container));
const partyContainers = availableContainers.filter(ContainerAccessors.isShared);
const characterContainers = availableContainers.filter((container) => !isShared(container));
const partyContainers = availableContainers.filter(isShared);
const options = [];
if (characterContainers.length) {
options.push({
@@ -69,9 +67,8 @@ export function getGroupedOptions(currentContainerDefinitionKey, containers, lab
})),
});
}
// Only display Party inventory if there are containers and the sharing state is turned to on
// ( e.g. hide these containers as options when OFF and in DELETE_ONLY )
if (partyContainers.length && sharingState === PartyInventorySharingStateEnum.ON) {
// Only display Party inventory if there are containers
if (partyContainers.length) {
options.push({
label: `${!characterContainers.length ? `${label} ` : ''}Party Inventory`,
options: partyContainers.map((container) => ({
@@ -160,6 +160,11 @@ export var PreferenceProgressionTypeEnum;
PreferenceProgressionTypeEnum[PreferenceProgressionTypeEnum["MILESTONE"] = 1] = "MILESTONE";
PreferenceProgressionTypeEnum[PreferenceProgressionTypeEnum["XP"] = 2] = "XP";
})(PreferenceProgressionTypeEnum || (PreferenceProgressionTypeEnum = {}));
export var PreferenceLongRestTypeEnum;
(function (PreferenceLongRestTypeEnum) {
PreferenceLongRestTypeEnum[PreferenceLongRestTypeEnum["HALF"] = 1] = "HALF";
PreferenceLongRestTypeEnum[PreferenceLongRestTypeEnum["FULL"] = 2] = "FULL";
})(PreferenceLongRestTypeEnum || (PreferenceLongRestTypeEnum = {}));
export var SpeedMovementKeyEnum;
(function (SpeedMovementKeyEnum) {
SpeedMovementKeyEnum["WALK"] = "walk";
@@ -1,27 +1,16 @@
export var FeatureFlagEnum;
(function (FeatureFlagEnum) {
// Brian added this in 06/2021 expected to be removed in 10/2021
FeatureFlagEnum["RELEASE_GATE_IMS"] = "release-gate-ims";
// Julie added this on 4/19/22 expected to be removed in ?? TODO
FeatureFlagEnum["RELEASE_GATE_GFS_BLESSINGS_UI"] = "release-gate-gfs-blessings-ui";
// Brian added this on 10/24/22 expected to remove in 11/2022
FeatureFlagEnum["RELEASE_GATE_CAMPAIGN_SETTINGS"] = "release-gate-character-sheet-campaign-settings";
// Tim added this on 02/23/23 expected to remove in ??
FeatureFlagEnum["RELEASE_GATE_CHARACTER_SHEET_TOUR"] = "release-gate-character-sheet-tour";
// Brittany added this on 2/24/2023
FeatureFlagEnum["RELEASE_GATE_PREMADE_CHARACTERS"] = "release-gate-premade-characters";
})(FeatureFlagEnum || (FeatureFlagEnum = {}));
export const FEATURE_FLAG_LIST = [
FeatureFlagEnum.RELEASE_GATE_IMS,
FeatureFlagEnum.RELEASE_GATE_GFS_BLESSINGS_UI,
FeatureFlagEnum.RELEASE_GATE_CAMPAIGN_SETTINGS,
FeatureFlagEnum.RELEASE_GATE_CHARACTER_SHEET_TOUR,
FeatureFlagEnum.RELEASE_GATE_PREMADE_CHARACTERS,
];
export const DEFAULT_FEATURE_FLAG_INFO = {
[FeatureFlagEnum.RELEASE_GATE_IMS]: false,
[FeatureFlagEnum.RELEASE_GATE_GFS_BLESSINGS_UI]: false,
[FeatureFlagEnum.RELEASE_GATE_CAMPAIGN_SETTINGS]: false,
[FeatureFlagEnum.RELEASE_GATE_CHARACTER_SHEET_TOUR]: false,
[FeatureFlagEnum.RELEASE_GATE_PREMADE_CHARACTERS]: false,
};
@@ -51,6 +51,27 @@ export function getDefinitionEntityTypeId(item) {
var _a, _b;
return (_b = (_a = item.definition) === null || _a === void 0 ? void 0 : _a.entityTypeId) !== null && _b !== void 0 ? _b : -1;
}
/**
*
* @param item
*/
export function getOriginEntityId(item) {
return item.originEntityId;
}
/**
*
* @param item
*/
export function getOriginEntityTypeId(item) {
return item.originEntityTypeId;
}
/**
*
* @param item
*/
export function getOriginDefinitionKey(item) {
return item.originDefinitionKey;
}
/**
*
* @param item
@@ -1046,3 +1067,6 @@ export function getReplacementWeaponStats(item) {
export function getAppliedWeaponReplacementStats(item) {
return item.appliedWeaponReplacementStats;
}
export function getPartyInventoryRestrictions(item) {
return item.partyInventoryRestrictions;
}
@@ -987,3 +987,8 @@ export function deriveSecondarySourceCategoryIds(item, ruleData) {
return ((_a = sourceData === null || sourceData === void 0 ? void 0 : sourceData.sourceCategory) === null || _a === void 0 ? void 0 : _a.id) || 0;
});
}
export function derivePartyInventoryRestrictions(item, partyInventoryRestrictions) {
return partyInventoryRestrictions.filter((restriction) => {
return restriction.inventoryMappingId === getMappingId(item) && restriction.itemId === getDefinitionId(item);
});
}
@@ -24,9 +24,9 @@ import { ModifierDerivers, ModifierGenerators, ModifierValidators, } from '../Mo
import { RuleDataAccessors } from '../RuleData';
import { SpellGenerators } from '../Spell';
import { AdjustmentTypeEnum, ValueAccessors, ValueHacks, ValueUtils, } from '../Value';
import { getDefinitionDamage, getEntityTypeId, getFixedDamage, getId, getItemWeaponBehaviors, getLimitedUse, getMappingEntityTypeId, getMappingId, getModifiers, getName, getUniqueKey, isAttuned, isDisplayAsAttack, isEquipped, } from './accessors';
import { getDefinitionDamage, getEntityTypeId, getFixedDamage, getId, getItemWeaponBehaviors, getLimitedUse, getMappingEntityTypeId, getMappingId, getModifiers, getName, getOriginDefinitionKey, getUniqueKey, isAttuned, isDisplayAsAttack, isEquipped, } from './accessors';
import { ItemBaseTypeEnum, ItemRarityNameEnum, WeaponPropertyEnum } from './constants';
import { deriveArmorClass, deriveAvailableWeaponAbilities, deriveAvatarUrl, deriveBaseType, deriveCanAttune, deriveCanBeDedicatedWeapon, deriveCanEquip, deriveCanHexWeapon, deriveCanWeaponOffhand, deriveCapacityWeight, deriveCategoryInfo, deriveCost, deriveDamageType, deriveDefinitionKey, deriveInfusionActions, deriveIsAdamantine, deriveIsCustomized, deriveIsDisplayAsAttack, deriveIsMagic, deriveIsMonkWeapon, deriveIsOffhand, deriveIsProficient, deriveIsSilvered, deriveLimitedUse, deriveMasteryName, deriveName, deriveNotes, deriveOriginalCustomContract, derivePrimarySourceCategoryId, deriveProperties, deriveSecondarySourceCategoryIds, deriveStealthCheck, deriveType, deriveValidGlobalModifiersFromArmor, deriveValidGlobalModifiersFromGear, deriveValidGlobalModifiersFromWeapons, deriveWeaponAdditionalDamage, deriveWeaponReach, deriveWeight, } from './derivers';
import { deriveArmorClass, deriveAvailableWeaponAbilities, deriveAvatarUrl, deriveBaseType, deriveCanAttune, deriveCanBeDedicatedWeapon, deriveCanEquip, deriveCanHexWeapon, deriveCanWeaponOffhand, deriveCapacityWeight, deriveCategoryInfo, deriveCost, deriveDamageType, deriveDefinitionKey, deriveInfusionActions, deriveIsAdamantine, deriveIsCustomized, deriveIsDisplayAsAttack, deriveIsMagic, deriveIsMonkWeapon, deriveIsOffhand, deriveIsProficient, deriveIsSilvered, deriveLimitedUse, deriveMasteryName, deriveName, deriveNotes, deriveOriginalCustomContract, derivePartyInventoryRestrictions, derivePrimarySourceCategoryId, deriveProperties, deriveSecondarySourceCategoryIds, deriveStealthCheck, deriveType, deriveValidGlobalModifiersFromArmor, deriveValidGlobalModifiersFromGear, deriveValidGlobalModifiersFromWeapons, deriveWeaponAdditionalDamage, deriveWeaponReach, deriveWeight, } from './derivers';
import { hasItemWeaponBehaviors, hasWeaponProperty, isAmmunition, isArmorContract, isBaseWeapon, isGearContract, isWeaponContract, } from './utils';
import { isCustomItem, isEquippedToCurrentCharacter, validateIsWeaponLike } from './validators';
/**
@@ -47,7 +47,7 @@ export function generateCustomItems(customItems, ruleData, characterId) {
export function generateCustomItem(customItem, ruleData, characterId) {
var _a, _b;
const { id, quantity, notes, weight } = customItem, customItemData = __rest(customItem, ["id", "quantity", "notes", "weight"]);
const definition = Object.assign(Object.assign({}, customItemData), { armorTypeId: null, armorClass: null, attackType: null, attunementDescription: null, avatarUrl: RuleDataAccessors.getDefaultGearImageUrl(ruleData), baseArmorName: null, baseItemId: null, baseTypeId: -1, bundleSize: 1, canAttune: false, canBeAddedToInventory: false, canEquip: false, capacity: null, capacityWeight: 0, categoryId: null, damage: null, damageType: null, entityTypeId: -1, filterType: null, fixedDamage: null, gearTypeId: null, grantedModifiers: [], groupedId: null, id: -1, isConsumable: false, isContainer: false, isHomebrew: false, isLegacy: false, isMonkWeapon: false, isPack: false, largeAvatarUrl: null, levelInfusionGranted: null, longRange: null, magic: false, properties: [], range: null, rarity: ItemRarityNameEnum.COMMON, snippet: null, sourcePageNumber: null, sources: [], stackable: true, stealthCheck: StealthCheckTypeEnum.NONE, strengthRequirement: null, subType: null, tags: [], type: 'Custom', version: null, weaponBehaviors: [], weight: weight !== null && weight !== void 0 ? weight : 0, weightMultiplier: 1 });
const definition = Object.assign(Object.assign({}, customItemData), { armorTypeId: null, armorClass: null, attackType: null, attunementDescription: null, avatarUrl: RuleDataAccessors.getDefaultGearImageUrl(ruleData), baseArmorName: null, baseItemId: null, baseTypeId: -1, bundleSize: 1, canAttune: false, canBeAddedToInventory: false, canEquip: false, capacity: null, capacityWeight: 0, categoryId: null, damage: null, damageType: null, definitionKey: '-1:-1', entityTypeId: -1, filterType: null, fixedDamage: null, gearTypeId: null, grantedModifiers: [], groupedId: null, id: -1, isConsumable: false, isContainer: false, isHomebrew: false, isLegacy: false, isMonkWeapon: false, isPack: false, largeAvatarUrl: null, levelInfusionGranted: null, longRange: null, magic: false, properties: [], range: null, rarity: ItemRarityNameEnum.COMMON, snippet: null, sourcePageNumber: null, sources: [], stackable: true, stealthCheck: StealthCheckTypeEnum.NONE, strengthRequirement: null, subType: null, tags: [], type: 'Custom', version: null, weaponBehaviors: [], weight: weight !== null && weight !== void 0 ? weight : 0, weightMultiplier: 1 });
const simulatedContract = {
chargesUsed: 0,
containerEntityId: characterId,
@@ -65,9 +65,12 @@ export function generateCustomItem(customItem, ruleData, characterId) {
id,
isAttuned: false,
limitedUse: null,
originEntityId: null,
originEntityTypeId: null,
originDefinitionKey: null,
quantity: quantity !== null && quantity !== void 0 ? quantity : 1,
};
return Object.assign(Object.assign({}, simulatedContract), { avatarUrl: (_a = definition.avatarUrl) !== null && _a !== void 0 ? _a : '', armorClass: null, baseItemType: ItemBaseTypeEnum.GEAR, additionalDamages: [], versatileDamage: null, reach: null, canAttune: false, canBeDedicatedWeapon: false, canEquip: false, canHexWeapon: false, canOffhand: false, canPactWeapon: false, categoryInfo: null, definitionKey: '', hexWeaponEnabled: false, isDedicatedWeapon: false, isHexWeapon: false, isPactWeapon: false, metaItems: [], pactWeaponEnabled: false, toHit: null, damage: null, infusion: null, infusionActions: [], isOffhand: false, isAdamantine: false, isMagic: false, isSilvered: false, damageType: definition.damageType, displayAsAttack: false, isCustom: true, isCustomized: false, isDisplayAsAttack: false, proficiency: false, modifiers: [], originalContract: customItem, spells: [], type: null, name: (_b = definition.name) !== null && _b !== void 0 ? _b : 'Unidentified Item', cost: deriveCost(simulatedContract, {}), weight: deriveWeight(simulatedContract, {}), capacityWeight: deriveCapacityWeight(simulatedContract, {}), notes, properties: [], stealthCheck: StealthCheckTypeEnum.NONE, masteryName: null, primarySourceCategoryId: -1, secondarySourceCategoryIds: [], replacementWeaponStats: [], appliedWeaponReplacementStats: [] });
return Object.assign(Object.assign({}, simulatedContract), { avatarUrl: (_a = definition.avatarUrl) !== null && _a !== void 0 ? _a : '', armorClass: null, baseItemType: ItemBaseTypeEnum.GEAR, additionalDamages: [], versatileDamage: null, reach: null, canAttune: false, canBeDedicatedWeapon: false, canEquip: false, canHexWeapon: false, canOffhand: false, canPactWeapon: false, categoryInfo: null, definitionKey: '', hexWeaponEnabled: false, isDedicatedWeapon: false, isHexWeapon: false, isPactWeapon: false, metaItems: [], pactWeaponEnabled: false, toHit: null, damage: null, infusion: null, infusionActions: [], isOffhand: false, isAdamantine: false, isMagic: false, isSilvered: false, damageType: definition.damageType, displayAsAttack: false, isCustom: true, isCustomized: false, isDisplayAsAttack: false, proficiency: false, modifiers: [], originalContract: customItem, spells: [], type: null, name: (_b = definition.name) !== null && _b !== void 0 ? _b : 'Unidentified Item', cost: deriveCost(simulatedContract, {}), weight: deriveWeight(simulatedContract, {}), capacityWeight: deriveCapacityWeight(simulatedContract, {}), notes, properties: [], stealthCheck: StealthCheckTypeEnum.NONE, masteryName: null, primarySourceCategoryId: -1, secondarySourceCategoryIds: [], replacementWeaponStats: [], appliedWeaponReplacementStats: [], partyInventoryRestrictions: [] });
}
/**
*
@@ -81,7 +84,7 @@ export function generateWeaponBehaviorBaseItem(baseWeapon, parentItem, valueLook
return null;
}
const item = Object.assign(Object.assign({}, parentItem), { definition: Object.assign(Object.assign(Object.assign({}, parentItem.definition), baseWeapon), { fixedDamage: null }) });
return Object.assign(Object.assign({}, item), { avatarUrl: deriveAvatarUrl(item, ruleData), baseItemType: ItemBaseTypeEnum.WEAPON, canAttune: deriveCanAttune(item, null), canEquip: deriveCanEquip(item, null), categoryInfo: deriveCategoryInfo(item, ruleData), cost: deriveCost(item, valueLookup), damageType: deriveDamageType(item, []), definitionKey: deriveDefinitionKey(item), isAdamantine: deriveIsAdamantine(item, valueLookup), isCustom: isCustomItem(item), isCustomized: deriveIsCustomized(item, valueLookup), isDisplayAsAttack: deriveIsDisplayAsAttack(item, valueLookup), isOffhand: deriveIsOffhand(item, valueLookup), isSilvered: deriveIsSilvered(item, valueLookup), isMagic: deriveIsMagic(item, null), infusion: null, infusionActions: [], modifiers: getModifiers(parentItem), name: deriveName(item, valueLookup), notes: deriveNotes(item, valueLookup), originalContract: null, properties: deriveProperties(item, [], ruleData), spells: [], type: deriveType(item, ruleData), weight: deriveWeight(item, valueLookup), capacityWeight: deriveCapacityWeight(item, valueLookup) });
return Object.assign(Object.assign({}, item), { avatarUrl: deriveAvatarUrl(item, ruleData), baseItemType: ItemBaseTypeEnum.WEAPON, canAttune: deriveCanAttune(item, null), canEquip: deriveCanEquip(item, null), categoryInfo: deriveCategoryInfo(item, ruleData), cost: deriveCost(item, valueLookup), damageType: deriveDamageType(item, []), definitionKey: deriveDefinitionKey(item), isAdamantine: deriveIsAdamantine(item, valueLookup), isCustom: isCustomItem(item), isCustomized: deriveIsCustomized(item, valueLookup), isDisplayAsAttack: deriveIsDisplayAsAttack(item, valueLookup), isOffhand: deriveIsOffhand(item, valueLookup), isSilvered: deriveIsSilvered(item, valueLookup), isMagic: deriveIsMagic(item, null), infusion: null, infusionActions: [], modifiers: getModifiers(parentItem), name: deriveName(item, valueLookup), notes: deriveNotes(item, valueLookup), originalContract: null, properties: deriveProperties(item, [], ruleData), spells: [], type: deriveType(item, ruleData), weight: deriveWeight(item, valueLookup), capacityWeight: deriveCapacityWeight(item, valueLookup), partyInventoryRestrictions: [] });
}
/**
*
@@ -294,8 +297,8 @@ export function generateItem(item, abilityLookup, proficiencyBonus, modifiers, e
* @param inventoryInfusionLookup
* @param ruleData
*/
export function generateBaseItems(items, modifierLookup, spellLookup, valueLookup, inventoryInfusionLookup, ruleData) {
return items.map((item) => generateBaseItem(item, modifierLookup, spellLookup, valueLookup, inventoryInfusionLookup, ruleData));
export function generateBaseItems(items, modifierLookup, spellLookup, valueLookup, inventoryInfusionLookup, ruleData, partyInventoryRestrictions = []) {
return items.map((item) => generateBaseItem(item, modifierLookup, spellLookup, valueLookup, inventoryInfusionLookup, ruleData, partyInventoryRestrictions));
}
/**
*
@@ -306,7 +309,7 @@ export function generateBaseItems(items, modifierLookup, spellLookup, valueLooku
* @param inventoryInfusionLookup
* @param ruleData
*/
export function generateBaseItem(item, modifierLookup, spellLookup, valueLookup, inventoryInfusionLookup, ruleData) {
export function generateBaseItem(item, modifierLookup, spellLookup, valueLookup, inventoryInfusionLookup, ruleData, partyInventoryRestrictions = []) {
const id = getId(item);
const entityTypeId = getEntityTypeId(item);
const infusion = HelperUtils.lookupDataOrFallback(inventoryInfusionLookup, getMappingId(item));
@@ -322,7 +325,7 @@ export function generateBaseItem(item, modifierLookup, spellLookup, valueLookup,
const infusionActions = deriveInfusionActions(infusion, valueLookup, item);
const notes = deriveNotes(item, valueLookup);
return Object.assign(Object.assign({}, item), { avatarUrl: deriveAvatarUrl(item, ruleData), baseItemType: deriveBaseType(item), canAttune: deriveCanAttune(item, infusion), canEquip: deriveCanEquip(item, infusion), categoryInfo: deriveCategoryInfo(item, ruleData), cost: deriveCost(item, valueLookup), definitionKey: deriveDefinitionKey(item), damageType: deriveDamageType(item, modifiers), infusion,
infusionActions, isAdamantine: deriveIsAdamantine(item, valueLookup), isCustom: isCustomItem(item), isCustomized: deriveIsCustomized(item, valueLookup), isDisplayAsAttack: deriveIsDisplayAsAttack(item, valueLookup), isMagic: deriveIsMagic(item, infusion), isOffhand: deriveIsOffhand(item, valueLookup), isSilvered: deriveIsSilvered(item, valueLookup), limitedUse: deriveLimitedUse(infusionActions, getLimitedUse(item)), modifiers, name: deriveName(item, valueLookup), notes, originalContract: deriveOriginalCustomContract(item, notes), properties: deriveProperties(item, modifiers, ruleData), spells: baseSpells.map((spell) => updateBaseItemSpells(item, spell)), type: deriveType(item, ruleData), weight: deriveWeight(item, valueLookup), capacityWeight: deriveCapacityWeight(item, valueLookup) });
infusionActions, isAdamantine: deriveIsAdamantine(item, valueLookup), isCustom: isCustomItem(item), isCustomized: deriveIsCustomized(item, valueLookup), isDisplayAsAttack: deriveIsDisplayAsAttack(item, valueLookup), isMagic: deriveIsMagic(item, infusion), isOffhand: deriveIsOffhand(item, valueLookup), isSilvered: deriveIsSilvered(item, valueLookup), limitedUse: deriveLimitedUse(infusionActions, getLimitedUse(item)), modifiers, name: deriveName(item, valueLookup), notes, originalContract: deriveOriginalCustomContract(item, notes), properties: deriveProperties(item, modifiers, ruleData), spells: baseSpells.map((spell) => updateBaseItemSpells(item, spell)), type: deriveType(item, ruleData), weight: deriveWeight(item, valueLookup), capacityWeight: deriveCapacityWeight(item, valueLookup), partyInventoryRestrictions: derivePartyInventoryRestrictions(item, partyInventoryRestrictions) });
}
/**
*
@@ -404,6 +407,10 @@ export function generateHasMaxAttunedItems(attunedItems, attunedItemCountMax) {
export function generateInventoryLookup(items) {
return keyBy(items, (item) => getMappingId(item));
}
export function generateInventoryLookupByOrigin(inventory, partyInventory) {
const combinedItems = [...inventory, ...partyInventory];
return HelperUtils.generateNonNullLookup(combinedItems, (item) => getOriginDefinitionKey(item));
}
/**
*
* @param items
@@ -7,7 +7,7 @@ import { SpellAccessors } from '../Spell';
import { getAdditionalDamages, getAttackType, getLimitedUse, getLongRange, getNotes, getProperties, getRange, getStealthCheck, getStrengthRequirement, getTags, isAdamantine, isOffhand, isSilvered, getArmorClass, getInfusion, isCustom, } from './accessors';
import { WeaponPropertyEnum } from './constants';
import { deriveCategoryInfo } from './derivers';
import { getApplicableWeaponSpellDamageGroups, hasWeaponProperty, isBaseArmor, isBaseGear, isBaseWeapon, isShield, } from './utils';
import { getApplicableWeaponSpellDamageGroups, hasWeaponProperty, isBaseArmor, isBaseGear, isBaseWeapon, isShield, isReplicated, } from './utils';
import { validateIsWeaponLike } from './validators';
/**
*
@@ -190,12 +190,16 @@ function getInfusionNoteComponents(item, infusion) {
* @param abilityLookup
* @param proficiencyBonus
*/
export function getNoteComponents(item, weaponSpellDamageGroups, ruleData, abilityLookup, proficiencyBonus) {
export function getNoteComponents(item, weaponSpellDamageGroups, ruleData, abilityLookup, proficiencyBonus, itemPlan = null) {
const notes = [];
const infusion = getInfusion(item);
if (infusion) {
notes.push(...getInfusionNoteComponents(item, infusion));
}
// If there is an item plan or the item is marked as replicated by PartyResctrictions - add a note
if (itemPlan || isReplicated(item)) {
notes.push(NoteGenerators.createPlainText('Replicated Item'));
}
if (isBaseWeapon(item)) {
notes.push(...getWeaponNoteComponents(item, weaponSpellDamageGroups, ruleData, abilityLookup, proficiencyBonus));
}
@@ -13,9 +13,9 @@ import { deriveArmorClass, deriveAvatarUrl, deriveBaseType, deriveCanAttune, der
*/
export function simulateItem(itemDefinition, globalModifiers, valueLookupByType, ruleData, overrides) {
var _a, _b;
const simulatedItemContract = Object.assign({ chargesUsed: 0, containerEntityId: -1, containerEntityTypeId: -1, containerDefinitionKey: '-1:-1', currency: null, definition: itemDefinition, definitionId: itemDefinition.id, definitionTypeId: -1, displayAsAttack: null, entityTypeId: -1, equipped: false, equippedEntityId: null, equippedEntityTypeId: null, id: -1, isAttuned: false, limitedUse: null, quantity: 1 }, ((_a = overrides === null || overrides === void 0 ? void 0 : overrides.simulatedItemContract) !== null && _a !== void 0 ? _a : {}));
const simulatedItemContract = Object.assign({ chargesUsed: 0, containerEntityId: -1, containerEntityTypeId: -1, containerDefinitionKey: '-1:-1', currency: null, definition: itemDefinition, definitionId: itemDefinition.id, definitionTypeId: -1, displayAsAttack: null, entityTypeId: -1, equipped: false, equippedEntityId: null, equippedEntityTypeId: null, id: -1, isAttuned: false, limitedUse: null, originEntityId: null, originEntityTypeId: null, originDefinitionKey: null, quantity: 1 }, ((_a = overrides === null || overrides === void 0 ? void 0 : overrides.simulatedItemContract) !== null && _a !== void 0 ? _a : {}));
const modifiers = (_b = getDefinitionGrantedModifiers(simulatedItemContract)) !== null && _b !== void 0 ? _b : [];
const simulatedItem = Object.assign(Object.assign({}, simulatedItemContract), { avatarUrl: deriveAvatarUrl(simulatedItemContract, ruleData), baseItemType: deriveBaseType(simulatedItemContract), canAttune: deriveCanAttune(simulatedItemContract, null), canEquip: deriveCanEquip(simulatedItemContract, null), categoryInfo: deriveCategoryInfo(simulatedItemContract, ruleData), cost: deriveCost(simulatedItemContract, {}), damageType: deriveDamageType(simulatedItemContract, []), definitionKey: deriveDefinitionKey(simulatedItemContract), isAdamantine: false, isCustom: false, isCustomized: false, isDisplayAsAttack: deriveIsDisplayAsAttack(simulatedItemContract, {}), isOffhand: false, isSilvered: false, isMagic: deriveIsMagic(simulatedItemContract, null), infusion: null, infusionActions: [], modifiers: modifiers.map((modifier) => ModifierGenerators.generateModifier(modifier, DataOriginTypeEnum.SIMULATED, null)), name: deriveName(simulatedItemContract, {}), notes: null, originalContract: null, properties: deriveProperties(simulatedItemContract, [], ruleData), spells: [], type: deriveType(simulatedItemContract, ruleData), weight: deriveWeight(simulatedItemContract, {}), capacityWeight: deriveCapacityWeight(simulatedItemContract, {}) });
const simulatedItem = Object.assign(Object.assign({}, simulatedItemContract), { avatarUrl: deriveAvatarUrl(simulatedItemContract, ruleData), baseItemType: deriveBaseType(simulatedItemContract), canAttune: deriveCanAttune(simulatedItemContract, null), canEquip: deriveCanEquip(simulatedItemContract, null), categoryInfo: deriveCategoryInfo(simulatedItemContract, ruleData), cost: deriveCost(simulatedItemContract, {}), damageType: deriveDamageType(simulatedItemContract, []), definitionKey: deriveDefinitionKey(simulatedItemContract), isAdamantine: false, isCustom: false, isCustomized: false, isDisplayAsAttack: deriveIsDisplayAsAttack(simulatedItemContract, {}), isOffhand: false, isSilvered: false, isMagic: deriveIsMagic(simulatedItemContract, null), infusion: null, infusionActions: [], modifiers: modifiers.map((modifier) => ModifierGenerators.generateModifier(modifier, DataOriginTypeEnum.SIMULATED, null)), name: deriveName(simulatedItemContract, {}), notes: null, originalContract: null, properties: deriveProperties(simulatedItemContract, [], ruleData), spells: [], type: deriveType(simulatedItemContract, ruleData), weight: deriveWeight(simulatedItemContract, {}), capacityWeight: deriveCapacityWeight(simulatedItemContract, {}), partyInventoryRestrictions: [] });
const additionalDamages = deriveWeaponAdditionalDamage(simulatedItem);
const reach = deriveWeaponReach(simulatedItem, globalModifiers, ruleData);
const proficiency = deriveIsProficient(simulatedItem, globalModifiers, false, valueLookupByType, ruleData);
@@ -1,9 +1,11 @@
import { orderBy } from 'lodash';
import { TypeScriptUtils } from '../../utils';
import { ActionAccessors } from '../Action';
import { PartyRestrictionTypeEnum } from '../Campaign';
import { ContainerValidators } from '../Container';
import { ItemPlanAccessors } from '../ItemPlan';
import { ValueHacks, ValueUtils } from '../Value';
import { canAttune, getArmorTypeId, getAttackType, getBaseItemId, getBaseType, getBaseTypeId, getContainerDefinitionKey, getGearTypeId, getItemWeaponBehaviors, getMappingEntityTypeId, getMappingId, getMasteryName, getName, getPrimarySourceCategoryId, getProperties, getRarity, getSecondarySourceCategoryIds, isAttuned, isContainer, } from './accessors';
import { canAttune, getArmorTypeId, getAttackType, getBaseItemId, getBaseType, getBaseTypeId, getContainerDefinitionKey, getDefinition, getGearTypeId, getItemWeaponBehaviors, getMappingEntityTypeId, getMappingId, getMasteryName, getName, getOriginDefinitionKey, getPartyInventoryRestrictions, getPrimarySourceCategoryId, getProperties, getRarity, getSecondarySourceCategoryIds, isAttuned, isContainer, } from './accessors';
import { ArmorTypeEnum, ItemBaseTypeEnum, ItemBaseTypeIdEnum, ItemRarityNameEnum, ItemTypeEnum, } from './constants';
//TODO probably move alot of these to validators and validate naming :)
export function isShield(armor) {
@@ -177,3 +179,15 @@ export function getMasteryAction(item, actions) {
export function getAllSourceCategoryIds(item) {
return [getPrimarySourceCategoryId(item), ...getSecondarySourceCategoryIds(item)];
}
/// Returns the item plan for the given item if it exists in the provided item plans.
export function getItemPlan(item, itemPlans) {
return (itemPlans.find((plan) => {
var _a;
return ((_a = getDefinition(item)) === null || _a === void 0 ? void 0 : _a.definitionKey) === ItemPlanAccessors.getItemDefinitionKey(plan) &&
getOriginDefinitionKey(item) === ItemPlanAccessors.getOriginDefinitionKey(plan);
}) || null);
}
export function isReplicated(item) {
const partyRestrictions = getPartyInventoryRestrictions(item);
return partyRestrictions.some((restriction) => restriction.type === PartyRestrictionTypeEnum.REPLICATED);
}
@@ -0,0 +1,21 @@
export function getItemDefinitionKey(itemPlan) {
return itemPlan.itemDefinitionKey;
}
export function getDataOrigin(itemPlan) {
return itemPlan.dataOrigin;
}
export function getItemName(itemPlan) {
return itemPlan.itemName;
}
export function getChoice(itemPlan) {
return itemPlan.choice;
}
export function getOriginDefinitionKey(itemPlan) {
return itemPlan.originDefinitionKey;
}
export function getDescription(itemPlan) {
return itemPlan.description;
}
export function getItem(itemPlan) {
return itemPlan.item;
}
@@ -0,0 +1,70 @@
import { sortBy } from 'lodash';
import { ChoiceAccessors } from '../Choice';
import { ClassAccessors, ClassDerivers } from '../Class';
import { ClassFeatureAccessors } from '../ClassFeature';
import { ContainerAccessors } from '../Container';
import { DataOriginGenerators } from '../DataOrigin';
import { DefinitionHacks } from '../Definition';
import { HelperUtils } from '../Helper';
import { ItemAccessors } from '../Item';
import { OptionAccessors } from '../Option';
import { getItemDefinitionKey, getItemName, getOriginDefinitionKey } from './accessors';
export function generateItemPlans(choices, options, dataOriginType, primary, parent) {
return choices.map((choice) => {
return generateItemPlan(choice, options, DataOriginGenerators.generateDataOrigin(dataOriginType, primary, parent));
});
}
export function generateItemPlan(choice, options, dataOrigin) {
const optionValue = ChoiceAccessors.getOptionValue(choice);
const chosenOption = options.find((option) => OptionAccessors.getId(option) === optionValue);
const itemName = chosenOption ? `Plan: ${OptionAccessors.getName(chosenOption)}` : 'Plan: Unknown';
let originDefinitionKey = null;
if (chosenOption && optionValue) {
originDefinitionKey = DefinitionHacks.hack__generateDefinitionKey(OptionAccessors.getDefinitionEntityTypeId(chosenOption), optionValue);
}
return {
originDefinitionKey,
choice,
dataOrigin,
itemName,
itemDefinitionKey: choice.itemDefinitionKey,
};
}
export function generateAggregatedItemPlans(classes, inventoryLookupByOrigin, containerLookup) {
const availablePlans = [];
classes.forEach((charClass) => {
ClassAccessors.getClassFeatures(charClass).forEach((feature) => {
const itemPlans = ClassFeatureAccessors.getItemPlans(feature).filter((plan) => getOriginDefinitionKey(plan) !== null && getItemDefinitionKey(plan) !== null);
availablePlans.push(...itemPlans);
});
});
//add inventory mappings to the item plans if they exist in the lookup
const updatedPlans = availablePlans.map((plan) => {
const planOriginDefinitionKey = getOriginDefinitionKey(plan);
const item = planOriginDefinitionKey
? HelperUtils.lookupDataOrFallback(inventoryLookupByOrigin, planOriginDefinitionKey)
: null;
const container = item
? HelperUtils.lookupDataOrFallback(containerLookup, ItemAccessors.getContainerDefinitionKey(item))
: null;
// if there is a container, use its name, otherwise default to 'In Equipment'
let containerName = 'In Equipment';
if (item && container) {
containerName = !ItemAccessors.isContainer(item)
? `In ${ContainerAccessors.getName(container)}`
: `In ${ContainerAccessors.isShared(container) ? 'Party ' : ''}Inventory`;
}
return Object.assign(Object.assign({}, plan), { item, description: item ? containerName : 'No item replicated.' });
});
return sortBy(updatedPlans, (plan) => getItemName(plan));
}
export function generateMaxReplicatedItemCount(classes) {
let totalMaxReplicatedItemsCount = 0;
classes.forEach((charClass) => {
const classMaxCount = ClassDerivers.deriveMaxReplicatedMagicItems(charClass);
if (classMaxCount) {
totalMaxReplicatedItemsCount += classMaxCount;
}
});
return totalMaxReplicatedItemsCount > 0 ? totalMaxReplicatedItemsCount : null;
}
@@ -0,0 +1,6 @@
import * as ItemPlanAccessors from './accessors';
import * as ItemPlanGenerators from './generators';
import * as ItemPlanTypings from './typings';
export * from './typings';
export { ItemPlanAccessors, ItemPlanGenerators };
export default Object.assign(Object.assign(Object.assign({}, ItemPlanAccessors), ItemPlanGenerators), ItemPlanTypings);
@@ -174,6 +174,8 @@ export var ModifierSubTypeEnum;
ModifierSubTypeEnum["STUDDED_LEATHER"] = "studded-leather";
ModifierSubTypeEnum["PRIDE_SILK_OUTFIT"] = "pride-silk-outfit";
ModifierSubTypeEnum["BARK_ARMOR"] = "bark-armor";
ModifierSubTypeEnum["LEATHER_SHIRT"] = "leather-shirt";
ModifierSubTypeEnum["LEATHER_CORSLET"] = "leather-corslet";
// medium armor
ModifierSubTypeEnum["HIDE"] = "hide";
ModifierSubTypeEnum["CHAIN_SHIRT"] = "chain-shirt";
@@ -182,6 +184,7 @@ export var ModifierSubTypeEnum;
ModifierSubTypeEnum["HALF_PLATE"] = "half-plate";
ModifierSubTypeEnum["SPIKED_ARMOR"] = "spiked-armor";
ModifierSubTypeEnum["SCUMWEED_ARMOR"] = "scumweed-armor";
ModifierSubTypeEnum["SCALE_ARMOUR"] = "scale-armour";
// heavy armor
ModifierSubTypeEnum["RING_MAIL"] = "ring-mail";
ModifierSubTypeEnum["CHAIN_MAIL"] = "chain-mail";
@@ -220,6 +223,8 @@ export var ModifierSubTypeEnum;
// Warlock Feature
ModifierSubTypeEnum["ENABLE_PACT_WEAPON"] = "enable-pact-weapon";
ModifierSubTypeEnum["ENABLE_HEX_WEAPON"] = "enable-hex-weapon";
// Artificer Feature
ModifierSubTypeEnum["ENABLE_REPLICATE_MAGIC_ITEM"] = "enable-replicate-magic-item";
// Enable Feature (used in tandem with REPLACE_WEAPON_ABILITY modifier)
ModifierSubTypeEnum["ENABLE_STRENGTH"] = "enable-strength";
ModifierSubTypeEnum["ENABLE_DEXTERITY"] = "enable-dexterity";
@@ -253,28 +258,31 @@ export const DAMAGE_ADJUSTMENT_LIST = [
ModifierSubTypeEnum.BLUDGEONING_PIERCING_SLASHING_NONMAGIC,
];
export const LIGHT_ARMOR_LIST = [
ModifierSubTypeEnum.PADDED,
ModifierSubTypeEnum.LEATHER,
ModifierSubTypeEnum.STUDDED_LEATHER,
ModifierSubTypeEnum.PRIDE_SILK_OUTFIT,
ModifierSubTypeEnum.BARK_ARMOR,
ModifierSubTypeEnum.LEATHER,
ModifierSubTypeEnum.LEATHER_CORSLET,
ModifierSubTypeEnum.LEATHER_SHIRT,
ModifierSubTypeEnum.PADDED,
ModifierSubTypeEnum.PRIDE_SILK_OUTFIT,
ModifierSubTypeEnum.STUDDED_LEATHER,
];
export const MEDIUM_ARMOR_LIST = [
ModifierSubTypeEnum.HIDE,
ModifierSubTypeEnum.CHAIN_SHIRT,
ModifierSubTypeEnum.SCALE_MAIL,
ModifierSubTypeEnum.BREASTPLATE,
ModifierSubTypeEnum.CHAIN_SHIRT,
ModifierSubTypeEnum.HALF_PLATE,
ModifierSubTypeEnum.SPIKED_ARMOR,
ModifierSubTypeEnum.HIDE,
ModifierSubTypeEnum.SCALE_ARMOUR,
ModifierSubTypeEnum.SCALE_MAIL,
ModifierSubTypeEnum.SCUMWEED_ARMOR,
ModifierSubTypeEnum.SPIKED_ARMOR,
];
export const HEAVY_ARMOR_LIST = [
ModifierSubTypeEnum.RING_MAIL,
ModifierSubTypeEnum.CHAIN_MAIL,
ModifierSubTypeEnum.SPLINT,
ModifierSubTypeEnum.DIVERS_ARMOR,
ModifierSubTypeEnum.PLATE,
ModifierSubTypeEnum.POWERED_ARMOR,
ModifierSubTypeEnum.DIVERS_ARMOR,
ModifierSubTypeEnum.RING_MAIL,
ModifierSubTypeEnum.SPLINT,
];
export const SHIELDS_LIST = [ModifierSubTypeEnum.SHIELD, ModifierSubTypeEnum.POT_LID];
export const ALL_ARMOR_LIST = [
@@ -306,6 +306,10 @@ export function isEnableHexWeaponModifier(modifier) {
return (getType(modifier) === ModifierTypeEnum.ENABLE_FEATURE &&
getSubType(modifier) === ModifierSubTypeEnum.ENABLE_HEX_WEAPON);
}
export function isEnableReplicateMagicItemModifier(modifier) {
return (getType(modifier) === ModifierTypeEnum.ENABLE_FEATURE &&
getSubType(modifier) === ModifierSubTypeEnum.ENABLE_REPLICATE_MAGIC_ITEM);
}
export function isEnablesAbilityStatModifier(modifier) {
if (getType(modifier) !== ModifierTypeEnum.ENABLE_FEATURE) {
return false;
@@ -14,6 +14,7 @@ export var SnippetMathOperatorEnum;
})(SnippetMathOperatorEnum || (SnippetMathOperatorEnum = {}));
export var SnippetTagValueTypeEnum;
(function (SnippetTagValueTypeEnum) {
SnippetTagValueTypeEnum["SPEED"] = "speed";
SnippetTagValueTypeEnum["SAVE_DC"] = "savedc";
SnippetTagValueTypeEnum["SPELL_ATTACK"] = "spellattack";
SnippetTagValueTypeEnum["SCALE_VALUE"] = "scalevalue";
@@ -51,6 +52,14 @@ export var SnippetAbilityKeyEnum;
SnippetAbilityKeyEnum["WISDOM"] = "wis";
SnippetAbilityKeyEnum["CHARISMA"] = "cha";
})(SnippetAbilityKeyEnum || (SnippetAbilityKeyEnum = {}));
export var SnippetSpeedMovementKeyEnum;
(function (SnippetSpeedMovementKeyEnum) {
SnippetSpeedMovementKeyEnum["WALK"] = "walk";
SnippetSpeedMovementKeyEnum["FLY"] = "fly";
SnippetSpeedMovementKeyEnum["BURROW"] = "burrow";
SnippetSpeedMovementKeyEnum["SWIM"] = "swim";
SnippetSpeedMovementKeyEnum["CLIMB"] = "climb";
})(SnippetSpeedMovementKeyEnum || (SnippetSpeedMovementKeyEnum = {}));
export var SnippetContentChunkTypeEnum;
(function (SnippetContentChunkTypeEnum) {
SnippetContentChunkTypeEnum["TEXT"] = "TEXT";
@@ -5,15 +5,17 @@
* @param abilityLookup
* @param xpInfo
* @param hitPointInfo
* @param speedInfo
* @param ruleData
*/
export function generateSnippetData(proficiencyBonus, abilityKeyLookup, abilityLookup, xpInfo, hitPointInfo, ruleData) {
export function generateSnippetData(proficiencyBonus, abilityKeyLookup, abilityLookup, xpInfo, hitPointInfo, speedInfo, ruleData) {
return {
proficiencyBonus,
abilityKeyLookup,
abilityLookup,
xpInfo,
hitPointInfo,
speedInfo,
ruleData,
};
}
@@ -2,6 +2,7 @@ import { isFinite, toNumber } from 'lodash';
import { TypeScriptUtils } from '../../utils';
import { AbilityAccessors } from '../Ability';
import { CharacterDerivers } from '../Character';
import { SpeedMovementKeyEnum } from '../Core';
import { DiceRenderers } from '../Dice';
import { FormatUtils } from '../Format';
import { LimitedUseDerivers } from '../LimitedUse';
@@ -90,6 +91,7 @@ export function isSnippetPostProcessTypeEnum(key) {
*/
export function isSnippetTagValueTypeEnum(key) {
switch (key) {
case SnippetTagValueTypeEnum.SPEED:
case SnippetTagValueTypeEnum.SCALE_VALUE:
case SnippetTagValueTypeEnum.LIMITED_USE:
case SnippetTagValueTypeEnum.CLASS_LEVEL:
@@ -107,6 +109,23 @@ export function isSnippetTagValueTypeEnum(key) {
}
return false;
}
/**
*
* @param type
*/
export function isSnippetSpeedMovementKeyEnum(key) {
switch (key) {
case SpeedMovementKeyEnum.WALK:
case SpeedMovementKeyEnum.FLY:
case SpeedMovementKeyEnum.BURROW:
case SpeedMovementKeyEnum.SWIM:
case SpeedMovementKeyEnum.CLIMB:
return true;
default:
// not implemented
}
return false;
}
/**
*
* @param type
@@ -207,6 +226,7 @@ export function throwInvalidSnippetCharacters(str) {
keywordMatches === null || keywordMatches === void 0 ? void 0 : keywordMatches.forEach((keyword) => {
if (isSnippetTagValueTypeEnum(keyword) ||
isSnippetAbilityKeyEnum(keyword) ||
isSnippetSpeedMovementKeyEnum(keyword) ||
isSnippetValueModifierTypeEnum(keyword) ||
isSnippetPostProcessTypeEnum(keyword)) {
return;
@@ -323,9 +343,21 @@ export function deriveStringTagValue(tagValue, contextData) {
* @param proficiencyBonus
*/
export function deriveNumericTagValue(tagValue, contextData, snippetData, proficiencyBonus) {
var _a;
const { type, params } = tagValue;
let value = 0;
switch (type) {
case SnippetTagValueTypeEnum.SPEED: {
const movementType = (_a = params[0]) !== null && _a !== void 0 ? _a : SpeedMovementKeyEnum.WALK;
if (!isSnippetSpeedMovementKeyEnum(movementType)) {
throw new Error(`Invalid speed type: ${movementType}`);
}
const speed = snippetData.speedInfo[movementType];
if (speed === null) {
throw new Error(`No speed data available for ${movementType}`);
}
return speed;
}
case SnippetTagValueTypeEnum.SAVE_DC:
if (params.length < 1) {
throw new Error('Save DC missing ability key');