New source found from dndbeyond.com

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