= [];
for (let i = 1; i <= level + levelsRemaining; i++) {
levelOptions.push({
label: "" + i,
value: i,
});
}
const handleLevelChangePromise = (
newLevel: string,
oldLevel: string,
accept: () => void,
reject: () => void
): void => {
const newLevelValue = HelperUtils.parseInputInt(newLevel, 0);
const oldLevelValue = HelperUtils.parseInputInt(oldLevel, 0);
const newTotalClassLevel: number = classes.reduce(
(acc: number, oldClass) =>
(acc += oldClass.id === charClass.id ? newLevelValue : oldClass.level),
0
);
const isLevelUp: boolean = newLevelValue > oldLevelValue;
const isLevelDown: boolean = newLevelValue < oldLevelValue;
// Modals to handle milestone
if (isLevelUp && isTypeMilestone) {
dispatch(characterActions.classLevelSetRequest(classId, newLevelValue));
accept();
}
if (isLevelDown && isTypeMilestone) {
createModal({
content: (
{renderModalIntro(currentLevel, newTotalClassLevel)}
Are you sure you want to level down in the {name} class?
Your hit points will be reduced by the fixed amount and class
feature choices you have made for the higher levels will be lost.
),
props: {
heading: "Level Down",
color: "secondary",
confirmButtonText: "Level Down",
size: "fit-content",
onConfirm: () => {
dispatch(
characterActions.classLevelSetRequest(classId, newLevelValue)
);
accept();
},
onClose: () => {
reject();
},
},
});
}
// Modals to handle progression
if (isLevelUp && isTypeXp) {
if (newTotalClassLevel <= currentLevel) {
dispatch(characterActions.classLevelSetRequest(classId, newLevelValue));
accept();
} else {
createModal({
content: (
{renderModalIntro(currentLevel, newTotalClassLevel)}
Are you sure you want to level up in the {name} class?
Your XP total will be increased to{" "}
{FormatUtils.renderLocaleNumber(
CharacterUtils.deriveCurrentLevelXp(
newTotalClassLevel,
ruleData
)
)}{" "}
to match your new level.
),
props: {
heading: "Level Up",
confirmButtonText: "Level Up",
size: "fit-content",
onConfirm: () => {
dispatch(
characterActions.classLevelSetRequest(
classId,
newLevelValue,
CharacterUtils.deriveCurrentLevelXp(
newTotalClassLevel,
ruleData
)
)
);
accept();
},
onClose: () => {
reject();
},
},
});
}
}
if (isLevelDown && isTypeXp) {
createModal({
content: (
{renderModalIntro(currentLevel, newTotalClassLevel)}
Are you sure you want to level down in the {name} class?
Your hit points will be reduced by the fixed amount and class
feature choices you have made for the higher levels will be lost.
Your XP total will be decreased to{" "}
{FormatUtils.renderLocaleNumber(
CharacterUtils.deriveCurrentLevelXp(
newTotalClassLevel,
ruleData
)
)}{" "}
to match your new level.
),
props: {
heading: "Level Down",
confirmButtonText: "Level Down",
color: "secondary",
size: "fit-content",
onConfirm: () => {
dispatch(
characterActions.classLevelSetRequest(
classId,
newLevelValue,
CharacterUtils.deriveCurrentLevelXp(
newTotalClassLevel,
ruleData
)
)
);
accept();
},
onClose: () => {
reject();
},
},
});
}
};
const handleRemoveClass = (): void => {
const newTotalClassLevel: number = classes.reduce(
(acc: number, oldClass) =>
(acc += oldClass.id === charClass.id ? 0 : oldClass.level),
0
);
createModal({
content: (
{renderModalIntro()}
Are you sure you want to remove all your levels in the {name} class?
Your hit points will be reduced by the fixed amount and class
feature choices you have made for the higher levels will be lost.
{isTypeXp && (
Your XP total will be decreased to match your new level.
)}
),
props: {
heading: "Remove Class",
variant: "remove",
size: "fit-content",
confirmButtonText: "Remove",
onConfirm: () => {
let newCharacterXp: number | null = isTypeXp
? CharacterUtils.deriveCurrentLevelXp(newTotalClassLevel, ruleData)
: null;
dispatch(
characterActions.classRemoveRequest(charClass.id, newCharacterXp)
);
},
onClose: () => {}, //Do nothing
},
});
};
const renderModalIntro = (
currentLevel: number | null = null,
newLevel: number | null = null
): React.ReactNode => {
return (
{classPortraitName}
{currentLevel !== null && newLevel !== null && (
Current Level: {currentLevel}
New Level: {newLevel}
)}
);
};
const classPortraitName: ReactNode = (
<>
{subclassDefinition && (
{subclassDefinition.name}
)}
{name}
>
);
return (
{isMulticlass && isStartingClass && (
Starting Class
)}
{classPortraitName}
);
};