Add PF2e spell description popovers in stat blocks
Clicking a spell name in a PF2e creature's stat block now opens a popover (desktop) or bottom sheet (mobile) showing full spell details: description, traits, rank, range, target, area, duration, defense, action cost icons, and heightening rules. All data is sourced from the embedded Foundry VTT spell items already in the bestiary cache. - Add SpellReference type replacing bare string spell arrays - Extract full spell data in pf2e-bestiary-adapter (description, traits, traditions, range, target, area, duration, defense, action cost, heightening, overlays) - Strip inline heightening text from descriptions to avoid duplication - Bold save outcome labels (Critical Success/Failure) in descriptions - Bump DB_VERSION to 6 for cache invalidation - Add useSwipeToDismissDown hook for mobile bottom sheet - Portal popover to document.body to escape transformed ancestors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,16 +31,71 @@ export interface LegendaryBlock {
|
||||
readonly entries: readonly TraitBlock[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A single spell entry within a creature's spellcasting block.
|
||||
*
|
||||
* `name` is always populated. All other fields are optional and are only
|
||||
* populated for PF2e creatures (sourced from embedded Foundry VTT spell items).
|
||||
* D&D 5e creatures populate only `name`.
|
||||
*/
|
||||
export interface SpellReference {
|
||||
readonly name: string;
|
||||
|
||||
/** Stable slug from Foundry VTT (e.g. "magic-missile"). PF2e only. */
|
||||
readonly slug?: string;
|
||||
|
||||
/** Plain-text description with Foundry enrichment tags stripped. */
|
||||
readonly description?: string;
|
||||
|
||||
/** Spell rank/level (0 = cantrip). */
|
||||
readonly rank?: number;
|
||||
|
||||
/** Trait slugs (e.g. ["concentrate", "manipulate", "force"]). */
|
||||
readonly traits?: readonly string[];
|
||||
|
||||
/** Tradition labels (e.g. ["arcane", "occult"]). */
|
||||
readonly traditions?: readonly string[];
|
||||
|
||||
/** Range (e.g. "30 feet", "touch"). */
|
||||
readonly range?: string;
|
||||
|
||||
/** Target (e.g. "1 creature"). */
|
||||
readonly target?: string;
|
||||
|
||||
/** Area (e.g. "20-foot burst"). */
|
||||
readonly area?: string;
|
||||
|
||||
/** Duration (e.g. "1 minute", "sustained up to 1 minute"). */
|
||||
readonly duration?: string;
|
||||
|
||||
/** Defense / save (e.g. "basic Reflex", "Will"). */
|
||||
readonly defense?: string;
|
||||
|
||||
/** Action cost. PF2e: number = action count, "reaction", "free", or
|
||||
* "1 minute" / "10 minutes" for cast time. */
|
||||
readonly actionCost?: string;
|
||||
|
||||
/**
|
||||
* Heightening rules text. May come from `system.heightening` (fixed
|
||||
* intervals) or `system.overlays` (variant casts). Plain text after
|
||||
* tag stripping.
|
||||
*/
|
||||
readonly heightening?: string;
|
||||
|
||||
/** Uses per day for "(×N)" rendering, when > 1. PF2e only. */
|
||||
readonly usesPerDay?: number;
|
||||
}
|
||||
|
||||
export interface DailySpells {
|
||||
readonly uses: number;
|
||||
readonly each: boolean;
|
||||
readonly spells: readonly string[];
|
||||
readonly spells: readonly SpellReference[];
|
||||
}
|
||||
|
||||
export interface SpellcastingBlock {
|
||||
readonly name: string;
|
||||
readonly headerText: string;
|
||||
readonly atWill?: readonly string[];
|
||||
readonly atWill?: readonly SpellReference[];
|
||||
readonly daily?: readonly DailySpells[];
|
||||
readonly restLong?: readonly DailySpells[];
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ export {
|
||||
type Pf2eCreature,
|
||||
proficiencyBonus,
|
||||
type SpellcastingBlock,
|
||||
type SpellReference,
|
||||
type TraitBlock,
|
||||
type TraitListItem,
|
||||
type TraitSegment,
|
||||
|
||||
Reference in New Issue
Block a user