254 lines
8.7 KiB
JavaScript
254 lines
8.7 KiB
JavaScript
import sortBy from 'lodash/sortBy';
|
|
import { AbilityAccessors } from '../Ability';
|
|
import { FormatUtils } from '../Format';
|
|
import { getEntityId, getFriendlySubtypeName, getPrerequisites, getSubType, getType, getValue, getShouldExclude, } from './accessors';
|
|
import { PrerequisiteSubTypeEnum, PrerequisiteTypeEnum } from './constants';
|
|
import { validatePrerequisite } from './validators';
|
|
/**
|
|
*
|
|
* @param prerequisite
|
|
* @param prerequisiteData
|
|
*/
|
|
export function getPrerequisiteFailure(prerequisite, prerequisiteData) {
|
|
switch (getType(prerequisite)) {
|
|
case PrerequisiteTypeEnum.ABILITY_SCORE:
|
|
return getPrerequisiteFailureAbilityScore(prerequisite, prerequisiteData);
|
|
case PrerequisiteTypeEnum.PROFICIENCY:
|
|
return getPrerequisiteFailureProficiency(prerequisite);
|
|
case PrerequisiteTypeEnum.SPECIES:
|
|
return getPrerequisiteFailureRace(prerequisite);
|
|
case PrerequisiteTypeEnum.SIZE:
|
|
return getPrerequisiteFailureSize(prerequisite);
|
|
case PrerequisiteTypeEnum.SPECIES_OPTION:
|
|
return getPrerequisiteFailureSubrace(prerequisite);
|
|
case PrerequisiteTypeEnum.LEVEL:
|
|
return getPrerequisiteFailureLevel(prerequisite);
|
|
case PrerequisiteTypeEnum.CLASS:
|
|
return getPrerequisiteFailureClass(prerequisite);
|
|
case PrerequisiteTypeEnum.FEAT:
|
|
return getPrerequisiteFailureFeat(prerequisite);
|
|
case PrerequisiteTypeEnum.CLASS_FEATURE:
|
|
return getPrerequisiteFailureClassFeature(prerequisite);
|
|
case PrerequisiteTypeEnum.CUSTOM_VALUE:
|
|
default:
|
|
// not defined
|
|
}
|
|
return null;
|
|
}
|
|
/**
|
|
*
|
|
* @param prerequisite
|
|
* @param prerequisiteData
|
|
*/
|
|
export function getPrerequisiteFailureLevel(prerequisite) {
|
|
let requiredDescription = '';
|
|
switch (getSubType(prerequisite)) {
|
|
case PrerequisiteSubTypeEnum.CHARACTER_LEVEL:
|
|
let value = getValue(prerequisite);
|
|
value = value ? value : 1;
|
|
requiredDescription = `${FormatUtils.ordinalize(value)} Level`;
|
|
break;
|
|
default:
|
|
// not implemented
|
|
}
|
|
return {
|
|
type: PrerequisiteTypeEnum.LEVEL,
|
|
data: {
|
|
requiredChoice: getFriendlySubtypeName(prerequisite),
|
|
requiredDescription,
|
|
},
|
|
shouldExclude: !!getShouldExclude(prerequisite),
|
|
};
|
|
}
|
|
/**
|
|
*
|
|
* @param prerequisite
|
|
* @param prerequisiteData
|
|
*/
|
|
export function getPrerequisiteFailureAbilityScore(prerequisite, prerequisiteData) {
|
|
let statKey = '';
|
|
let currentAmount = null;
|
|
const entityId = getEntityId(prerequisite);
|
|
if (entityId !== null) {
|
|
const ability = prerequisiteData.abilityLookup[entityId];
|
|
statKey = AbilityAccessors.getStatKey(ability);
|
|
currentAmount = AbilityAccessors.getScore(ability);
|
|
}
|
|
return {
|
|
type: PrerequisiteTypeEnum.ABILITY_SCORE,
|
|
data: {
|
|
statKey,
|
|
currentAmount,
|
|
requiredValue: getValue(prerequisite),
|
|
requiredChoice: getFriendlySubtypeName(prerequisite),
|
|
requiredDescription: `${getFriendlySubtypeName(prerequisite)} ${getValue(prerequisite)}+`,
|
|
},
|
|
shouldExclude: !!getShouldExclude(prerequisite),
|
|
};
|
|
}
|
|
/**
|
|
*
|
|
* @param prerequisite
|
|
* @param prerequisiteData
|
|
*/
|
|
export function getPrerequisiteFailureProficiency(prerequisite) {
|
|
return {
|
|
type: PrerequisiteTypeEnum.PROFICIENCY,
|
|
data: {
|
|
requiredChoice: getFriendlySubtypeName(prerequisite),
|
|
requiredDescription: `${getFriendlySubtypeName(prerequisite)} Proficiency`,
|
|
},
|
|
shouldExclude: !!getShouldExclude(prerequisite),
|
|
};
|
|
}
|
|
/**
|
|
*
|
|
* @param prerequisite
|
|
* @param prerequisiteData
|
|
*/
|
|
export function getPrerequisiteFailureRace(prerequisite) {
|
|
return {
|
|
type: PrerequisiteTypeEnum.SPECIES,
|
|
data: {
|
|
requiredChoice: getFriendlySubtypeName(prerequisite),
|
|
requiredDescription: getFriendlySubtypeName(prerequisite),
|
|
},
|
|
shouldExclude: !!getShouldExclude(prerequisite),
|
|
};
|
|
}
|
|
/**
|
|
*
|
|
* @param prerequisite
|
|
* @param prerequisiteData
|
|
*/
|
|
export function getPrerequisiteFailureSubrace(prerequisite) {
|
|
return {
|
|
type: PrerequisiteTypeEnum.SPECIES_OPTION,
|
|
data: {
|
|
requiredChoice: getFriendlySubtypeName(prerequisite),
|
|
requiredDescription: getFriendlySubtypeName(prerequisite),
|
|
},
|
|
shouldExclude: !!getShouldExclude(prerequisite),
|
|
};
|
|
}
|
|
/**
|
|
*
|
|
* @param prerequisite
|
|
* @param prerequisiteData
|
|
*/
|
|
export function getPrerequisiteFailureSize(prerequisite) {
|
|
return {
|
|
type: PrerequisiteTypeEnum.SIZE,
|
|
data: {
|
|
requiredChoice: getFriendlySubtypeName(prerequisite),
|
|
requiredDescription: `${getFriendlySubtypeName(prerequisite)} Size`,
|
|
},
|
|
shouldExclude: !!getShouldExclude(prerequisite),
|
|
};
|
|
}
|
|
/**
|
|
*
|
|
* @param prerequisite
|
|
* @param prerequisiteData
|
|
*/
|
|
export function getPrerequisiteFailureClass(prerequisite) {
|
|
return {
|
|
type: PrerequisiteTypeEnum.CLASS,
|
|
data: {
|
|
requiredChoice: getFriendlySubtypeName(prerequisite),
|
|
requiredDescription: `${getFriendlySubtypeName(prerequisite)}`,
|
|
},
|
|
shouldExclude: !!getShouldExclude(prerequisite),
|
|
};
|
|
}
|
|
export const getPrerequisiteFailureClassFeature = (prerequisite) => ({
|
|
type: PrerequisiteTypeEnum.CLASS_FEATURE,
|
|
data: {
|
|
requiredChoice: prerequisite.friendlySubTypeName,
|
|
requiredDescription: prerequisite.friendlySubTypeName,
|
|
},
|
|
shouldExclude: !!getShouldExclude(prerequisite),
|
|
});
|
|
/**
|
|
*
|
|
* @param prerequisite
|
|
* @param prerequisiteData
|
|
*/
|
|
export function getPrerequisiteFailureFeat(prerequisite) {
|
|
return {
|
|
type: PrerequisiteTypeEnum.FEAT,
|
|
data: {
|
|
requiredChoice: getFriendlySubtypeName(prerequisite),
|
|
requiredDescription: `${getFriendlySubtypeName(prerequisite)}`,
|
|
},
|
|
shouldExclude: !!getShouldExclude(prerequisite),
|
|
};
|
|
}
|
|
/**
|
|
*
|
|
* @param prerequisiteGrouping
|
|
* @param prerequisiteData
|
|
*/
|
|
export function getPrerequisiteGroupingFailures(prerequisiteGrouping, prerequisiteData) {
|
|
const groupingFailures = [];
|
|
if (prerequisiteGrouping !== null) {
|
|
prerequisiteGrouping.forEach((prerequisiteGroup) => {
|
|
const groupFailures = [];
|
|
const prerequisites = getPrerequisites(prerequisiteGroup);
|
|
prerequisites.forEach((prerequisite) => {
|
|
if (!validatePrerequisite(prerequisite, prerequisiteData)) {
|
|
const prereqFailure = getPrerequisiteFailure(prerequisite, prerequisiteData);
|
|
if (prereqFailure) {
|
|
groupFailures.push(prereqFailure);
|
|
}
|
|
}
|
|
});
|
|
groupingFailures.push(groupFailures);
|
|
});
|
|
}
|
|
return groupingFailures.filter((group) => group.length);
|
|
}
|
|
// Creates a string that summarizes the prerequisite failures for feats and multiclassing
|
|
export function getPrerequisiteFailuresText(prereqFailures) {
|
|
//get all the prerequisite failures, sorted so that if every group failure is a missing prereq, they come first
|
|
const failures = sortBy(prereqFailures, (failureGroup) => (failureGroup.every((f) => !f.shouldExclude) ? 0 : 1));
|
|
// Create an intro string for the summary
|
|
let intro = '';
|
|
// Check if all failures are either missing or prohibited
|
|
const hasOnlyMissingFailures = failures.every((failureGroup) => failureGroup.every((f) => !f.shouldExclude));
|
|
const hasOnlyProhibitedFailures = failures.every((failureGroup) => failureGroup.every((f) => f.shouldExclude));
|
|
// Determine the intro text based on the type of failures
|
|
if (hasOnlyMissingFailures) {
|
|
intro = 'Missing: ';
|
|
}
|
|
else if (hasOnlyProhibitedFailures) {
|
|
intro = 'Prohibited by: ';
|
|
}
|
|
else {
|
|
intro = 'Requires: ';
|
|
}
|
|
// Each failure is sorted so that prohibited failures come last, and then combined into a single string
|
|
const combinedStrings = failures
|
|
.map((failure) => sortBy(failure, (f) => (f.shouldExclude ? 1 : 0))
|
|
.map((failureAnd) => {
|
|
if (failureAnd.shouldExclude && !hasOnlyProhibitedFailures && !hasOnlyMissingFailures) {
|
|
return `Prohibited by: ${failureAnd.data.requiredDescription}`;
|
|
}
|
|
return `${failureAnd.data.requiredDescription}`;
|
|
})
|
|
.reduce((acc, desc, idx) => {
|
|
let connector = '';
|
|
if (idx < failure.length - 2) {
|
|
connector = ', ';
|
|
}
|
|
else if (idx < failure.length - 1) {
|
|
connector = ' and ';
|
|
}
|
|
acc += `${desc}${connector}`;
|
|
return acc;
|
|
}, ''))
|
|
.join(' or ');
|
|
// return the intro text followed by the combined strings
|
|
return `${intro}${combinedStrings}`;
|
|
}
|