Skip to content

Commit

Permalink
Add more class/spell search options to ActorPF2e#getStatistic
Browse files Browse the repository at this point in the history
- "spell" and "spell-attack": highest spellcasting statistic as measured by attack modifier
- "spell-dc": highest spellcasting statistic as measured by DC
- "class-spell": highest among all class and spellcasting statistics
- "class" and "class-dc": alias of "classDC"
  • Loading branch information
stwlam committed Aug 9, 2023
1 parent 9387d2c commit 9458f09
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 14 deletions.
44 changes: 36 additions & 8 deletions src/module/actor/character/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,14 @@ import {
ensureProficiencyOption,
} from "@actor/modifiers.ts";
import {
AttributeString,
AttackItem,
AttributeString,
CheckContext,
CheckContextParams,
MovementType,
RollContext,
RollContextParams,
SaveType,
SkillLongForm,
} from "@actor/types.ts";
import {
ATTRIBUTE_ABBREVIATIONS,
Expand Down Expand Up @@ -74,7 +73,15 @@ import { PredicatePF2e } from "@system/predication.ts";
import { AttackRollParams, DamageRollParams, RollParameters } from "@system/rolls.ts";
import { ArmorStatistic } from "@system/statistic/armor-class.ts";
import { Statistic, StatisticCheck } from "@system/statistic/index.ts";
import { ErrorPF2e, objectHasKey, signedInteger, sluggify, sortedStringify, traitSlugToObject } from "@util";
import {
ErrorPF2e,
setHasElement,
signedInteger,
sluggify,
sortedStringify,
traitSlugToObject,
tupleHasValue,
} from "@util";
import { UUIDUtils } from "@util/uuid.ts";
import * as R from "remeda";
import { CraftingEntry, CraftingEntryData, CraftingFormula } from "./crafting/index.ts";
Expand Down Expand Up @@ -103,7 +110,13 @@ import {
imposeOversizedWeaponCondition,
} from "./helpers.ts";
import { CharacterSheetTabVisibility } from "./sheet.ts";
import { CharacterHitPointsSummary, CharacterSkill, CharacterSkills, DexterityModifierCapData } from "./types.ts";
import {
CharacterHitPointsSummary,
CharacterSkill,
CharacterSkills,
DexterityModifierCapData,
GuaranteedGetStatisticSlug,
} from "./types.ts";
import { CHARACTER_SHEET_TABS } from "./values.ts";

class CharacterPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | null> extends CreaturePF2e<TParent> {
Expand Down Expand Up @@ -183,12 +196,27 @@ class CharacterPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e
return deepClone(this.system.resources.heroPoints);
}

/** Retrieve lore skills, class statistics, and spellcasting */
override getStatistic(slug: SaveType | SkillLongForm | "perception" | "classDC" | MagicTradition): Statistic;
/** Retrieve lore skills, class statistics, and tradition-specific spellcasting */
override getStatistic(slug: GuaranteedGetStatisticSlug): Statistic;
override getStatistic(slug: string): Statistic | null;
override getStatistic(slug: string): Statistic | null {
if (slug === "classDC") return this.classDC;
if (objectHasKey(this.traditions, slug)) return this.traditions[slug];
if (tupleHasValue(["class", "class-dc", "classDC"], slug)) return this.classDC;
if (setHasElement(MAGIC_TRADITIONS, slug)) return this.traditions[slug];
if (slug === "class-spell") {
const highestClass = Object.values(this.classDCs)
.sort((a, b) => b.mod - a.mod)
.shift();
const highestSpell = this.spellcasting.contents
.flatMap((s) => s.statistic ?? [])
.sort((a, b) => b.mod - a.mod)
.shift();
return (
R.compact([highestClass, highestSpell])
.sort((a, b) => b.mod - a.mod)
.shift() ?? null
);
}

return this.classDCs[slug] ?? super.getStatistic(slug);
}

Expand Down
22 changes: 20 additions & 2 deletions src/module/actor/character/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { HitPointsSummary } from "@actor/base.ts";
import { AttributeString, SkillLongForm } from "@actor/types.ts";
import { AttributeString, SaveType, SkillLongForm } from "@actor/types.ts";
import { MagicTradition } from "@item/spell/types.ts";
import { ZeroToFour } from "@module/data.ts";
import { Statistic } from "@system/statistic/index.ts";

Expand All @@ -20,4 +21,21 @@ interface DexterityModifierCapData {
source: string;
}

export { CharacterHitPointsSummary, CharacterSkill, CharacterSkills, DexterityModifierCapData };
/** Slugs guaranteed to return a `Statistic` when passed to `CharacterPF2e#getStatistic` */
type GuaranteedGetStatisticSlug =
| SaveType
| SkillLongForm
| "perception"
| "class-spell"
| "class"
| "class-dc"
| "classDC"
| MagicTradition;

export {
CharacterHitPointsSummary,
CharacterSkill,
CharacterSkills,
DexterityModifierCapData,
GuaranteedGetStatisticSlug,
};
30 changes: 26 additions & 4 deletions src/module/actor/creature/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,35 @@ abstract class CreaturePF2e<
}, heldShields.slice(-1)[0]);
}

/** Retrieve percpetion and spellcasting statistics */
override getStatistic(slug: SaveType | SkillLongForm | "perception"): Statistic;
override getStatistic(slug: string): Statistic | null;
override getStatistic(slug: string): Statistic | null {
return slug === "perception"
? this.perception
: this.spellcasting.contents.flatMap((sc) => sc.statistic ?? []).find((s) => s.slug === slug) ??
super.getStatistic(slug);
switch (slug) {
case "perception":
return this.perception;
case "spell":
case "spell-attack":
return (
this.spellcasting.contents
.flatMap((sc) => sc.statistic ?? [])
.sort((a, b) => b.mod - a.mod)
.shift() ?? null
);
case "spell-dc":
return (
this.spellcasting.contents
.flatMap((sc) => sc.statistic ?? [])
.sort((a, b) => b.dc.value - a.dc.value)
.shift() ?? null
);

default:
return (
this.spellcasting.contents.flatMap((sc) => sc.statistic ?? []).find((s) => s.slug === slug) ??
super.getStatistic(slug)
);
}
}

protected override _initialize(options?: Record<string, unknown>): void {
Expand Down

0 comments on commit 9458f09

Please sign in to comment.