New source found from dndbeyond.com

This commit is contained in:
2026-07-08 01:00:09 -07:00
parent 9a983a6d7b
commit dcefa0d2f2
2865 changed files with 222467 additions and 49053 deletions
@@ -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,
});
@@ -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 };
}