Add Recall Knowledge DC and skill to PF2e stat blocks
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>
This commit is contained in:
118
packages/domain/src/recall-knowledge.ts
Normal file
118
packages/domain/src/recall-knowledge.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* 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 };
|
||||
}
|
||||
Reference in New Issue
Block a user