New source found from dndbeyond.com
This commit is contained in:
@@ -0,0 +1 @@
|
||||
export const ITEM_PLAN_INVENTORY_MAPPING_CREATE = 'character.ITEM_PLAN_INVENTORY_MAPPING_CREATE';
|
||||
@@ -7,7 +7,7 @@ import * as actionTypes from '../actionTypes';
|
||||
* @param choiceId
|
||||
* @param optionValue
|
||||
*/
|
||||
export function classFeatureChoiceSetRequest(classId, classFeatureId, choiceType, choiceId, optionValue, parentChoiceId) {
|
||||
export function classFeatureChoiceSetRequest(classId, classFeatureId, choiceType, choiceId, optionValue, parentChoiceId, accept, reject) {
|
||||
return {
|
||||
type: actionTypes.CLASS_FEATURE_CHOICE_SET_REQUEST,
|
||||
payload: {
|
||||
@@ -18,6 +18,9 @@ export function classFeatureChoiceSetRequest(classId, classFeatureId, choiceType
|
||||
optionValue,
|
||||
parentChoiceId,
|
||||
},
|
||||
meta: {},
|
||||
meta: {
|
||||
accept,
|
||||
reject,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ export function itemAdd(item) {
|
||||
* @param id
|
||||
* @param removeContainerContents
|
||||
*/
|
||||
export function itemRemove(id, removeContainerContents) {
|
||||
export function itemRemove(id, removeContainerContents = false) {
|
||||
return {
|
||||
type: actionTypes.ITEM_REMOVE,
|
||||
payload: {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import * as actionTypes from '../actionTypes';
|
||||
/**
|
||||
*
|
||||
* @param item
|
||||
* @param quantity
|
||||
* @param accept
|
||||
* @param reject
|
||||
* @param containerDefinitionKey
|
||||
*/
|
||||
export function itemPlanInventoryMappingCreate(itemDefinitionKey, quantity, itemPlanOriginDefinitionKey, containerDefinitionKey, accept, reject) {
|
||||
return {
|
||||
type: actionTypes.ITEM_PLAN_INVENTORY_MAPPING_CREATE,
|
||||
payload: {
|
||||
itemDefinitionKey,
|
||||
quantity,
|
||||
itemPlanOriginDefinitionKey,
|
||||
containerDefinitionKey,
|
||||
},
|
||||
meta: {
|
||||
accept,
|
||||
reject,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export const LONG_REST_TEXT_SET = 'serviceData.LONG_REST_TEXT_SET';
|
||||
@@ -30,14 +30,17 @@ export function infusionMappingAdd(infusionMapping) {
|
||||
* @param infusionId
|
||||
* @param inventoryMappingId
|
||||
*/
|
||||
export function infusionMappingDestroy(infusionId, inventoryMappingId) {
|
||||
export function infusionMappingDestroy(infusionId, inventoryMappingId, accept, reject) {
|
||||
return {
|
||||
type: actionTypes.INFUSION_MAPPING_DESTROY,
|
||||
payload: {
|
||||
infusionId,
|
||||
inventoryMappingId,
|
||||
},
|
||||
meta: {},
|
||||
meta: {
|
||||
accept,
|
||||
reject,
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import * as actionTypes from '../actionTypes';
|
||||
export function longRestTextSet(longRestText) {
|
||||
return {
|
||||
type: actionTypes.LONG_REST_TEXT_SET,
|
||||
payload: longRestText,
|
||||
meta: {},
|
||||
};
|
||||
}
|
||||
@@ -6,15 +6,3 @@ import { ApiTypeEnum } from '../../../constants';
|
||||
export const postCharacterBuilderStandardBuild = ApiAdapterUtils.makePost(ApiTypeEnum.CHARACTER_SERVICE, 'builder/standard-build', {
|
||||
removeDefaultParams: true,
|
||||
});
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const postCharacterBuilderRandomBuild = ApiAdapterUtils.makePost(ApiTypeEnum.CHARACTER_SERVICE, 'builder/random-build', {
|
||||
removeDefaultParams: true,
|
||||
});
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export const postCharacterBuilderQuickBuild = ApiAdapterUtils.makePost(ApiTypeEnum.CHARACTER_SERVICE, 'builder/quick-build', {
|
||||
removeDefaultParams: true,
|
||||
});
|
||||
|
||||
@@ -24,8 +24,6 @@ export const getCharacterGameDataBackdrops = ApiAdapterUtils.makeGet(ApiTypeEnum
|
||||
* This is a temporary character service endpoint and will eventually be moved to the game data service
|
||||
*/
|
||||
export const getCharacterGameDataFeats = ApiAdapterUtils.makeGet(ApiTypeEnum.HACK__CHARACTER_SERVICE_GAME_DATA, 'game-data/feats');
|
||||
// /features/v1/features/collection?category=blessing
|
||||
export const getCharacterGameDataFeatures = ApiAdapterUtils.makeGet(ApiTypeEnum.GAME_DATA_SERVICE, 'features/v1/features/collection');
|
||||
/**
|
||||
* This is a temporary character service endpoint and will eventually be moved to the game data service
|
||||
*/
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import { ApiTypeEnum } from "../../constants";
|
||||
import * as ApiAdapterUtils from '../../../apiAdapter/utils';
|
||||
export const getCharacterFeatures = ApiAdapterUtils.makeInterpolatedGet(ApiTypeEnum.CHARACTER_SERVICE, 'features/{characterId}', { removeDefaultParams: true });
|
||||
export const postCharacterFeature = ApiAdapterUtils.makePost(ApiTypeEnum.CHARACTER_SERVICE, 'feature');
|
||||
export const deleteCharacterFeature = ApiAdapterUtils.makeDelete(ApiTypeEnum.CHARACTER_SERVICE, 'feature');
|
||||
export const postFeaturesAndSubfeatures = ApiAdapterUtils.makePost(ApiTypeEnum.GAME_DATA_SERVICE, 'features/v1/features/collection');
|
||||
@@ -2,16 +2,16 @@ import axios from 'axios';
|
||||
import { LoggerUtils } from '../logger';
|
||||
import { ApiException } from './errors';
|
||||
export function handleApiException(error) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
||||
// only do something if not canceled, cancellation should be fine
|
||||
if (axios.isCancel(error)) {
|
||||
throw error;
|
||||
}
|
||||
else {
|
||||
throw new ApiException((_a = error.config.url) !== null && _a !== void 0 ? _a : null, (_c = (_b = error.response) === null || _b === void 0 ? void 0 : _b.status) !== null && _c !== void 0 ? _c : null, (_d = error.config.method) !== null && _d !== void 0 ? _d : null, {
|
||||
params: (_e = error.config.params) !== null && _e !== void 0 ? _e : null,
|
||||
data: (_f = error.config.data) !== null && _f !== void 0 ? _f : null,
|
||||
serverErrorData: (_j = (_h = (_g = error.response) === null || _g === void 0 ? void 0 : _g.data) === null || _h === void 0 ? void 0 : _h.data) !== null && _j !== void 0 ? _j : [],
|
||||
throw new ApiException((_b = (_a = error.config) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : null, (_d = (_c = error.response) === null || _c === void 0 ? void 0 : _c.status) !== null && _d !== void 0 ? _d : null, (_f = (_e = error.config) === null || _e === void 0 ? void 0 : _e.method) !== null && _f !== void 0 ? _f : null, {
|
||||
params: (_h = (_g = error.config) === null || _g === void 0 ? void 0 : _g.params) !== null && _h !== void 0 ? _h : null,
|
||||
data: (_k = (_j = error.config) === null || _j === void 0 ? void 0 : _j.data) !== null && _k !== void 0 ? _k : null,
|
||||
serverErrorData: (_m = (_l = error.response) === null || _l === void 0 ? void 0 : _l.data) !== null && _m !== void 0 ? _m : [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -4,7 +4,7 @@ import { AbilityScoreStatTypeEnum } from "../engine/Core";
|
||||
import { HelperUtils } from "../engine/Helper";
|
||||
import { RuleDataAccessors } from "../engine/RuleData";
|
||||
import { rulesEngineSelectors } from "../selectors";
|
||||
import { FeaturesManager } from './FeaturesManager';
|
||||
import { BaseManager } from './BaseManager';
|
||||
export const abilityDefinitionMap = new Map();
|
||||
const abilityMangerMap = new Map();
|
||||
export const getAbilityManager = (params) => {
|
||||
@@ -23,7 +23,7 @@ export const getAbilityManager = (params) => {
|
||||
abilityMangerMap.set(abilityId, newAbilityManager);
|
||||
return newAbilityManager;
|
||||
};
|
||||
export class AbilityManager extends FeaturesManager {
|
||||
export class AbilityManager extends BaseManager {
|
||||
constructor(params) {
|
||||
super(params);
|
||||
//Accessors
|
||||
@@ -87,7 +87,6 @@ export class AbilityManager extends FeaturesManager {
|
||||
getCompendiumText() {
|
||||
const abilityRuleData = this.getAbilityRuleData();
|
||||
// TODO: we should accessor all the things?
|
||||
// maybe gfs will be the time to do it?
|
||||
return abilityRuleData.compendiumText;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
});
|
||||
};
|
||||
import { orderBy } from 'lodash';
|
||||
import { AbilityAccessors } from "../engine/Ability";
|
||||
import { FeatureFlagEnum } from "../engine/FeatureFlagInfo";
|
||||
import { characterSelectors, featureFlagInfoSelectors, rulesEngineSelectors } from "../selectors";
|
||||
import { rulesEngineSelectors } from "../selectors";
|
||||
import { getAbilityManager } from './AbilityManager';
|
||||
import { FeatureFlagManager } from './FeatureFlagManager';
|
||||
// import { BlessingManager, getBlessingManager } from './FeatureManager';
|
||||
import { FeaturesManager } from './FeaturesManager';
|
||||
import { transformAbilityScores } from './utils/modifierTransformers';
|
||||
export class AttributesManager extends FeaturesManager {
|
||||
import { BaseManager } from './BaseManager';
|
||||
export class AttributesManager extends BaseManager {
|
||||
constructor(params) {
|
||||
super(params);
|
||||
this.getHighestAbilityScore = (abilities) => {
|
||||
@@ -28,31 +23,9 @@ export class AttributesManager extends FeaturesManager {
|
||||
getAbilities() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const abilities = rulesEngineSelectors.getAbilities(this.state);
|
||||
const featureFlagsManager = new FeatureFlagManager(featureFlagInfoSelectors.getFeatureFlagInfo(this.state));
|
||||
const hasAccessToBlessing = featureFlagsManager.getFlag(FeatureFlagEnum.RELEASE_GATE_GFS_BLESSINGS_UI);
|
||||
if (!hasAccessToBlessing) {
|
||||
return abilities.map((ability) => {
|
||||
return getAbilityManager(Object.assign(Object.assign({}, this.params), { ability }));
|
||||
});
|
||||
}
|
||||
else {
|
||||
// TODO: GFS this is all the wrong place
|
||||
// it should just be
|
||||
// const abilities = getCharacter.abilities ...
|
||||
const validGlobalModifiers = this.getValidGlobalModifiers();
|
||||
const baseStats = characterSelectors.getStats(this.state);
|
||||
const ruleData = rulesEngineSelectors.getRuleData(this.state);
|
||||
const { generatedFeature } = transformAbilityScores(validGlobalModifiers, baseStats, ruleData);
|
||||
// TODO: GFS THERE IS SOME MORE TO DO HERE
|
||||
const characterFeatureManagers = yield this.getCharacterFeatures();
|
||||
// TODO: GFS this should be part of the process and I should just ask for the the object here.
|
||||
const myAbilityState = this.processCharacter(generatedFeature);
|
||||
return abilities.map((ability) => {
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
const name = (_b = (_a = AbilityAccessors.getLabel(ability)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : 'The ability with no name';
|
||||
return getAbilityManager(Object.assign(Object.assign({}, this.params), { ability: Object.assign(Object.assign({}, ability), { maxStatScore: (_c = myAbilityState.attributes[name].max) !== null && _c !== void 0 ? _c : null, modifier: (_d = myAbilityState.attributes[name].modifier) !== null && _d !== void 0 ? _d : null, score: (_e = myAbilityState.attributes[name].value) !== null && _e !== void 0 ? _e : null, totalScore: (_f = myAbilityState.attributes[name].value) !== null && _f !== void 0 ? _f : null }) }));
|
||||
});
|
||||
}
|
||||
return abilities.map((ability) => {
|
||||
return getAbilityManager(Object.assign(Object.assign({}, this.params), { ability }));
|
||||
});
|
||||
});
|
||||
}
|
||||
getAbilitiesWithoutBlessings() {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { HelperUtils } from "../engine/Helper";
|
||||
import { getCurrentRulesEngineConfig } from '../config/utils';
|
||||
export const subscriptionsMap = new Map();
|
||||
export class BaseManager {
|
||||
constructor(params = {}) {
|
||||
this.randomId = 0; // helpful for debugging
|
||||
@@ -50,3 +52,26 @@ export class BaseManager {
|
||||
};
|
||||
}
|
||||
}
|
||||
// manage subscriptions
|
||||
BaseManager.subscribeToUpdates = ({ onUpdate, shouldInit = true }) => {
|
||||
// TODO: maybe from lib.
|
||||
const mapKey = HelperUtils.generateGuid();
|
||||
// connect to redux for updates
|
||||
let unsubscribe;
|
||||
if (getCurrentRulesEngineConfig().store) {
|
||||
const store = getCurrentRulesEngineConfig().store;
|
||||
unsubscribe = store === null || store === void 0 ? void 0 : store.subscribe(() => {
|
||||
onUpdate();
|
||||
});
|
||||
}
|
||||
subscriptionsMap.set(mapKey, onUpdate);
|
||||
if (shouldInit) {
|
||||
onUpdate();
|
||||
}
|
||||
return () => {
|
||||
subscriptionsMap.delete(mapKey);
|
||||
if (unsubscribe) {
|
||||
unsubscribe();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -15,27 +15,10 @@ import { FeatAccessors, FeatSimulators } from "../engine/Feat";
|
||||
import { HelperUtils } from "../engine/Helper";
|
||||
import { featDefinitionMap, getFeatManager } from "./FeatManager";
|
||||
import { apiCreatorSelectors, rulesEngineSelectors } from "../selectors";
|
||||
import { FeaturesManager } from './FeaturesManager';
|
||||
export class CharacterFeaturesManager extends FeaturesManager {
|
||||
import { BaseManager } from './BaseManager';
|
||||
export class CharacterFeaturesManager extends BaseManager {
|
||||
constructor(params) {
|
||||
super(params);
|
||||
//TODO GFS THIS!!!!
|
||||
this.getBlessings = () => __awaiter(this, void 0, void 0, function* () {
|
||||
// TODO get the blessings only?
|
||||
/**
|
||||
* this could be on the character obj under blessings key
|
||||
*/
|
||||
const blessingManagers = yield this.getCharacterFeatures();
|
||||
this.blessingManagers = blessingManagers;
|
||||
return blessingManagers;
|
||||
});
|
||||
this.getBlessing = (id) => { var _a; return (_a = this.blessingManagers.find((blessing) => id === blessing.getId())) !== null && _a !== void 0 ? _a : null; };
|
||||
// TODO is there value in moving these to hasFeatures and hasBlessings
|
||||
this.hasBlessings = () => __awaiter(this, void 0, void 0, function* () {
|
||||
const blessings = yield this.getBlessings();
|
||||
return blessings.length > 0;
|
||||
});
|
||||
this.hasBlessing = (blessing) => !!this.blessingManagers.find((characterBlessing) => characterBlessing.getId() === blessing.getId());
|
||||
this.handlePreferenceChange = (preferenceKey, value) => {
|
||||
const typedPrefKey = CharacterUtils.getPreferenceKey(preferenceKey);
|
||||
if (typedPrefKey !== null) {
|
||||
@@ -43,7 +26,6 @@ export class CharacterFeaturesManager extends FeaturesManager {
|
||||
}
|
||||
};
|
||||
this.params = params;
|
||||
this.blessingManagers = [];
|
||||
}
|
||||
mapFeatsToManagers(feats) {
|
||||
return feats.map((feat) => getFeatManager(Object.assign(Object.assign({}, this.params), { feat })));
|
||||
@@ -127,16 +109,6 @@ export class CharacterFeaturesManager extends FeaturesManager {
|
||||
return [];
|
||||
});
|
||||
}
|
||||
getBlessingShoppe(additionalConfig) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const blessings = yield this.getFeaturesShoppe({
|
||||
params: {
|
||||
category: 'blessing',
|
||||
},
|
||||
});
|
||||
return orderBy(blessings, (blessing) => blessing.getName());
|
||||
});
|
||||
}
|
||||
//UTILS
|
||||
// filter to only allow one of each simulated repeatable feat group
|
||||
filterUniqueSimulatedRepeatableFeats(feats, parentFeats) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { characterActions, serviceDataActions } from '../actions';
|
||||
import { ConfigUtils } from '../config';
|
||||
import { rulesEngineConfig } from '../config/utils';
|
||||
import { ContainerAccessors } from '../engine/Container';
|
||||
import { ContainerAccessors, ContainerValidators } from '../engine/Container';
|
||||
import { CoreUtils, CURRENCY_VALUE } from '../engine/Core';
|
||||
import { DefinitionHacks } from '../engine/Definition';
|
||||
import { FormatUtils } from '../engine/Format';
|
||||
@@ -22,6 +22,7 @@ export class CoinManager extends InventoryManager {
|
||||
if (!isEmpty && container) {
|
||||
const destinationEntityTypeId = ContainerAccessors.getContainerType(container);
|
||||
const destinationEntityId = ContainerAccessors.getMappingId(container);
|
||||
const isDestinationContainerShared = ContainerValidators.validateIsShared(DefinitionHacks.hack__generateDefinitionKey(destinationEntityTypeId, destinationEntityId), containerLookup);
|
||||
const currentCoins = this.getContainerCoin(containerDefinitionKey);
|
||||
if (multiplier === 1) {
|
||||
const validAddCoin = this.calculateAddCoinPayload(currentCoins, coin.cp || 0, coin.ep || 0, coin.gp || 0, coin.pp || 0, coin.sp || 0);
|
||||
@@ -39,6 +40,11 @@ export class CoinManager extends InventoryManager {
|
||||
}
|
||||
this.dispatch(characterActions.currencyTransactionSet(Object.assign(Object.assign({}, adjustedCurrency), { destinationEntityId: destinationEntityId, destinationEntityTypeId: destinationEntityTypeId }), () => {
|
||||
typeof onSuccess === 'function' && onSuccess();
|
||||
if (isDestinationContainerShared) {
|
||||
const data = {};
|
||||
const eventType = this.EVENT_TYPES.ITEM_SHARED_FULFILLED;
|
||||
this.sendMessage({ data, eventType });
|
||||
}
|
||||
}, () => {
|
||||
typeof onError === 'function' && onError();
|
||||
}));
|
||||
@@ -238,25 +244,6 @@ export class CoinManager extends InventoryManager {
|
||||
}
|
||||
};
|
||||
// Validators
|
||||
this.canAddCoin = (coin, containerDefinitionKey) => {
|
||||
const containerLookup = rulesEngineSelectors.getContainerLookup(this.state);
|
||||
const container = HelperUtils.lookupDataOrFallback(containerLookup, containerDefinitionKey);
|
||||
const isShared = container ? ContainerAccessors.isShared(container) : false;
|
||||
if (isShared && this.isSharingTurnedDeleteOnly()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
this.canRemoveCoin = (coin, containerDefinitionKey) => {
|
||||
const containerLookup = rulesEngineSelectors.getContainerLookup(this.state);
|
||||
const container = HelperUtils.lookupDataOrFallback(containerLookup, containerDefinitionKey);
|
||||
const isShared = container ? ContainerAccessors.isShared(container) : false;
|
||||
if (isShared && this.isSharingTurnedDeleteOnly()) {
|
||||
let hasNegatives = Object.values(coin).some((value) => value < 0);
|
||||
return !hasNegatives;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
this.canUseCointainers = () => {
|
||||
const rulesEngineConfig = ConfigUtils.getCurrentRulesEngineConfig();
|
||||
const preferences = rulesEngineSelectors.getPreferences(this.state);
|
||||
|
||||
@@ -144,6 +144,7 @@ export class ContainerManager extends MessageManager {
|
||||
this.getCoin = () => ContainerAccessors.getCoin(this.container);
|
||||
// Validators
|
||||
this.isCharacterContainer = () => ContainerValidators.isCharacterContainer(this.container);
|
||||
this.isPartyContainer = () => ContainerValidators.isPartyContainer(this.container);
|
||||
this.isSharedOtherContainerDefinitionKey = (otherContainerDefinitionKey) => {
|
||||
const containerLookup = rulesEngineSelectors.getContainerLookup(this.state);
|
||||
return ContainerValidators.validateIsShared(otherContainerDefinitionKey, containerLookup);
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
import { ApiRequests } from "../api";
|
||||
export class FeatureManager {
|
||||
constructor(params) {
|
||||
this.handleAcceptOnSuccess = (onSuccess) => {
|
||||
typeof onSuccess === 'function' && onSuccess();
|
||||
};
|
||||
this.handleRejectOnError = (onError) => {
|
||||
typeof onError === 'function' && onError();
|
||||
};
|
||||
this.handleAdd = (onSuccess, onError) => __awaiter(this, void 0, void 0, function* () {
|
||||
yield ApiRequests.postCharacterFeature({ featureId: this.getId() });
|
||||
this.bustCache();
|
||||
this.handleAcceptOnSuccess(onSuccess);
|
||||
this.runSubscriptions();
|
||||
});
|
||||
this.handleRemove = (onSuccess, onError) => __awaiter(this, void 0, void 0, function* () {
|
||||
// featureManagerMap.delete(this.getId()); //TODO GFS do we still need to do it this way
|
||||
yield ApiRequests.deleteCharacterFeature({ featureId: this.getId() });
|
||||
this.bustCache();
|
||||
this.handleAcceptOnSuccess(onSuccess);
|
||||
this.runSubscriptions();
|
||||
});
|
||||
//Accessors
|
||||
this.getId = () => this.feature.featureId;
|
||||
this.getStatements = () => this.feature.statements;
|
||||
this.getFeature = () => this.feature;
|
||||
// Label accessors
|
||||
// TODO what are the default/standard ones?
|
||||
//TODO GFS: talk about role.toLowerCase
|
||||
this.getName = () => { var _a, _b; return (_b = (_a = this.feature.labels.find((label) => label.role.toLowerCase() === 'name')) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 'FEATURE WITH NO NAME'; }; //TODO GFS ENUMS for all of these
|
||||
this.getDescription = () => { var _a, _b; return (_b = (_a = this.feature.labels.find((label) => label.role.toLowerCase() === 'description')) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ''; };
|
||||
this.params = params;
|
||||
this.feature = params.feature;
|
||||
this.runSubscriptions = params.runSubscriptions;
|
||||
this.bustCache = params.bustCache;
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
import { generateCharacterState } from '@dndbeyond/character-gfs';
|
||||
import { ApiRequests } from "../api";
|
||||
import { ApiAdapterUtils } from "../apiAdapter";
|
||||
import { getCurrentRulesEngineConfig } from "../config/utils";
|
||||
import { HelperUtils } from "../engine/Helper";
|
||||
import { apiCreatorSelectors, rulesEngineSelectors } from "../selectors";
|
||||
import { TypeScriptUtils } from "../utils";
|
||||
import { FeatureManager } from './FeatureManager';
|
||||
import { MessageManager } from './MessageManager';
|
||||
export const featureMap = new Map();
|
||||
export const subscriptionsMap = new Map();
|
||||
const featureManagerMap = new Map();
|
||||
export const getFeatureManager = (params) => {
|
||||
const { feature } = params;
|
||||
const featureId = feature.featureId; //TODO GFS Accessors?
|
||||
if (featureManagerMap.has(featureId)) {
|
||||
const FeatureManager = featureManagerMap.get(featureId);
|
||||
if (!FeatureManager) {
|
||||
throw new Error(`FeatureManager for feature ${featureId} is null`);
|
||||
}
|
||||
if (FeatureManager.params.feature === feature) {
|
||||
return FeatureManager;
|
||||
}
|
||||
}
|
||||
const newFeatureManager = new FeatureManager(params);
|
||||
featureManagerMap.set(featureId, newFeatureManager);
|
||||
return newFeatureManager;
|
||||
};
|
||||
// we want this cached across all instances of the FeaturesManager
|
||||
let rootCharacterFeatureManagers = null; // needs
|
||||
let allCharacterFeatureManagers = null; // needs
|
||||
let availableFeaturesResponseData = null; // not required to bust
|
||||
export class FeaturesManager extends MessageManager {
|
||||
constructor(params = {}) {
|
||||
super(params);
|
||||
// these values are used for caching and may need to be busted when the character changes
|
||||
this.randomId = 0; // helpful for debugging
|
||||
this.runSubscriptions = () => {
|
||||
subscriptionsMap.forEach((cb) => cb());
|
||||
};
|
||||
this.transformLoadedFeatures = (features) => {
|
||||
return features.map((feature) => {
|
||||
featureMap.set(feature.featureId, feature);
|
||||
return getFeatureManager({ feature, runSubscriptions: this.runSubscriptions, bustCache: this.bustCache });
|
||||
});
|
||||
};
|
||||
this.getAvailableFeatures = (additionalConfig) => __awaiter(this, void 0, void 0, function* () {
|
||||
var _a;
|
||||
if (availableFeaturesResponseData) {
|
||||
return availableFeaturesResponseData;
|
||||
}
|
||||
const loadFeatures = apiCreatorSelectors.makeLoadAvailableFeatures(this.state);
|
||||
const response = yield loadFeatures(additionalConfig);
|
||||
availableFeaturesResponseData = (_a = ApiAdapterUtils.getResponseData(response)) !== null && _a !== void 0 ? _a : [];
|
||||
availableFeaturesResponseData.map((feature) => {
|
||||
featureMap.set(feature.featureId, feature);
|
||||
});
|
||||
return availableFeaturesResponseData;
|
||||
});
|
||||
this.getFeaturesShoppe = (additionalConfig) => __awaiter(this, void 0, void 0, function* () {
|
||||
let data = yield this.getAvailableFeatures(additionalConfig);
|
||||
if (data) {
|
||||
return this.transformLoadedFeatures(data);
|
||||
}
|
||||
return [];
|
||||
});
|
||||
this.getAllCharacterFeatures = (rootCharacterFeatureIds) => __awaiter(this, void 0, void 0, function* () {
|
||||
var _b;
|
||||
if (allCharacterFeatureManagers) {
|
||||
return allCharacterFeatureManagers;
|
||||
}
|
||||
const allFeaturesAndSubFeatureResponse = yield ApiRequests.postFeaturesAndSubfeatures({
|
||||
featureIds: rootCharacterFeatureIds,
|
||||
});
|
||||
const allFeaturesAndSubFeatureData = (_b = ApiAdapterUtils.getResponseData(allFeaturesAndSubFeatureResponse)) !== null && _b !== void 0 ? _b : [];
|
||||
allFeaturesAndSubFeatureData.map((feature) => {
|
||||
featureMap.set(feature.featureId, feature);
|
||||
});
|
||||
const allFeaturesAndSubFeatureIds = allFeaturesAndSubFeatureData.map((feature) => feature.featureId);
|
||||
allCharacterFeatureManagers = allFeaturesAndSubFeatureIds
|
||||
.map((id) => {
|
||||
const feature = featureMap.get(id);
|
||||
return feature
|
||||
? getFeatureManager({ feature, runSubscriptions: this.runSubscriptions, bustCache: this.bustCache })
|
||||
: null;
|
||||
})
|
||||
.filter(TypeScriptUtils.isNotNullOrUndefined);
|
||||
return allCharacterFeatureManagers || [];
|
||||
});
|
||||
this.bustCache = () => __awaiter(this, void 0, void 0, function* () {
|
||||
availableFeaturesResponseData = null;
|
||||
rootCharacterFeatureManagers = null;
|
||||
allCharacterFeatureManagers = null;
|
||||
});
|
||||
this.getCharacterFeatures = () => __awaiter(this, void 0, void 0, function* () {
|
||||
var _c;
|
||||
if (rootCharacterFeatureManagers) {
|
||||
return rootCharacterFeatureManagers;
|
||||
}
|
||||
const characterId = rulesEngineSelectors.getId(this.state);
|
||||
const characterFeatureResponse = yield ApiRequests.getCharacterFeatures({ characterId });
|
||||
const characterFeatureData = (_c = ApiAdapterUtils.getResponseData(characterFeatureResponse)) !== null && _c !== void 0 ? _c : [];
|
||||
const characterFeatureIds = characterFeatureData.map((feature) => feature.id);
|
||||
if (characterFeatureIds.length > 0) {
|
||||
yield this.getAvailableFeatures({
|
||||
params: {
|
||||
category: 'blessing',
|
||||
},
|
||||
});
|
||||
yield this.getAllCharacterFeatures(characterFeatureIds);
|
||||
}
|
||||
rootCharacterFeatureManagers = characterFeatureIds
|
||||
.map((id) => {
|
||||
const feature = featureMap.get(id);
|
||||
return feature
|
||||
? getFeatureManager({ feature, runSubscriptions: this.runSubscriptions, bustCache: this.bustCache })
|
||||
: null;
|
||||
})
|
||||
.filter(TypeScriptUtils.isNotNullOrUndefined);
|
||||
return rootCharacterFeatureManagers;
|
||||
});
|
||||
this.processCharacter = (generatedFeature) => {
|
||||
featureMap.set(generatedFeature.featureId, generatedFeature);
|
||||
return generateCharacterState({
|
||||
rootFeatureIds: [
|
||||
generatedFeature.featureId,
|
||||
...((rootCharacterFeatureManagers === null || rootCharacterFeatureManagers === void 0 ? void 0 : rootCharacterFeatureManagers.map((featureManager) => featureManager.getId())) || []),
|
||||
],
|
||||
featureMap,
|
||||
});
|
||||
};
|
||||
this.randomId = Math.floor(Math.random() * 1000000);
|
||||
}
|
||||
}
|
||||
// manage subscriptions
|
||||
FeaturesManager.subscribeToUpdates = ({ onUpdate, shouldInit = true }) => {
|
||||
// TODO: maybe from lib.
|
||||
const mapKey = HelperUtils.generateGuid();
|
||||
// connect to redux for updates
|
||||
let unsubscribe;
|
||||
if (getCurrentRulesEngineConfig().store) {
|
||||
const store = getCurrentRulesEngineConfig().store;
|
||||
unsubscribe = store === null || store === void 0 ? void 0 : store.subscribe(() => {
|
||||
onUpdate();
|
||||
});
|
||||
}
|
||||
subscriptionsMap.set(mapKey, onUpdate);
|
||||
if (shouldInit) {
|
||||
onUpdate();
|
||||
}
|
||||
return () => {
|
||||
subscriptionsMap.delete(mapKey);
|
||||
if (unsubscribe) {
|
||||
unsubscribe();
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
};
|
||||
import * as ApiAdapterUtils from "../apiAdapter/utils";
|
||||
import { characterActions } from '../actions';
|
||||
import { ContainerAccessors, ContainerGenerators, ContainerTypeEnum, ContainerUtils, ContainerValidators, } from '../engine/Container';
|
||||
import { ContainerGenerators, ContainerTypeEnum, ContainerUtils, ContainerValidators, } from '../engine/Container';
|
||||
import { EntityTypeEnum, DefaultCharacterName } from '../engine/Core';
|
||||
import { DefinitionHacks } from '../engine/Definition';
|
||||
import { HelperUtils } from '../engine/Helper';
|
||||
@@ -19,6 +19,15 @@ import { ValueHacks } from '../engine/Value';
|
||||
import { apiCreatorSelectors, characterSelectors, rulesEngineSelectors } from '../selectors';
|
||||
import { getContainerManager } from './ContainerManager';
|
||||
import { PartyManager } from './PartyManager';
|
||||
let inventoryManager = null;
|
||||
let itemShoppe = null;
|
||||
export function getInventoryManager(params) {
|
||||
if (inventoryManager) {
|
||||
return inventoryManager;
|
||||
}
|
||||
inventoryManager = new InventoryManager(params);
|
||||
return inventoryManager;
|
||||
}
|
||||
export class InventoryManager extends PartyManager {
|
||||
constructor(params) {
|
||||
super(params);
|
||||
@@ -89,9 +98,11 @@ export class InventoryManager extends PartyManager {
|
||||
this.dispatch(characterActions.customItemDestroy(ItemAccessors.getDefinitionId(item), ItemAccessors.getMappingId(item), isShared ? this.getPartyId() : null, this.handleAcceptOnSuccess(isShared, onSuccess)));
|
||||
}
|
||||
else {
|
||||
const itemPlans = rulesEngineSelectors.getAvailableItemPlans(this.state);
|
||||
const isContainer = ItemAccessors.isContainer(item);
|
||||
const infusion = ItemAccessors.getInfusion(item);
|
||||
this.dispatch(characterActions.itemDestroy(ItemAccessors.getMappingId(item), isContainer && infusion ? false : true, this.handleAcceptOnSuccess(isShared, onSuccess)));
|
||||
const itemPlan = ItemUtils.getItemPlan(item, itemPlans);
|
||||
this.dispatch(characterActions.itemDestroy(ItemAccessors.getMappingId(item), isContainer && (infusion || itemPlan) ? false : true, this.handleAcceptOnSuccess(isShared, onSuccess)));
|
||||
}
|
||||
};
|
||||
/**
|
||||
@@ -158,9 +169,19 @@ export class InventoryManager extends PartyManager {
|
||||
this.dispatch(characterActions.itemCustomizationsDelete(ItemAccessors.getMappingId(item), ItemAccessors.getMappingEntityTypeId(item), isShared ? this.getPartyId() : null, this.handleAcceptOnSuccess(isShared, onSuccess)));
|
||||
};
|
||||
// Validators
|
||||
this.canAddToContainer = (container) => {
|
||||
const isShared = ContainerAccessors.isShared(container);
|
||||
return !isShared || this.isSharingTurnedOn();
|
||||
// check for party inventory restrictions for isClaimable if its a shared item
|
||||
this.isClaimRestricted = (item) => {
|
||||
const isShared = this.isShared(item);
|
||||
if (!isShared) {
|
||||
return false;
|
||||
}
|
||||
const partyInventoryRestrictions = ItemAccessors.getPartyInventoryRestrictions(item);
|
||||
if ((partyInventoryRestrictions === null || partyInventoryRestrictions === void 0 ? void 0 : partyInventoryRestrictions.length) > 0) {
|
||||
if (partyInventoryRestrictions.some((restriction) => !restriction.isClaimable && restriction.characterId !== rulesEngineSelectors.getId(this.state))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
/**
|
||||
* @deprecated
|
||||
@@ -170,10 +191,7 @@ export class InventoryManager extends PartyManager {
|
||||
const canEquip = ItemAccessors.canEquip(item);
|
||||
const isEquipped = ItemAccessors.isEquipped(item);
|
||||
if (isShared && canEquip) {
|
||||
if (this.isSharingTurnedOn() || (this.isSharingTurnedDeleteOnly() && isEquipped)) {
|
||||
return isEquipped ? this.isEquippedToCurrentCharacter(item) : true;
|
||||
}
|
||||
return false;
|
||||
return isEquipped ? this.isEquippedToCurrentCharacter(item) : true;
|
||||
}
|
||||
return canEquip;
|
||||
};
|
||||
@@ -184,9 +202,6 @@ export class InventoryManager extends PartyManager {
|
||||
const isAttuned = ItemAccessors.isAttuned(item);
|
||||
if (!isAttuned) {
|
||||
if (isShared) {
|
||||
if (this.isSharingTurnedDeleteOnly()) {
|
||||
return false;
|
||||
}
|
||||
return this.isEquippedToCurrentCharacter(item) && !hasMaxAttunedItems && canAttune;
|
||||
}
|
||||
return !hasMaxAttunedItems && canAttune;
|
||||
@@ -199,30 +214,18 @@ export class InventoryManager extends PartyManager {
|
||||
}
|
||||
};
|
||||
this.canModifyQuantity = (item) => {
|
||||
const isShared = this.isShared(item);
|
||||
const isStackable = ItemAccessors.isStackable(item);
|
||||
if (isShared && isStackable) {
|
||||
return this.isSharingTurnedOn();
|
||||
}
|
||||
return isStackable;
|
||||
};
|
||||
this.canCustomizeItem = (item) => {
|
||||
const isShared = this.isShared(item);
|
||||
if (isShared) {
|
||||
return this.isSharingTurnedOn();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
this.canUseItemCharges = (item) => {
|
||||
const isShared = this.isShared(item);
|
||||
if (isShared) {
|
||||
return this.isSharingTurnedOn();
|
||||
}
|
||||
return !!ItemAccessors.getLimitedUse(item);
|
||||
};
|
||||
this.canRemoveItem = (item) => {
|
||||
const isShared = this.isShared(item);
|
||||
if (isShared) {
|
||||
if (this.isClaimRestricted(item)) {
|
||||
return false;
|
||||
}
|
||||
const infusion = ItemAccessors.getInfusion(item);
|
||||
if (infusion) {
|
||||
const infusionCharacterId = InfusionAccessors.getCharacterId(infusion);
|
||||
@@ -230,16 +233,22 @@ export class InventoryManager extends PartyManager {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ItemAccessors.isEquipped(item)
|
||||
? this.isSharingTurnedOnOrDeleteOnly() && this.isEquippedToCurrentCharacter(item)
|
||||
: this.isSharingTurnedOnOrDeleteOnly();
|
||||
return ItemAccessors.isEquipped(item) ? this.isEquippedToCurrentCharacter(item) : true;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
this.canMoveItem = (item) => {
|
||||
// If you are changing this, you may want to change the canRemoveItem above
|
||||
const isContainer = ItemAccessors.isContainer(item);
|
||||
if (isContainer) {
|
||||
return false;
|
||||
}
|
||||
const isShared = this.isShared(item);
|
||||
if (isShared) {
|
||||
if (this.isClaimRestricted(item)) {
|
||||
return false;
|
||||
}
|
||||
//Might be able to remove this in favor of the above restriction check
|
||||
const infusion = ItemAccessors.getInfusion(item);
|
||||
if (infusion) {
|
||||
const infusionCharacterId = InfusionAccessors.getCharacterId(infusion);
|
||||
@@ -247,26 +256,23 @@ export class InventoryManager extends PartyManager {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ItemAccessors.isEquipped(item)
|
||||
? this.isSharingTurnedOnOrDeleteOnly() && this.isEquippedToCurrentCharacter(item)
|
||||
: this.isSharingTurnedOnOrDeleteOnly();
|
||||
}
|
||||
else if (this.isSharingTurnedDeleteOnly()) {
|
||||
const localContainers = rulesEngineSelectors.getCharacterInventoryContainers(this.state);
|
||||
return localContainers.length > 1;
|
||||
return ItemAccessors.isEquipped(item) ? this.isEquippedToCurrentCharacter(item) : true;
|
||||
}
|
||||
const containerLookup = rulesEngineSelectors.getContainerLookup(this.state);
|
||||
return Object.keys(containerLookup).length > 1;
|
||||
};
|
||||
this.canShareItem = (item) => {
|
||||
//Can a container item be moved into the party inventory?
|
||||
this.canShareContainer = (item) => {
|
||||
//check that the item is a container
|
||||
const isContainer = ItemAccessors.isContainer(item);
|
||||
if (!isContainer) {
|
||||
return false;
|
||||
}
|
||||
const isShared = this.isShared(item);
|
||||
return !isShared && this.isSharingTurnedOn();
|
||||
return !isShared;
|
||||
};
|
||||
this.canClaimItem = (item) => {
|
||||
//Can a container item be "claimed" out of the party inventory?
|
||||
this.canClaimContainer = (item) => {
|
||||
const isContainer = ItemAccessors.isContainer(item);
|
||||
if (!isContainer || (ItemAccessors.isEquipped(item) && !this.isEquippedToCurrentCharacter(item))) {
|
||||
return false;
|
||||
@@ -278,6 +284,9 @@ export class InventoryManager extends PartyManager {
|
||||
const definitionKey = DefinitionHacks.hack__generateDefinitionKey(EntityTypeEnum.ITEM, ItemAccessors.getMappingId(item));
|
||||
const container = HelperUtils.lookupDataOrFallback(containerLookup, definitionKey);
|
||||
if (container) {
|
||||
if (this.isClaimRestricted(item)) {
|
||||
return false;
|
||||
}
|
||||
const infusion = ItemAccessors.getInfusion(item);
|
||||
if (infusion) {
|
||||
const infusionCharacterId = InfusionAccessors.getCharacterId(infusion);
|
||||
@@ -292,7 +301,7 @@ export class InventoryManager extends PartyManager {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return this.isSharingTurnedOnOrDeleteOnly();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -370,6 +379,11 @@ export class InventoryManager extends PartyManager {
|
||||
getInventoryShoppe({ onSuccess, additionalApiConfig, }) {
|
||||
var _a, _b;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// If we already have the item shoppe, return it
|
||||
if (itemShoppe) {
|
||||
onSuccess(itemShoppe);
|
||||
return itemShoppe;
|
||||
}
|
||||
const characterId = characterSelectors.getId(this.state);
|
||||
const loadItems = apiCreatorSelectors.makeLoadAvailableItems(this.state);
|
||||
//set up pagination params
|
||||
@@ -404,6 +418,7 @@ export class InventoryManager extends PartyManager {
|
||||
const ruleData = rulesEngineSelectors.getRuleData(this.state);
|
||||
const shoppeContainer = ContainerGenerators.generateContainer(-1, ContainerTypeEnum.SHOPPE, 'Item Shoppe', transformedItems, false, null, null, characterId, null, ruleData);
|
||||
const shoppeManager = getContainerManager(Object.assign(Object.assign({}, this.params), { container: shoppeContainer, overrideItems: transformedItems }));
|
||||
itemShoppe = shoppeManager;
|
||||
onSuccess(shoppeManager);
|
||||
return shoppeManager;
|
||||
});
|
||||
|
||||
@@ -57,7 +57,8 @@ export class ItemManager extends PartyManager {
|
||||
else {
|
||||
const isContainer = this.isContainer();
|
||||
const infusion = this.getInfusion();
|
||||
this.dispatch(characterActions.itemDestroy(this.getMappingId(), isContainer && infusion ? false : true, this.handleAcceptOnSuccess(isShared, onSuccess)));
|
||||
const itemPlan = this.getItemPlan();
|
||||
this.dispatch(characterActions.itemDestroy(this.getMappingId(), isContainer && (infusion || itemPlan) ? false : true, this.handleAcceptOnSuccess(isShared, onSuccess)));
|
||||
}
|
||||
};
|
||||
this.handleMove = ({ containerDefinitionKey }, onSuccess, onError) => {
|
||||
@@ -124,6 +125,13 @@ export class ItemManager extends PartyManager {
|
||||
this.getPrimarySourceCategoryId = () => ItemAccessors.getPrimarySourceCategoryId(this.item);
|
||||
this.getSecondarySourceCategoryIds = () => ItemAccessors.getSecondarySourceCategoryIds(this.item);
|
||||
this.getAllSourceCategoryIds = () => ItemUtils.getAllSourceCategoryIds(this.item);
|
||||
this.getDefinitionKey = () => { var _a; return (_a = ItemAccessors.getDefinition(this.item)) === null || _a === void 0 ? void 0 : _a.definitionKey; };
|
||||
this.getOriginDefinitionKey = () => ItemAccessors.getOriginDefinitionKey(this.item);
|
||||
this.getDescription = () => ItemAccessors.getDescription(this.item);
|
||||
this.getRarity = () => ItemAccessors.getRarity(this.item);
|
||||
this.canAttune = () => ItemAccessors.canAttune(this.item);
|
||||
this.getAttunementDescription = () => ItemAccessors.getAttunementDescription(this.item);
|
||||
this.getPartyInventoryRestrictions = () => ItemAccessors.getPartyInventoryRestrictions(this.item);
|
||||
// Validator
|
||||
this.isShared = () => this.requiresContainer().isShared();
|
||||
this.isArmorContract = () => ItemUtils.isArmorContract(this.item);
|
||||
@@ -134,10 +142,7 @@ export class ItemManager extends PartyManager {
|
||||
const canEquip = ItemAccessors.canEquip(this.item);
|
||||
const isEquipped = ItemAccessors.isEquipped(this.item);
|
||||
if (isShared && canEquip) {
|
||||
if (this.isSharingTurnedOn() || (this.isSharingTurnedDeleteOnly() && isEquipped)) {
|
||||
return isEquipped ? this.isEquippedToCurrentCharacter() : true;
|
||||
}
|
||||
return false;
|
||||
return isEquipped ? this.isEquippedToCurrentCharacter() : true;
|
||||
}
|
||||
return canEquip;
|
||||
};
|
||||
@@ -145,6 +150,7 @@ export class ItemManager extends PartyManager {
|
||||
const characterId = rulesEngineSelectors.getId(this.state);
|
||||
return ItemValidators.isEquippedToCurrentCharacter(this.item, characterId);
|
||||
};
|
||||
this.isReplicated = () => ItemUtils.isReplicated(this.item);
|
||||
// Utils
|
||||
this.getRarityLevel = () => ItemUtils.getRarityLevel(this.item);
|
||||
this.generateContainerDefinitionKey = () => {
|
||||
@@ -161,12 +167,61 @@ export class ItemManager extends PartyManager {
|
||||
}
|
||||
return DefaultCharacterName;
|
||||
};
|
||||
this.getItemPlan = () => {
|
||||
const itemPlans = rulesEngineSelectors.getAvailableItemPlans(this.state);
|
||||
return ItemUtils.getItemPlan(this.item, itemPlans);
|
||||
};
|
||||
this.getNotes = () => {
|
||||
const weaponSpellDamageGroups = rulesEngineSelectors.getWeaponSpellDamageGroups(this.state);
|
||||
const ruleData = rulesEngineSelectors.getRuleData(this.state);
|
||||
const abilityLookup = rulesEngineSelectors.getAbilityLookup(this.state);
|
||||
const proficiencyBonus = rulesEngineSelectors.getProficiencyBonus(this.state);
|
||||
return ItemNotes.getNoteComponents(this.item, weaponSpellDamageGroups, ruleData, abilityLookup, proficiencyBonus);
|
||||
return ItemNotes.getNoteComponents(this.item, weaponSpellDamageGroups, ruleData, abilityLookup, proficiencyBonus, this.getItemPlan());
|
||||
};
|
||||
this.getIntroText = () => {
|
||||
const strings = [];
|
||||
const subType = this.getSubType();
|
||||
const rarity = this.getRarity();
|
||||
const attunementDescription = this.getAttunementDescription();
|
||||
let type = this.getType();
|
||||
if (this.isWeaponContract()) {
|
||||
if (this.isMagic()) {
|
||||
type = `Weapon (${type})`;
|
||||
}
|
||||
else {
|
||||
type = 'Weapon';
|
||||
}
|
||||
}
|
||||
else if (this.isArmorContract()) {
|
||||
if (this.isMagic()) {
|
||||
type = `Armor (${this.getBaseArmorName()})`;
|
||||
}
|
||||
else {
|
||||
type = 'Armor';
|
||||
}
|
||||
}
|
||||
else if (this.isGearContract()) {
|
||||
type = subType || type;
|
||||
}
|
||||
else if (this.isCustom()) {
|
||||
type = 'Custom';
|
||||
}
|
||||
if (this.isLegacy()) {
|
||||
strings.push('Legacy • ');
|
||||
}
|
||||
if (type) {
|
||||
strings.push(type);
|
||||
}
|
||||
if (!this.isCustom() && rarity) {
|
||||
strings.push(`, ${rarity}`);
|
||||
}
|
||||
if (this.canAttune()) {
|
||||
strings.push(` (requires attunement${attunementDescription ? ` by a ${attunementDescription}` : ''})`);
|
||||
}
|
||||
if (this.isContainer()) {
|
||||
strings.push(', container');
|
||||
}
|
||||
return strings.join('');
|
||||
};
|
||||
this.getMetaText = () => {
|
||||
const appliedWeaponReplacementStats = this.getAppliedWeaponReplacementStats();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { serviceDataActions } from '../actions';
|
||||
import { CampaignAccessors, CampaignUtils } from '../engine/Campaign';
|
||||
import { PartyInventorySharingStateEnum } from '../engine/Campaign/constants';
|
||||
import { serviceDataSelectors } from '../selectors';
|
||||
import { MessageManager } from './MessageManager';
|
||||
export class PartyManager extends MessageManager {
|
||||
@@ -28,11 +27,6 @@ export class PartyManager extends MessageManager {
|
||||
};
|
||||
};
|
||||
// Accessors
|
||||
this.getSharingState = () => {
|
||||
var _a;
|
||||
const partyInfo = serviceDataSelectors.getPartyInfo(this.state);
|
||||
return (_a = (partyInfo && CampaignAccessors.getSharingState(partyInfo))) !== null && _a !== void 0 ? _a : PartyInventorySharingStateEnum.OFF; // if we get null return off
|
||||
};
|
||||
this.getPartyId = () => {
|
||||
const partyInfo = serviceDataSelectors.getPartyInfo(this.state);
|
||||
return partyInfo ? CampaignAccessors.getId(partyInfo) : null;
|
||||
@@ -44,11 +38,6 @@ export class PartyManager extends MessageManager {
|
||||
}
|
||||
return '';
|
||||
};
|
||||
// Validators
|
||||
this.isSharingTurnedOn = () => this.getSharingState() === PartyInventorySharingStateEnum.ON;
|
||||
this.isSharingTurnedOff = () => this.getSharingState() === PartyInventorySharingStateEnum.OFF;
|
||||
this.isSharingTurnedDeleteOnly = () => this.getSharingState() === PartyInventorySharingStateEnum.DELETE_ONLY;
|
||||
this.isSharingTurnedOnOrDeleteOnly = () => CampaignUtils.isSharingStateActive(this.getSharingState());
|
||||
this.addSubscriptions({
|
||||
[this.EVENT_TYPES.ITEM_SHARED_FULFILLED]: this.updateSharedInventory,
|
||||
});
|
||||
|
||||
-148
@@ -1,148 +0,0 @@
|
||||
import { ExpressionOperators, StatementOperators } from '@dndbeyond/character-gfs';
|
||||
import { ModifierAccessors, ModifierTypeEnum, ModifierValidators } from "../../../engine/Modifier";
|
||||
import { RuleDataUtils } from "../../../engine/RuleData";
|
||||
export function transformAbilityScores(validGlobalModifiers, baseStats, ruleData) {
|
||||
const abilityScoreModifiers = validGlobalModifiers.filter((modifier) => {
|
||||
return (ModifierValidators.isValidStatScoreModifier(modifier, 1) ||
|
||||
ModifierValidators.isValidStatScoreModifier(modifier, 2) ||
|
||||
ModifierValidators.isValidStatScoreModifier(modifier, 3) ||
|
||||
ModifierValidators.isValidStatScoreModifier(modifier, 4) ||
|
||||
ModifierValidators.isValidStatScoreModifier(modifier, 5) ||
|
||||
ModifierValidators.isValidStatScoreModifier(modifier, 6));
|
||||
});
|
||||
const baseAbilityScores = baseStats.flatMap((stat) => {
|
||||
var _a, _b, _c;
|
||||
if (stat.id) {
|
||||
const statName = (_b = (_a = RuleDataUtils.getStatNameById(stat.id, ruleData, true)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : '';
|
||||
stat.value = (_c = stat.value) !== null && _c !== void 0 ? _c : 0;
|
||||
// Math.floor((stat.value - 10) / 2)
|
||||
return [
|
||||
{
|
||||
precedence: 0.5,
|
||||
target: ['attributes', statName, 'value'],
|
||||
operator: StatementOperators.SET,
|
||||
operand: {
|
||||
operator: ExpressionOperators.STATIC_VALUE,
|
||||
values: [stat.value],
|
||||
operands: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
precedence: 0.5,
|
||||
target: ['attributes', statName, 'modifier'],
|
||||
operator: StatementOperators.SET,
|
||||
operand: {
|
||||
operator: ExpressionOperators.FLOOR,
|
||||
values: null,
|
||||
operands: [
|
||||
{
|
||||
operator: ExpressionOperators.MULTIPLY,
|
||||
values: null,
|
||||
operands: [
|
||||
{
|
||||
operator: ExpressionOperators.STATIC_VALUE,
|
||||
values: [0.5],
|
||||
operands: null,
|
||||
},
|
||||
{
|
||||
operator: ExpressionOperators.ADD,
|
||||
values: null,
|
||||
operands: [
|
||||
{
|
||||
operator: ExpressionOperators.STATIC_VALUE,
|
||||
values: [-10],
|
||||
operands: null,
|
||||
},
|
||||
{
|
||||
operator: ExpressionOperators.DYNAMIC_VALUE,
|
||||
values: ['attributes', statName, 'value'],
|
||||
operands: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
precedence: 0.5,
|
||||
target: ['attributes', statName, 'max'],
|
||||
operator: StatementOperators.SET,
|
||||
operand: {
|
||||
operator: ExpressionOperators.STATIC_VALUE,
|
||||
values: [20],
|
||||
operands: null,
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
return [];
|
||||
});
|
||||
const gfsAbilityScores = abilityScoreModifiers.map((abilityScoreModifier) => {
|
||||
var _a, _b, _c, _d;
|
||||
const modifierType = ModifierAccessors.getType(abilityScoreModifier);
|
||||
switch (modifierType) {
|
||||
case ModifierTypeEnum.SET:
|
||||
return {
|
||||
precedence: 0.5,
|
||||
target: [
|
||||
'attributes',
|
||||
(_a = ModifierAccessors.getSubType(abilityScoreModifier)) === null || _a === void 0 ? void 0 : _a.replace('-score', ''),
|
||||
'value',
|
||||
],
|
||||
operator: StatementOperators.SET,
|
||||
operand: {
|
||||
operator: ExpressionOperators.STATIC_VALUE,
|
||||
values: [ModifierAccessors.getValue(abilityScoreModifier)],
|
||||
},
|
||||
};
|
||||
case ModifierTypeEnum.BONUS:
|
||||
default:
|
||||
return {
|
||||
precedence: 0.5,
|
||||
target: [
|
||||
'attributes',
|
||||
(_b = ModifierAccessors.getSubType(abilityScoreModifier)) === null || _b === void 0 ? void 0 : _b.replace('-score', ''),
|
||||
'value',
|
||||
],
|
||||
operator: StatementOperators.SET,
|
||||
operand: {
|
||||
operator: ExpressionOperators.ADD,
|
||||
values: null,
|
||||
operands: [
|
||||
{
|
||||
operator: ExpressionOperators.DYNAMIC_VALUE,
|
||||
operands: null,
|
||||
values: [
|
||||
'attributes',
|
||||
(_c = ModifierAccessors.getSubType(abilityScoreModifier)) === null || _c === void 0 ? void 0 : _c.replace('-score', ''),
|
||||
'value',
|
||||
],
|
||||
},
|
||||
{
|
||||
operator: ExpressionOperators.STATIC_VALUE,
|
||||
values: [(_d = ModifierAccessors.getValue(abilityScoreModifier)) !== null && _d !== void 0 ? _d : 0],
|
||||
operands: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
const generatedFeature = {
|
||||
meta: {
|
||||
name: 'Generated Ability Scores',
|
||||
category: 'Generated',
|
||||
},
|
||||
statements: [...baseAbilityScores, ...gfsAbilityScores],
|
||||
featureId: 'generated-ability-scores',
|
||||
labels: [],
|
||||
sources: [],
|
||||
subfeatures: [],
|
||||
acceptableInputs: {},
|
||||
primarySource: null,
|
||||
secondarySources: [],
|
||||
};
|
||||
return { baseAbilityScores, gfsAbilityScores, generatedFeature };
|
||||
}
|
||||
@@ -269,6 +269,9 @@ const initialItemState = {
|
||||
id: -1,
|
||||
isAttuned: null,
|
||||
limitedUse: null,
|
||||
originEntityId: null,
|
||||
originEntityTypeId: null,
|
||||
originDefinitionKey: null,
|
||||
quantity: -1,
|
||||
};
|
||||
export function itemReducer(state = initialItemState, action) {
|
||||
|
||||
@@ -134,7 +134,7 @@ const initialPartyInfoState = {
|
||||
name: null,
|
||||
publicNotes: null,
|
||||
partyInventory: [],
|
||||
sharingState: 0,
|
||||
partyRestrictions: [],
|
||||
modifiers: null,
|
||||
spells: null,
|
||||
};
|
||||
@@ -187,6 +187,7 @@ export const initialState = {
|
||||
},
|
||||
partyInfo: null,
|
||||
campaignSettings: [],
|
||||
longRestText: null,
|
||||
};
|
||||
function serviceData(state = initialState, action) {
|
||||
var _a;
|
||||
@@ -309,6 +310,9 @@ function serviceData(state = initialState, action) {
|
||||
case actionTypes.CAMPAIGN_SETTINGS_SET_COMMIT: {
|
||||
return Object.assign(Object.assign({}, state), { campaignSettings: action.payload });
|
||||
}
|
||||
case actionTypes.LONG_REST_TEXT_SET: {
|
||||
return Object.assign(Object.assign({}, state), { longRestText: action.payload });
|
||||
}
|
||||
default:
|
||||
// not implemented
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { all, call, put, select } from 'redux-saga/effects';
|
||||
import { ItemPlanAccessors } from "../../engine/ItemPlan";
|
||||
import { characterActions, characterEnvActions, featureFlagInfoActions, ruleDataActions, serviceDataActions, } from '../../actions';
|
||||
import { ApiRequests } from '../../api';
|
||||
import * as ApiUtils from '../../api/utils';
|
||||
import * as ApiAdapterUtils from '../../apiAdapter/utils';
|
||||
import { ConfigUtils } from '../../config';
|
||||
import { BackgroundAccessors } from '../../engine/Background';
|
||||
import { CampaignAccessors, PartyInventorySharingStateEnum } from '../../engine/Campaign';
|
||||
import { CampaignAccessors } from '../../engine/Campaign';
|
||||
import { CharacterDerivers } from '../../engine/Character';
|
||||
import { ChoiceAccessors } from '../../engine/Choice';
|
||||
import { ClassAccessors, ClassUtils } from '../../engine/Class';
|
||||
@@ -426,6 +427,16 @@ export function* handlePreferenceChoose(action) {
|
||||
[key]: value,
|
||||
});
|
||||
yield put(callCommitAction(characterActions.preferenceSet, key, value));
|
||||
// These cases need to happen after the preference is set in state
|
||||
switch (key) {
|
||||
case 'longRestType': {
|
||||
const data = yield call(SagaHelpers.getApiRequestData, ApiRequests.getCharacterRestLong);
|
||||
yield put(serviceDataActions.longRestTextSet(data));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//not implemented
|
||||
}
|
||||
yield call(handleDataUpdates, data);
|
||||
}
|
||||
/**
|
||||
@@ -557,6 +568,7 @@ export function* handleClassRemoveRequest(action) {
|
||||
yield call(handleDataUpdates, data);
|
||||
yield call(autoUpdateInfusions);
|
||||
yield call(autoUpdateChoices);
|
||||
yield call(autoUpdateReplicatedItems);
|
||||
}
|
||||
/**
|
||||
*
|
||||
@@ -858,7 +870,7 @@ export function* handleItemCustomizationsDelete(action) {
|
||||
action.meta.accept();
|
||||
}
|
||||
}
|
||||
export function* handleContainerDestroy(item, removeContents) {
|
||||
export function* handleContainerDestroy(item, removeContents, onAccept) {
|
||||
const itemMappingId = ItemAccessors.getMappingId(item);
|
||||
const containerLookup = yield select(rulesEngineSelectors.getContainerLookup);
|
||||
const inventoryLookup = yield select(rulesEngineSelectors.getInventoryLookup);
|
||||
@@ -920,6 +932,9 @@ export function* handleContainerDestroy(item, removeContents) {
|
||||
yield put(characterActions.itemRemove(itemMappingId, removeContents));
|
||||
}
|
||||
}
|
||||
if (onAccept) {
|
||||
onAccept();
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
@@ -933,7 +948,7 @@ export function* handleItemDestroy(action) {
|
||||
if (item) {
|
||||
//if item isContainer, handle removing container and contents
|
||||
if (ItemAccessors.isContainer(item)) {
|
||||
yield call(handleContainerDestroy, item, removeContainerContents);
|
||||
yield call(handleContainerDestroy, item, removeContainerContents, action.meta.accept);
|
||||
}
|
||||
else {
|
||||
//item is not container, just remove it (removeContainerContents should be false for now)
|
||||
@@ -951,20 +966,11 @@ export function* handleItemDestroy(action) {
|
||||
//if item isContainer, handle removing container and contents
|
||||
// TODO IMS: check that this works with shared containers
|
||||
if (ItemAccessors.isContainer(item)) {
|
||||
yield call(handleContainerDestroy, item, removeContainerContents);
|
||||
yield call(handleContainerDestroy, item, removeContainerContents, action.meta.accept);
|
||||
}
|
||||
else {
|
||||
//item is not container, just remove it (removeContainerContents should be false for now)
|
||||
yield put(serviceDataActions.partyItemRemove(id, false));
|
||||
const partyInfo = yield select(serviceDataSelectors.getPartyInfo);
|
||||
if (partyInfo &&
|
||||
CampaignAccessors.getSharingState(partyInfo) === PartyInventorySharingStateEnum.DELETE_ONLY) {
|
||||
const partyInventory = CampaignAccessors.getPartyBaseInventoryContracts(partyInfo);
|
||||
// If all that is left if what we just deleted
|
||||
if (partyInventory.length === 1 && ItemAccessors.getId(partyInventory[0]) === id) {
|
||||
yield put(serviceDataActions.partyCampaignInfoSet(Object.assign(Object.assign({}, partyInfo), { sharingState: PartyInventorySharingStateEnum.OFF })));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (action.meta.accept) {
|
||||
action.meta.accept();
|
||||
@@ -1027,6 +1033,7 @@ export function* handleItemMove(action) {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
const partyInfo = yield select(serviceDataSelectors.getPartyInfo);
|
||||
const isCurrentContainerShared = ItemUtils.isShared(item, containerLookup);
|
||||
const isDestinationContainerShared = ContainerValidators.validateIsShared(DefinitionHacks.hack__generateDefinitionKey(action.payload.containerEntityTypeId, action.payload.containerEntityId), containerLookup);
|
||||
const isItemContainer = ItemAccessors.isContainer(item);
|
||||
@@ -1041,12 +1048,30 @@ export function* handleItemMove(action) {
|
||||
if (isItemContainer) {
|
||||
const inventoryItems = yield select(rulesEngineSelectors.getPartyInventory);
|
||||
const itemContainer = HelperUtils.lookupDataOrFallback(containerLookup, DefinitionHacks.hack__generateDefinitionKey(EntityTypeEnum.ITEM, ItemAccessors.getMappingId(item)));
|
||||
const currentCharacterId = yield select(rulesEngineSelectors.getId);
|
||||
// If item is container we need to move contents to inventory
|
||||
if (itemContainer) {
|
||||
const inventoryInContainer = ContainerUtils.getInventoryItems(itemContainer, inventoryItems);
|
||||
//loop through items in the container and move contents. If there is an infusion, only move if infusion belongs to the character otherwise leave in party inventory
|
||||
for (let i = 0; i < inventoryInContainer.length; i++) {
|
||||
yield put(callCommitAction(characterActions.itemAdd, Object.assign(Object.assign({}, inventoryInContainer[i]), { containerEntityId: ContainerAccessors.getMappingId(itemContainer), containerEntityTypeId: ContainerAccessors.getContainerType(itemContainer), containerDefinitionKey: ContainerAccessors.getDefinitionKey(itemContainer) })));
|
||||
yield put(callCommitAction(serviceDataActions.partyItemRemove, ItemAccessors.getMappingId(inventoryInContainer[i])));
|
||||
const infusion = ItemAccessors.getInfusion(inventoryInContainer[i]);
|
||||
let canMoveInfusion = false;
|
||||
if (infusion) {
|
||||
const infusionCharacterId = InfusionAccessors.getCharacterId(infusion);
|
||||
canMoveInfusion = infusionCharacterId === currentCharacterId;
|
||||
}
|
||||
const itemPartyRestrictions = ItemAccessors.getPartyInventoryRestrictions(inventoryInContainer[i]);
|
||||
const canMoveRestrictedItem = itemPartyRestrictions.length > 0
|
||||
? itemPartyRestrictions.some((restriction) => restriction.characterId === currentCharacterId)
|
||||
: true;
|
||||
if (partyInfo && (!canMoveRestrictedItem || (infusion && !canMoveInfusion))) {
|
||||
//if we can't move the infusion or replicated item, we need to remove the item from the container so it doesn't get "lost" when we move the container - leave the item in the party equipment container
|
||||
yield put(callCommitAction(serviceDataActions.partyItemMoveSet, ItemAccessors.getMappingId(inventoryInContainer[i]), CampaignAccessors.getId(partyInfo), ContainerTypeEnum.CAMPAIGN));
|
||||
}
|
||||
else {
|
||||
yield put(callCommitAction(characterActions.itemAdd, Object.assign(Object.assign({}, inventoryInContainer[i]), { containerEntityId: ContainerAccessors.getMappingId(itemContainer), containerEntityTypeId: ContainerAccessors.getContainerType(itemContainer), containerDefinitionKey: ContainerAccessors.getDefinitionKey(itemContainer) })));
|
||||
yield put(callCommitAction(serviceDataActions.partyItemRemove, ItemAccessors.getMappingId(inventoryInContainer[i])));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1381,6 +1406,19 @@ export function* handleClassFeatureChoiceSetRequest(action) {
|
||||
}
|
||||
//remove any spells that are associated with the spell lists from the subclass or feat choices
|
||||
yield call(apiRemoveSpellsBySpellListIds, spellListIdsToRemove);
|
||||
//remove any item mappings from feature options that come from item plans (magic item mappings)
|
||||
if (choiceType === BuilderChoiceTypeEnum.FEATURE_OPTION && oldCharClass) {
|
||||
const itemPlans = yield select(rulesEngineSelectors.getAvailableItemPlans);
|
||||
const chosenItemPlan = itemPlans.find((plan) => {
|
||||
const planChoice = ItemPlanAccessors.getChoice(plan);
|
||||
return ChoiceAccessors.getId(planChoice) === choiceId;
|
||||
});
|
||||
const item = chosenItemPlan ? ItemPlanAccessors.getItem(chosenItemPlan) : null;
|
||||
if (item) {
|
||||
// TODO: PARTY - can we send the party inventory update request here instead of from the component?
|
||||
yield put(characterActions.itemDestroy(ItemAccessors.getMappingId(item), false, action.meta.accept));
|
||||
}
|
||||
}
|
||||
yield call(apiClassFeatureChoiceSet, action);
|
||||
const classes = yield select(rulesEngineSelectors.getClasses);
|
||||
const charClass = classes.find((charClass) => !!oldCharClass && ClassAccessors.getId(charClass) === ClassAccessors.getId(oldCharClass));
|
||||
@@ -1502,6 +1540,7 @@ export function* handleClassLevelSetRequest(action) {
|
||||
yield call(autoUpdateInfusions);
|
||||
yield call(autoUpdateChoices);
|
||||
yield call(autoUpdateClassAlwaysPreparedSpells, [action.payload.classId]);
|
||||
yield call(autoUpdateReplicatedItems);
|
||||
}
|
||||
/**
|
||||
*
|
||||
@@ -1731,6 +1770,27 @@ function* autoUpdateChoices(lastChoice = null) {
|
||||
yield call(autoUpdateBackgroundChoices);
|
||||
yield call(autoUpdateExpertiseChoices);
|
||||
}
|
||||
function* autoUpdateReplicatedItems() {
|
||||
const itemOriginLookup = yield select(rulesEngineSelectors.getAllInventoryLookupByOrigin);
|
||||
const itemPlans = yield select(rulesEngineSelectors.getAvailableItemPlans);
|
||||
const itemMappingIdsToRemove = [];
|
||||
Object.keys(itemOriginLookup).forEach((originKey) => {
|
||||
if (!itemPlans.some((itemPlan) => ItemPlanAccessors.getOriginDefinitionKey(itemPlan) === originKey)) {
|
||||
const item = itemOriginLookup[originKey];
|
||||
if (item) {
|
||||
// If the item is not part of any item plan, we can remove it
|
||||
itemMappingIdsToRemove.push(ItemAccessors.getMappingId(item));
|
||||
}
|
||||
}
|
||||
});
|
||||
while (itemMappingIdsToRemove.length > 0) {
|
||||
const itemMappingId = itemMappingIdsToRemove.pop();
|
||||
if (!itemMappingId) {
|
||||
continue;
|
||||
}
|
||||
yield put(characterActions.itemRemove(itemMappingId));
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param choice
|
||||
@@ -2261,3 +2321,40 @@ export function* handlePremadeInfoGet(action) {
|
||||
yield put(characterActions.premadeInfoSetCommit(responseData));
|
||||
}
|
||||
}
|
||||
export function* handleItemPlanInventoryMappingCreate(action) {
|
||||
var _a;
|
||||
const itemDefinitionKey = action.payload.itemDefinitionKey;
|
||||
const containerDefinitionKey = action.payload.containerDefinitionKey;
|
||||
const itemPlanOriginDefinitionKey = (_a = action.payload.itemPlanOriginDefinitionKey) !== null && _a !== void 0 ? _a : null;
|
||||
const quantity = action.payload.quantity;
|
||||
const itemId = Number(DefinitionUtils.getDefinitionKeyId(itemDefinitionKey));
|
||||
const itemEntityTypeId = Number(DefinitionUtils.getDefinitionKeyType(itemDefinitionKey));
|
||||
const containerEntityId = containerDefinitionKey
|
||||
? Number(DefinitionUtils.getDefinitionKeyId(containerDefinitionKey))
|
||||
: null;
|
||||
const containerEntityTypeId = containerDefinitionKey
|
||||
? Number(DefinitionUtils.getDefinitionKeyType(containerDefinitionKey))
|
||||
: null;
|
||||
const originEntityId = itemPlanOriginDefinitionKey
|
||||
? Number(DefinitionUtils.getDefinitionKeyId(itemPlanOriginDefinitionKey))
|
||||
: null;
|
||||
const originEntityTypeId = itemPlanOriginDefinitionKey
|
||||
? Number(DefinitionUtils.getDefinitionKeyType(itemPlanOriginDefinitionKey))
|
||||
: null;
|
||||
if (itemId !== null && itemEntityTypeId !== null) {
|
||||
let params = {
|
||||
equipment: [
|
||||
{
|
||||
containerEntityId,
|
||||
containerEntityTypeId,
|
||||
entityId: itemId,
|
||||
entityTypeId: itemEntityTypeId,
|
||||
quantity,
|
||||
originEntityId,
|
||||
originEntityTypeId,
|
||||
},
|
||||
],
|
||||
};
|
||||
yield call(apiItemsCreate, params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,8 @@ const SYNC_ACTION_LOOKUP = {
|
||||
[types.CUSTOM_ITEM_CREATE]: true,
|
||||
[types.ITEM_DESTROY]: true,
|
||||
[types.CUSTOM_ITEM_DESTROY]: true,
|
||||
//ITEM PLAN
|
||||
[types.ITEM_PLAN_INVENTORY_MAPPING_CREATE]: true,
|
||||
//CURRENCY
|
||||
[types.CURRENCY_TRANSACTION_SET]: true,
|
||||
//OPTIONAL_FEATURES
|
||||
@@ -454,6 +456,8 @@ export function* executeHandler(action) {
|
||||
[types.CUSTOM_ITEM_DESTROY]: sagaHandlers.handleCustomItemDestroy,
|
||||
[types.ITEM_CHARGES_SET]: sagaHandlers.handleItemChargesSet,
|
||||
[types.ITEM_MOVE_SET]: sagaHandlers.handleItemMove,
|
||||
//ITEM PLAN
|
||||
[types.ITEM_PLAN_INVENTORY_MAPPING_CREATE]: sagaHandlers.handleItemPlanInventoryMappingCreate,
|
||||
//CURRENCY
|
||||
[types.CURRENCY_TRANSACTION_SET]: sagaHandlers.handleCurrencyTransactionSet,
|
||||
//OPTIONAL_FEATURES
|
||||
|
||||
@@ -2,11 +2,10 @@ import { call, put, select } from 'redux-saga/effects';
|
||||
import { characterActions, serviceDataActions } from '../../actions';
|
||||
import { ApiRequests } from '../../api';
|
||||
import * as apiShared from '../../api/requests';
|
||||
import { CampaignAccessors, PartyInventorySharingStateEnum } from '../../engine/Campaign';
|
||||
import { CampaignAccessors } from '../../engine/Campaign';
|
||||
import { CreatureAccessors } from '../../engine/Creature';
|
||||
import { DefinitionAccessors, DefinitionTypeEnum, DefinitionUtils } from '../../engine/Definition';
|
||||
import { DefinitionPoolUtils } from '../../engine/DefinitionPool';
|
||||
import { FeatureFlagEnum, FeatureFlagInfoUtils } from '../../engine/FeatureFlagInfo';
|
||||
import { HelperUtils } from '../../engine/Helper';
|
||||
import { InfusionAccessors, InfusionTypeEnum } from '../../engine/Infusion';
|
||||
import { InfusionChoiceAccessors } from '../../engine/InfusionChoice';
|
||||
@@ -17,7 +16,7 @@ import { VehicleAccessors, VehicleSimulators } from '../../engine/Vehicle';
|
||||
import { VehicleComponentAccessors } from '../../engine/VehicleComponent';
|
||||
import { initialCoinState } from '../../reducers/character';
|
||||
import * as SagaHelpers from '../../sagas/SagaHelpers';
|
||||
import { characterSelectors, featureFlagInfoSelectors, rulesEngineSelectors, serviceDataSelectors, } from '../../selectors';
|
||||
import { characterSelectors, rulesEngineSelectors, serviceDataSelectors, } from '../../selectors';
|
||||
import { TypeScriptUtils } from '../../utils';
|
||||
import { callCommitAction } from '../../utils/ReduxActionUtils';
|
||||
import { apiCreatureCreate, apiItemsCreate, handleLoadDefinitions } from '../character/handlers';
|
||||
@@ -95,6 +94,8 @@ export function* handleInfusionCreate(action) {
|
||||
entityId: itemId,
|
||||
entityTypeId: itemEntityTypeId,
|
||||
quantity: 1,
|
||||
originEntityId: null,
|
||||
originEntityTypeId: null,
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -165,14 +166,15 @@ export function* handleInfusionDestroy(action) {
|
||||
//if infused item is a REPLICATE type remove the item from inventory
|
||||
//otherwise leave the item but un-attune and reset charges
|
||||
if (infusionType === InfusionTypeEnum.REPLICATE && inventoryMappingId !== null) {
|
||||
yield put(characterActions.itemRemove(inventoryMappingId, true));
|
||||
yield put(characterActions.itemDestroy(inventoryMappingId, true, action.meta.accept, action.meta.reject));
|
||||
// Mapping was removed on the backend due to being an item
|
||||
// Only call commit action to mirror backend
|
||||
yield put(callCommitAction(serviceDataActions.infusionMappingRemove, action.payload.infusionId, action.payload.inventoryMappingId));
|
||||
}
|
||||
else {
|
||||
const inventoryLookup = yield select(rulesEngineSelectors.getInventoryLookup);
|
||||
const foundItem = HelperUtils.lookupDataOrFallback(inventoryLookup, action.payload.inventoryMappingId);
|
||||
const partyInventoryLookup = yield select(rulesEngineSelectors.getPartyInventoryLookup);
|
||||
const foundItem = HelperUtils.lookupDataOrFallback(Object.assign(Object.assign({}, inventoryLookup), partyInventoryLookup), action.payload.inventoryMappingId);
|
||||
if (foundItem) {
|
||||
if (ItemAccessors.isAttuned(foundItem)) {
|
||||
yield put(characterActions.itemAttuneSet(inventoryMappingId, false));
|
||||
@@ -182,6 +184,9 @@ export function* handleInfusionDestroy(action) {
|
||||
// TODO IMS Infusions come back here and switch this out
|
||||
yield put(characterActions.itemChargesSet(ItemAccessors.getMappingId(foundItem), 0));
|
||||
}
|
||||
if (action.meta.accept) {
|
||||
action.meta.accept();
|
||||
}
|
||||
}
|
||||
yield put(serviceDataActions.infusionMappingRemove(action.payload.infusionId, action.payload.inventoryMappingId));
|
||||
}
|
||||
@@ -244,31 +249,27 @@ export function* handleVehicleRemove(action) {
|
||||
}
|
||||
export function* handlePartyInventoryRequest(action) {
|
||||
var _a, _b, _c, _d, _e, _f;
|
||||
const featureFlagInfo = yield select(featureFlagInfoSelectors.getFeatureFlagInfo);
|
||||
const partyFlag = FeatureFlagInfoUtils.getFeatureFlagInfoValue(FeatureFlagEnum.RELEASE_GATE_IMS, featureFlagInfo);
|
||||
// Party Inventory
|
||||
if (partyFlag) {
|
||||
const campaignInfo = yield select(characterSelectors.getCampaign);
|
||||
if (campaignInfo) {
|
||||
const data = yield call(SagaHelpers.getApiRequestData, apiShared.getPartyInventory, { campaignId: CampaignAccessors.getId(campaignInfo) });
|
||||
// This sets the data in the serviceData.partyInfo state
|
||||
yield put(serviceDataActions.partyCampaignInfoSet(Object.assign(Object.assign({}, campaignInfo), { sharingState: (_a = data === null || data === void 0 ? void 0 : data.sharingState) !== null && _a !== void 0 ? _a : PartyInventorySharingStateEnum.OFF, partyInventory: (_b = data === null || data === void 0 ? void 0 : data.partyItems) !== null && _b !== void 0 ? _b : [], spells: (_c = data === null || data === void 0 ? void 0 : data.spells) !== null && _c !== void 0 ? _c : null, modifiers: (_d = data === null || data === void 0 ? void 0 : data.modifiers) !== null && _d !== void 0 ? _d : null, coin: (_e = data === null || data === void 0 ? void 0 : data.currency) !== null && _e !== void 0 ? _e : initialCoinState })));
|
||||
yield call(handleUpdatePartyInventoryValues, data);
|
||||
// Party infusions set into serviceData
|
||||
if ((_f = data.partyInfusions) === null || _f === void 0 ? void 0 : _f.length) {
|
||||
let infusionDefinitionIds = new Set();
|
||||
for (let i = 0; i < data.partyInfusions.length; i++) {
|
||||
const mapping = data.partyInfusions[i];
|
||||
yield put(callCommitAction(serviceDataActions.infusionMappingAdd, mapping));
|
||||
const definitionKey = InfusionAccessors.getDefinitionKey(mapping);
|
||||
if (definitionKey !== null) {
|
||||
infusionDefinitionIds.add(DefinitionUtils.getDefinitionKeyId(definitionKey));
|
||||
}
|
||||
}
|
||||
if (infusionDefinitionIds.size > 0) {
|
||||
yield call(handleLoadDefinitions, DefinitionTypeEnum.INFUSION, Array.from(infusionDefinitionIds));
|
||||
const campaignInfo = yield select(characterSelectors.getCampaign);
|
||||
if (campaignInfo) {
|
||||
const data = yield call(SagaHelpers.getApiRequestData, apiShared.getPartyInventory, { campaignId: CampaignAccessors.getId(campaignInfo) });
|
||||
// This sets the data in the serviceData.partyInfo state
|
||||
yield put(serviceDataActions.partyCampaignInfoSet(Object.assign(Object.assign({}, campaignInfo), { partyInventory: (_a = data === null || data === void 0 ? void 0 : data.partyItems) !== null && _a !== void 0 ? _a : [], spells: (_b = data === null || data === void 0 ? void 0 : data.spells) !== null && _b !== void 0 ? _b : null, modifiers: (_c = data === null || data === void 0 ? void 0 : data.modifiers) !== null && _c !== void 0 ? _c : null, coin: (_d = data === null || data === void 0 ? void 0 : data.currency) !== null && _d !== void 0 ? _d : initialCoinState, partyRestrictions: (_e = data === null || data === void 0 ? void 0 : data.partyRestrictions) !== null && _e !== void 0 ? _e : [] })));
|
||||
yield call(handleUpdatePartyInventoryValues, data);
|
||||
// Party infusions set into serviceData
|
||||
if ((_f = data.partyInfusions) === null || _f === void 0 ? void 0 : _f.length) {
|
||||
let infusionDefinitionIds = new Set();
|
||||
for (let i = 0; i < data.partyInfusions.length; i++) {
|
||||
const mapping = data.partyInfusions[i];
|
||||
yield put(callCommitAction(serviceDataActions.infusionMappingAdd, mapping));
|
||||
const definitionKey = InfusionAccessors.getDefinitionKey(mapping);
|
||||
if (definitionKey !== null) {
|
||||
infusionDefinitionIds.add(DefinitionUtils.getDefinitionKeyId(definitionKey));
|
||||
}
|
||||
}
|
||||
if (infusionDefinitionIds.size > 0) {
|
||||
yield call(handleLoadDefinitions, DefinitionTypeEnum.INFUSION, Array.from(infusionDefinitionIds));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,14 +158,3 @@ export const makeLoadAvailableOptionalClassFeatures = createSelector([rulesEngin
|
||||
};
|
||||
};
|
||||
});
|
||||
//----------------------------
|
||||
// BELOW LIES GFS
|
||||
//----------------------------
|
||||
// TODO: restrictEntityDefinitionResponseData is filtering by homebrew and sources categories based on preferences
|
||||
// so maybe that should just be part of the api.
|
||||
// if you change it during game you would have to make the api call again.
|
||||
export const makeLoadAvailableFeatures = createSelector([rulesEngineSelectors.getEntityRestrictionData, characterSelectors.getId], (entityRestrictionData, characterId) => (additionalConfig) => {
|
||||
return ApiRequests.getCharacterGameDataFeatures(additionalConfig).then((response) =>
|
||||
// restrictEntityDefinitionResponseData(response, entityRestrictionData, characterId)
|
||||
response);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import { ItemPlanGenerators } from "../../engine/ItemPlan";
|
||||
import { ApiGenerators } from '../../api';
|
||||
import { AbilityGenerators } from '../../engine/Ability';
|
||||
import { ActionGenerators } from '../../engine/Action';
|
||||
@@ -759,6 +760,11 @@ export const getInventoryLookup = createSelector([getInventory], ItemGenerators.
|
||||
*
|
||||
*/
|
||||
export const getPartyInventoryLookup = createSelector([getPartyInventory], ItemGenerators.generateInventoryLookup);
|
||||
/**
|
||||
* returns all Items in all inventories, grouped by origin
|
||||
* @returns {Record<string, Array<Item>>}
|
||||
*/
|
||||
export const getAllInventoryLookupByOrigin = createSelector([getInventory, getPartyInventory], ItemGenerators.generateInventoryLookupByOrigin);
|
||||
/**
|
||||
* TODO v5.1: remove customItems from this selector when mobile moves up to 5.1 customItems as Items
|
||||
* @returns {Array<Container>}
|
||||
@@ -769,7 +775,6 @@ export const getInventoryContainers = createSelector([
|
||||
characterSelectors.getId,
|
||||
serviceDataSelectors.getPartyInfo,
|
||||
getPartyInventory,
|
||||
featureFlagInfoSelectors.getFeatureFlagInfo,
|
||||
characterSelectors.getCurrencies,
|
||||
characterSelectors.getPreferences,
|
||||
getRuleData,
|
||||
@@ -780,6 +785,11 @@ export const getPartyInventoryContainers = createSelector([getInventoryContainer
|
||||
* @returns {ContainerLookup}
|
||||
*/
|
||||
export const getContainerLookup = createSelector([getInventoryContainers], ContainerGenerators.generateContainerLookup);
|
||||
/**
|
||||
* @returns {Array<ItemPlan>}
|
||||
*/
|
||||
export const getAvailableItemPlans = createSelector([getClasses, getAllInventoryLookupByOrigin, getContainerLookup], ItemPlanGenerators.generateAggregatedItemPlans);
|
||||
export const getMaxReplicatedItemsCount = createSelector([getClasses], ItemPlanGenerators.generateMaxReplicatedItemCount);
|
||||
/**
|
||||
* @returns {Array<Modifier>}
|
||||
*/
|
||||
@@ -1384,7 +1394,15 @@ export const getProficiencyGroups = createSelector([
|
||||
/**
|
||||
* @returns {SnippetData}
|
||||
*/
|
||||
export const getSnippetData = createSelector([getProficiencyBonus, getAbilityKeyLookup, getAbilityLookup, getExperienceInfo, getHitPointInfo, getRuleData], SnippetGenerators.generateSnippetData);
|
||||
export const getSnippetData = createSelector([
|
||||
getProficiencyBonus,
|
||||
getAbilityKeyLookup,
|
||||
getAbilityLookup,
|
||||
getExperienceInfo,
|
||||
getHitPointInfo,
|
||||
getCurrentCarriedWeightSpeed,
|
||||
getRuleData,
|
||||
], SnippetGenerators.generateSnippetData);
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
@@ -8,3 +8,4 @@ export const getVehicleComponentMappings = (state) => state.serviceData.vehicleC
|
||||
export const getVehicleMappings = (state) => state.serviceData.vehicleMappings;
|
||||
export const getPartyInfo = (state) => state.serviceData.partyInfo;
|
||||
export const getCampaignSettings = (state) => state.serviceData.campaignSettings;
|
||||
export const getLongRestText = (state) => state.serviceData.longRestText;
|
||||
|
||||
Reference in New Issue
Block a user