Display Recall Knowledge line below trait tags showing DC (from level via standard DC-by-level table, adjusted for rarity) and associated skill derived from creature type trait. Omitted for D&D creatures and creatures with no recognized type trait. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
119 lines
2.8 KiB
TypeScript
119 lines
2.8 KiB
TypeScript
/**
|
|
* PF2e Recall Knowledge DC calculation and type-to-skill mapping.
|
|
*
|
|
* DC is derived from creature level using the standard DC-by-level table
|
|
* (Player Core / GM Core), adjusted for rarity.
|
|
*/
|
|
|
|
/** Standard DC-by-level table from PF2e GM Core. Index = level + 1 (level -1 → index 0). */
|
|
const DC_BY_LEVEL: readonly number[] = [
|
|
13, // level -1
|
|
14, // level 0
|
|
15, // level 1
|
|
16, // level 2
|
|
18, // level 3
|
|
19, // level 4
|
|
20, // level 5
|
|
22, // level 6
|
|
23, // level 7
|
|
24, // level 8
|
|
26, // level 9
|
|
27, // level 10
|
|
28, // level 11
|
|
30, // level 12
|
|
31, // level 13
|
|
32, // level 14
|
|
34, // level 15
|
|
35, // level 16
|
|
36, // level 17
|
|
38, // level 18
|
|
39, // level 19
|
|
40, // level 20
|
|
42, // level 21
|
|
44, // level 22
|
|
46, // level 23
|
|
48, // level 24
|
|
50, // level 25
|
|
];
|
|
|
|
const RARITY_ADJUSTMENT: Readonly<Record<string, number>> = {
|
|
uncommon: 2,
|
|
rare: 5,
|
|
unique: 10,
|
|
};
|
|
|
|
/**
|
|
* Mapping from PF2e creature type traits to the skill(s) used for
|
|
* Recall Knowledge. Types that map to multiple skills list all of them.
|
|
*/
|
|
const TYPE_TO_SKILLS: Readonly<Record<string, readonly string[]>> = {
|
|
aberration: ["Occultism"],
|
|
animal: ["Nature"],
|
|
astral: ["Occultism"],
|
|
beast: ["Arcana", "Nature"],
|
|
celestial: ["Religion"],
|
|
construct: ["Arcana", "Crafting"],
|
|
dragon: ["Arcana"],
|
|
dream: ["Occultism"],
|
|
elemental: ["Arcana", "Nature"],
|
|
ethereal: ["Occultism"],
|
|
fey: ["Nature"],
|
|
fiend: ["Religion"],
|
|
fungus: ["Nature"],
|
|
giant: ["Society"],
|
|
humanoid: ["Society"],
|
|
monitor: ["Religion"],
|
|
ooze: ["Occultism"],
|
|
plant: ["Nature"],
|
|
undead: ["Religion"],
|
|
};
|
|
|
|
export interface RecallKnowledge {
|
|
readonly dc: number;
|
|
readonly type: string;
|
|
readonly skills: readonly string[];
|
|
}
|
|
|
|
/**
|
|
* Calculate Recall Knowledge DC, type, and skill(s) for a PF2e creature.
|
|
*
|
|
* Returns `null` when no recognized type trait is found in the creature's
|
|
* traits array, indicating the Recall Knowledge line should be omitted.
|
|
*/
|
|
export function recallKnowledge(
|
|
level: number,
|
|
traits: readonly string[],
|
|
): RecallKnowledge | null {
|
|
// Find the first type trait that maps to a skill
|
|
let matchedType: string | undefined;
|
|
let skills: readonly string[] | undefined;
|
|
|
|
for (const trait of traits) {
|
|
const lower = trait.toLowerCase();
|
|
const mapped = TYPE_TO_SKILLS[lower];
|
|
if (mapped) {
|
|
matchedType = trait;
|
|
skills = mapped;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!matchedType || !skills) return null;
|
|
|
|
// Calculate DC from level
|
|
const clampedIndex = Math.max(0, Math.min(level + 1, DC_BY_LEVEL.length - 1));
|
|
let dc = DC_BY_LEVEL[clampedIndex];
|
|
|
|
// Apply rarity adjustment (rarity traits are included in the traits array
|
|
// for non-common creatures by the normalization pipeline)
|
|
for (const trait of traits) {
|
|
const adjustment = RARITY_ADJUSTMENT[trait.toLowerCase()];
|
|
if (adjustment) {
|
|
dc += adjustment;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return { dc, type: matchedType, skills };
|
|
}
|