New source found from dndbeyond.com

This commit is contained in:
2025-07-16 01:00:16 -07:00
parent 151590af7a
commit f9f8dd0e7a
25 changed files with 886 additions and 1299 deletions
@@ -343,6 +343,11 @@ export function* handleAdhocFeatCreate(action) {
* @param action
*/
export function* handleAdhocFeatRemove(action) {
const featLookup = yield select(rulesEngineSelectors.getFeatLookup);
const currentFeat = HelperUtils.lookupDataOrFallback(featLookup, action.payload.id, null);
if (currentFeat !== null) {
yield call(apiRemoveSpellsBySpellListIds, FeatAccessors.getSpellListIds(currentFeat));
}
const data = yield call(SagaHelpers.getApiRequestData, ApiRequests.deleteCharacterFeatAdHoc, action.payload);
yield call(handleDataUpdates, data);
}
@@ -457,7 +462,13 @@ export function* handleRaceChoose(action) {
const { race } = action.payload;
const existingRace = yield select(rulesEngineSelectors.getRace);
if (existingRace !== null) {
yield call(apiRemoveSpellsBySpellListIds, RaceAccessors.getSpellListIds(existingRace));
const spellListIdsToRemove = RaceAccessors.getSpellListIds(existingRace);
const racialTraitsToRemove = RaceAccessors.getRacialTraits(existingRace);
const featsFromRacialTraits = racialTraitsToRemove.map((trait) => RacialTraitAccessors.getFeats(trait)).flat();
featsFromRacialTraits.forEach((feat) => {
spellListIdsToRemove.push(...FeatAccessors.getSpellListIds(feat));
});
yield call(apiRemoveSpellsBySpellListIds, spellListIdsToRemove);
const existingOptionalOrigins = yield select(rulesEngineSelectors.getOptionalOrigins);
const optionalOriginsIdsToRemove = existingOptionalOrigins.map(OptionalOriginAccessors.getRacialTraitId);
yield call(apiRemoveOptionalOriginsCollection, {
@@ -1309,15 +1320,21 @@ export function* handleCurrencyTransactionSet(action) {
*/
export function* handleRacialTraitChoiceSetRequest(action) {
const { racialTraitId, choiceId } = action.payload;
yield call(apiRacialTraitChoiceSet, action);
const race = yield select(rulesEngineSelectors.getRace);
if (race) {
const racialTrait = RaceAccessors.getRacialTraits(race).find((racialTrait) => RacialTraitAccessors.getId(racialTrait) === racialTraitId);
if (racialTrait) {
const racialTraitChoice = RacialTraitAccessors.getChoices(racialTrait).find((choice) => ChoiceAccessors.getId(choice) === choiceId);
if (racialTraitChoice) {
yield call(autoUpdateChoices, racialTraitChoice);
}
const racialTrait = race
? RaceAccessors.getRacialTraits(race).find((racialTrait) => RacialTraitAccessors.getId(racialTrait) === racialTraitId)
: null;
// Remove any spells that are associated with the feat from the racial trait choices
const feats = racialTrait ? RacialTraitAccessors.getFeats(racialTrait) : [];
const featSpellListIds = feats
.map(FeatAccessors.getSpellListIds)
.reduce((acc, ids) => acc.concat(ids), []);
yield call(apiRemoveSpellsBySpellListIds, featSpellListIds);
yield call(apiRacialTraitChoiceSet, action);
if (racialTrait) {
const racialTraitChoice = RacialTraitAccessors.getChoices(racialTrait).find((choice) => ChoiceAccessors.getId(choice) === choiceId);
if (racialTraitChoice) {
yield call(autoUpdateChoices, racialTraitChoice);
}
}
}
@@ -1343,6 +1360,7 @@ export function* handleClassFeatureChoiceSetRequest(action) {
const { classId, classFeatureId, choiceId, choiceType, optionValue } = action.payload;
let oldClasses = yield select(rulesEngineSelectors.getClasses);
let oldCharClass = oldClasses.find((charClass) => ClassAccessors.getActiveId(charClass) === classId);
const spellListIdsToRemove = [];
if (choiceType === BuilderChoiceTypeEnum.SUB_CLASS_OPTION && oldCharClass) {
const subclass = ClassAccessors.getSubclass(oldCharClass);
if (subclass !== null) {
@@ -1350,9 +1368,19 @@ export function* handleClassFeatureChoiceSetRequest(action) {
.filter((classFeature) => ClassFeatureAccessors.getClassId(classFeature) === subclass.id)
.map(ClassFeatureAccessors.getSpellListIds)
.reduce((acc, ids) => acc.concat(ids), []);
yield call(apiRemoveSpellsBySpellListIds, spellListIds);
spellListIdsToRemove.push(...spellListIds);
}
}
if (choiceType === BuilderChoiceTypeEnum.FEAT_CHOICE_OPTION && oldCharClass) {
const classFeature = ClassAccessors.getClassFeatures(oldCharClass).find((classFeature) => ClassFeatureAccessors.getId(classFeature) === classFeatureId);
const featsFromClassFeature = classFeature ? ClassFeatureAccessors.getFeats(classFeature) : [];
featsFromClassFeature.forEach((feat) => {
const spellListIds = FeatAccessors.getSpellListIds(feat);
spellListIdsToRemove.push(...spellListIds);
});
}
//remove any spells that are associated with the spell lists from the subclass or feat choices
yield call(apiRemoveSpellsBySpellListIds, spellListIdsToRemove);
yield call(apiClassFeatureChoiceSet, action);
const classes = yield select(rulesEngineSelectors.getClasses);
const charClass = classes.find((charClass) => !!oldCharClass && ClassAccessors.getId(charClass) === ClassAccessors.getId(oldCharClass));
@@ -1453,12 +1481,21 @@ export function* handleClassLevelSetRequest(action) {
const oldClassId = ClassAccessors.getId(oldCharClass);
const removedClassFeatures = ClassAccessors.getActiveClassFeatures(oldCharClass).filter((classFeature) => ClassFeatureAccessors.getRequiredLevel(classFeature) > level);
const isRemovingSubclass = removedClassFeatures.some((feature) => ClassFeatureAccessors.getChoices(feature).some((choice) => ChoiceAccessors.getType(choice) === BuilderChoiceTypeEnum.SUB_CLASS_OPTION));
const spellListIdsFromFeatsToRemove = [];
removedClassFeatures.forEach((classFeature) => {
const feats = ClassFeatureAccessors.getFeats(classFeature);
feats.forEach((feat) => {
const spellListIds = FeatAccessors.getSpellListIds(feat);
spellListIdsFromFeatsToRemove.push(...spellListIds);
});
});
const removedSpellListIds = ClassAccessors.getActiveClassFeatures(oldCharClass)
.filter((classFeature) => ClassFeatureAccessors.getRequiredLevel(classFeature) > level ||
(isRemovingSubclass && ClassFeatureAccessors.getClassId(classFeature) !== oldClassId))
.map(ClassFeatureAccessors.getSpellListIds)
.reduce((acc, spellListIds) => acc.concat(spellListIds), []);
yield call(apiRemoveSpellsBySpellListIds, removedSpellListIds);
// Remove spells associated with the spell lists from the removed class features
yield call(apiRemoveSpellsBySpellListIds, [...removedSpellListIds, ...spellListIdsFromFeatsToRemove]);
}
}
yield call(apiClassLevelSet, action);
@@ -1582,7 +1619,21 @@ function* updateBackgroundResult(action, data) {
export function* handleBackgroundSetRequest(action) {
const existingBackground = yield select(rulesEngineSelectors.getBackgroundInfo);
if (existingBackground !== null) {
yield call(apiRemoveSpellsBySpellListIds, BackgroundAccessors.getSpellListIds(existingBackground));
//start an array of spellListIds to remove with any spellListIds from the existing background
const spellListIdsToRemove = BackgroundAccessors.getSpellListIds(existingBackground);
//check for any granted or chosen feats on the background and get their spellListIds
const featLookup = yield select(rulesEngineSelectors.getFeatLookup);
const chosenFeatIds = BackgroundAccessors.getFeatLists(existingBackground)
.map((featList) => featList.chosenFeatId)
.filter(TypeScriptUtils.isNotNullOrUndefined);
chosenFeatIds.forEach((featId) => {
const feat = HelperUtils.lookupDataOrFallback(featLookup, featId);
if (feat) {
spellListIdsToRemove.push(...FeatAccessors.getSpellListIds(feat));
}
});
//remove any spellListIds that were collected
yield call(apiRemoveSpellsBySpellListIds, spellListIdsToRemove);
}
yield put(callCommitAction(characterActions.backgroundHasCustomSet, false));
const data = yield call(SagaHelpers.getApiRequestData, ApiRequests.putCharacterBackground, action.payload);