diff --git a/scripts/parse_mpmb.py b/scripts/parse_mpmb.py index 1499010..0f968be 100644 --- a/scripts/parse_mpmb.py +++ b/scripts/parse_mpmb.py @@ -2,8 +2,9 @@ """Parse MPMB all_WotC_published.js into structured JSON files""" import re, json, os -INPUT = "/home/nilsb/Downloads/all_WotC_published.js" -OUT_DIR = "/home/nilsb/Documents/Projects/TTRPG_manager/src/assets/srd" +INPUT = os.environ.get("MPMB_INPUT", "/home/nilsb/Downloads/all_WotC_published.js") +# Output path (the app reads from src/data/srd). Override with MPMB_OUT for a dry run. +OUT_DIR = os.environ.get("MPMB_OUT", "/home/nilsb/Documents/Projects/TTRPG_manager/src/data/srd") def parse_mpmb(filepath): with open(filepath, 'r', encoding='utf-8') as f: @@ -87,6 +88,16 @@ def safe_extract_fields(obj_str): 'description': r'description\s*:\s*["\']([^"]+)["\']', 'weight': r'weight\s*:\s*(-?\d+)', 'prerequisite': r'prerequisite\s*:\s*["\']([^"\']+)["\']', + # --- spell fields (additive; only present on SpellsList entries) --- + 'level': r'\blevel\s*:\s*(\d+)', + 'school': r'\bschool\s*:\s*["\']([^"\']+)["\']', + 'time': r'\btime\s*:\s*["\']([^"\']+)["\']', + 'range': r'\brange\s*:\s*["\']([^"\']+)["\']', + 'components': r'\bcomponents\s*:\s*["\']([^"\']+)["\']', + 'duration': r'\bduration\s*:\s*["\']([^"\']+)["\']', + 'save': r'\bsave\s*:\s*["\']([^"\']+)["\']', + 'ritual': r'\britual\s*:\s*(true|false)', + 'classes': r'\bclasses\s*:\s*(\[[^\]]*\])', } for field, pattern in patterns.items(): m = re.search(pattern, obj_str) @@ -94,6 +105,13 @@ def safe_extract_fields(obj_str): val = m.group(1) if field == 'weight': val = int(val) + elif field == 'level': + val = int(val) + elif field == 'ritual': + val = (val == 'true') + elif field == 'classes': + # ["cleric","warlock"] -> list of class names + val = re.findall(r'["\']([^"\']+)["\']', val) elif field == 'source': # Parse [[SourceName, page], [SourceName2, page2]] sources = re.findall(r'\["([^"]+)",?\s*(\d+)?\]', val) diff --git a/src/data/srd/mpmb-spells.json b/src/data/srd/mpmb-spells.json index 7735489..ba06ee7 100644 --- a/src/data/srd/mpmb-spells.json +++ b/src/data/srd/mpmb-spells.json @@ -7,7 +7,18 @@ "page": 214 } ], - "description": "Two portals, up to 500 ft apart, teleport any to other side; portals are filled with opaque mist" + "description": "Two portals, up to 500 ft apart, teleport any to other side; portals are filled with opaque mist", + "level": 6, + "school": "Conj", + "time": "1 a", + "range": "500 ft", + "components": "V,S", + "duration": "Conc, 10 min", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "armor of agathys": { "name": "Armor of Agathys", @@ -17,7 +28,16 @@ "page": 215 } ], - "description": "5+5/SL temp HP; as long as temp HP last any crea that hits in melee takes 5+5/SL Cold dmg" + "description": "5+5/SL temp HP; as long as temp HP last any crea that hits in melee takes 5+5/SL Cold dmg", + "level": 1, + "school": "Abjur", + "time": "1 a", + "range": "Self", + "components": "V,S,M", + "duration": "1 h", + "classes": [ + "warlock" + ] }, "arms of hadar": { "name": "Arms of Hadar", @@ -27,7 +47,17 @@ "page": 215 } ], - "description": "2d6+1d6/SL Necrotic dmg; save halves; on failed save no reactions until next turn" + "description": "2d6+1d6/SL Necrotic dmg; save halves; on failed save no reactions until next turn", + "level": 1, + "school": "Conj", + "time": "1 a", + "range": "S:10-ft rad", + "components": "V,S", + "duration": "Instantaneous", + "save": "Str", + "classes": [ + "warlock" + ] }, "aura of life": { "name": "Aura of Life", @@ -37,7 +67,16 @@ "page": 216 } ], - "description": "Me + any crea while in area Necrotic dmg resist.; at turn start, 0 HP living in area heal 1 HP" + "description": "Me + any crea while in area Necrotic dmg resist.; at turn start, 0 HP living in area heal 1 HP", + "level": 4, + "school": "Abjur", + "time": "1 a", + "range": "S:30-ft rad", + "components": "V", + "duration": "Conc, 10 min", + "classes": [ + "paladin" + ] }, "aura of purity": { "name": "Aura of Purity", @@ -47,7 +86,16 @@ "page": 216 } ], - "description": "Me + any crea while in area Poison dmg resist., immune to disease, adv. on saves vs. conditions" + "description": "Me + any crea while in area Poison dmg resist., immune to disease, adv. on saves vs. conditions", + "level": 4, + "school": "Abjur", + "time": "1 a", + "range": "S:30-ft rad", + "components": "V", + "duration": "Conc, 10 min", + "classes": [ + "paladin" + ] }, "aura of vitality": { "name": "Aura of Vitality", @@ -57,7 +105,16 @@ "page": 216 } ], - "description": "As a bonus action for the duration, I can heal 2d6 HP to 1 creature in range (can be me)" + "description": "As a bonus action for the duration, I can heal 2d6 HP to 1 creature in range (can be me)", + "level": 3, + "school": "Evoc", + "time": "1 a", + "range": "S:30-ft rad", + "components": "V", + "duration": "Conc, 1 min", + "classes": [ + "paladin" + ] }, "banishing smite": { "name": "Banishing Smite", @@ -67,7 +124,16 @@ "page": 216 } ], - "description": "Next weapon hit +5d10 Force dmg; if this brings target HP<50, I banish it until spell ends" + "description": "Next weapon hit +5d10 Force dmg; if this brings target HP<50, I banish it until spell ends", + "level": 5, + "school": "Abjur", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "classes": [ + "paladin" + ] }, "beast sense": { "name": "Beast Sense", @@ -77,7 +143,18 @@ "page": 217 } ], - "description": "Use 1 willing beast's senses; I'm blinded and deafened while doing so" + "description": "Use 1 willing beast's senses; I'm blinded and deafened while doing so", + "level": 2, + "school": "Div", + "time": "1 a", + "range": "Touch", + "components": "S", + "duration": "Conc, 1 h", + "ritual": true, + "classes": [ + "druid", + "ranger" + ] }, "blade ward": { "name": "Blade Ward", @@ -87,7 +164,19 @@ "page": 218 } ], - "description": "Until the end of my next turn, Bludgeoning, Piercing, and Slashing dmg resist. vs. weapons" + "description": "Until the end of my next turn, Bludgeoning, Piercing, and Slashing dmg resist. vs. weapons", + "level": 0, + "school": "Abjur", + "time": "1 a", + "range": "Self", + "components": "V,S", + "duration": "1 rnd", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "blinding smite": { "name": "Blinding Smite", @@ -97,7 +186,17 @@ "page": 219 } ], - "description": "Next melee weapon hit +3d8 Radiant dmg; save or blinded; extra save at end of every turn" + "description": "Next melee weapon hit +3d8 Radiant dmg; save or blinded; extra save at end of every turn", + "level": 3, + "school": "Evoc", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "save": "Con", + "classes": [ + "paladin" + ] }, "chromatic orb": { "name": "Chromatic Orb", @@ -107,7 +206,17 @@ "page": 221 } ], - "description": "Spell attack for 3d8+1d8/SL Acid, Cold, Fire, Lightning, Poison or Thunder dmg (50gp)" + "description": "Spell attack for 3d8+1d8/SL Acid, Cold, Fire, Lightning, Poison or Thunder dmg (50gp)", + "level": 1, + "school": "Evoc", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Instantaneous", + "classes": [ + "sorcerer", + "wizard" + ] }, "circle of power": { "name": "Circle of Power", @@ -117,7 +226,16 @@ "page": 221 } ], - "description": "Any crea while in area adv. on saves vs. magical effects; if save would half dmg it takes no dmg" + "description": "Any crea while in area adv. on saves vs. magical effects; if save would half dmg it takes no dmg", + "level": 5, + "school": "Abjur", + "time": "1 a", + "range": "S:30-ft rad", + "components": "V", + "duration": "Conc, 10 min", + "classes": [ + "paladin" + ] }, "cloud of daggers": { "name": "Cloud of Daggers", @@ -127,7 +245,19 @@ "page": 222 } ], - "description": "5-ft cube 4d4+2d4/SL Slashing dmg to all that enter or start turn in area" + "description": "5-ft cube 4d4+2d4/SL Slashing dmg to all that enter or start turn in area", + "level": 2, + "school": "Conj", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "compelled duel": { "name": "Compelled Duel", @@ -137,7 +267,17 @@ "page": 224 } ], - "description": "1 crea save or dis. on attacks vs. not-me and save if moving more than 30 ft away" + "description": "1 crea save or dis. on attacks vs. not-me and save if moving more than 30 ft away", + "level": 1, + "school": "Ench", + "time": "1 bns", + "range": "30 ft", + "components": "V", + "duration": "Conc, 1 min", + "save": "Wis", + "classes": [ + "paladin" + ] }, "conjure barrage": { "name": "Conjure Barrage", @@ -147,7 +287,17 @@ "page": 225 } ], - "description": "Throw weapon or ammo; copies rain down for 3d8 dmg; dmg type as weapon; save halves" + "description": "Throw weapon or ammo; copies rain down for 3d8 dmg; dmg type as weapon; save halves", + "level": 3, + "school": "Conj", + "time": "1 a", + "range": "S:60", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "ranger" + ] }, "conjure volley": { "name": "Conjure Volley", @@ -157,7 +307,17 @@ "page": 226 } ], - "description": "Turn ammo/thrown wea into volley; 40-ft rad 20-ft high 8d8 dmg; dmg type as weapon; save halves" + "description": "Turn ammo/thrown wea into volley; 40-ft rad 20-ft high 8d8 dmg; dmg type as weapon; save halves", + "level": 5, + "school": "Conj", + "time": "1 a", + "range": "150 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "ranger" + ] }, "cordon of arrows": { "name": "Cordon of Arrows", @@ -167,7 +327,17 @@ "page": 228 } ], - "description": "4+2/SL arrows/bolts attack first crea in 30 ft one at a time for 1d6 Piercing dmg; save halves" + "description": "4+2/SL arrows/bolts attack first crea in 30 ft one at a time for 1d6 Piercing dmg; save halves", + "level": 2, + "school": "Trans", + "time": "1 a", + "range": "5 ft", + "components": "V,S,M", + "duration": "8 h", + "save": "Dex", + "classes": [ + "ranger" + ] }, "crown of madness": { "name": "Crown of Madness", @@ -177,7 +347,20 @@ "page": 229 } ], - "description": "1 humanoid save or charmed and must melee attack against crea chosen by me; extra save/rnd" + "description": "1 humanoid save or charmed and must melee attack against crea chosen by me; extra save/rnd", + "level": 2, + "school": "Ench", + "time": "1 a", + "range": "120 ft", + "components": "V,S", + "duration": "Conc, 1 min", + "save": "Wis", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "crusader's mantle": { "name": "Crusader", @@ -187,7 +370,16 @@ "page": 230 } ], - "description": "Me and allies in range deal extra 1d4 Radiant dmg with weapon attacks" + "description": "Me and allies in range deal extra 1d4 Radiant dmg with weapon attacks", + "level": 3, + "school": "Evoc", + "time": "1 a", + "range": "S:30-ft rad", + "components": "V", + "duration": "Conc, 1 min", + "classes": [ + "paladin" + ] }, "destructive wave": { "name": "Destructive Wave", @@ -197,7 +389,17 @@ "page": 231 } ], - "description": "Any crea 5d6 Thunder dmg \\u0026 5d6 Radiant or Necrotic dmg \\u0026 knocked prone; save halves, not prone" + "description": "Any crea 5d6 Thunder dmg \\u0026 5d6 Radiant or Necrotic dmg \\u0026 knocked prone; save halves, not prone", + "level": 5, + "school": "Evoc", + "time": "1 a", + "range": "S:30-ft rad", + "components": "V", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "paladin" + ] }, "dissonant whispers": { "name": "Dissonant Whispers", @@ -207,7 +409,17 @@ "page": 234 } ], - "description": "1 crea 3d6+1d6/SL Psychic dmg and flee; save halves and no fleeing; deaf crea are immune" + "description": "1 crea 3d6+1d6/SL Psychic dmg and flee; save halves and no fleeing; deaf crea are immune", + "level": 1, + "school": "Ench", + "time": "1 a", + "range": "60 ft", + "components": "V", + "duration": "Instantaneous", + "save": "Wis", + "classes": [ + "bard" + ] }, "elemental weapon": { "name": "Elemental Weapon", @@ -217,7 +429,17 @@ "page": 237 } ], - "description": "+1 magical weapon; +1d4 Acid, Cold, Fire, Lightning, or Thunder dmg; SL5: +2/+2d4, SL7: +3/+3d4" + "description": "+1 magical weapon; +1d4 Acid, Cold, Fire, Lightning, or Thunder dmg; SL5: +2/+2d4, SL7: +3/+3d4", + "level": 3, + "school": "Trans", + "time": "1 a", + "range": "Touch", + "components": "V,S", + "duration": "Conc, 1 h", + "classes": [ + "artificer", + "paladin" + ] }, "ensnaring strike": { "name": "Ensnaring Strike", @@ -227,7 +449,17 @@ "page": 237 } ], - "description": "Next crea hit save (Large adv.) or restrained, 1d6+1d6/SL Piercing dmg/rnd; Str check to escape" + "description": "Next crea hit save (Large adv.) or restrained, 1d6+1d6/SL Piercing dmg/rnd; Str check to escape", + "level": 1, + "school": "Conj", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "save": "Str", + "classes": [ + "ranger" + ] }, "feign death": { "name": "Feign Death", @@ -237,7 +469,20 @@ "page": 240 } ], - "description": "Willing creature appears dead; it is blinded, incapacitated, has dmg resist. all but Psychic, and speed 0" + "description": "Willing creature appears dead; it is blinded, incapacitated, has dmg resist. all but Psychic, and speed 0", + "level": 3, + "school": "Necro", + "time": "1 a", + "range": "Touch", + "components": "V,S,M", + "duration": "1 h (D)", + "ritual": true, + "classes": [ + "bard", + "cleric", + "druid", + "wizard" + ] }, "friends": { "name": "Friends", @@ -247,7 +492,19 @@ "page": 244 } ], - "description": "Adv. on Cha checks vs. 1 crea currently not hostile; when spell ends, crea knows and becomes hostile" + "description": "Adv. on Cha checks vs. 1 crea currently not hostile; when spell ends, crea knows and becomes hostile", + "level": 0, + "school": "Ench", + "time": "1 a", + "range": "Self", + "components": "S,M", + "duration": "Conc, 1 min", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "grasping vine": { "name": "Grasping Vine", @@ -257,7 +514,18 @@ "page": 246 } ], - "description": "Conjure vine with 30 ft reach; bns a to direct to 1 crea save or pulled 20 ft to vine" + "description": "Conjure vine with 30 ft reach; bns a to direct to 1 crea save or pulled 20 ft to vine", + "level": 4, + "school": "Conj", + "time": "1 bns", + "range": "30 ft", + "components": "V,S", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "druid", + "ranger" + ] }, "hail of thorns": { "name": "Hail of Thorns", @@ -267,7 +535,17 @@ "page": 249 } ], - "description": "Next ranged weapon hit, all within 5 ft of target 1d10+1d10/SL Piercing dmg; save halves" + "description": "Next ranged weapon hit, all within 5 ft of target 1d10+1d10/SL Piercing dmg; save halves", + "level": 1, + "school": "Conj", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "ranger" + ] }, "hex": { "name": "Hex", @@ -277,7 +555,16 @@ "page": 251 } ], - "description": "1 crea +1d6 Necrotic dmg from my atks; dis. on chosen ability checks; SL3: conc, 8h; SL5: conc, 24h" + "description": "1 crea +1d6 Necrotic dmg from my atks; dis. on chosen ability checks; SL3: conc, 8h; SL5: conc, 24h", + "level": 1, + "school": "Ench", + "time": "1 bns", + "range": "90 ft", + "components": "V,S,M", + "duration": "Conc, 1 h", + "classes": [ + "warlock" + ] }, "hunger of hadar": { "name": "Hunger of Hadar", @@ -287,7 +574,17 @@ "page": 251 } ], - "description": "20-ft rad all: blind while in, start turn in 2d6 Cold dmg, end turn in save or 2d6 Acid dmg" + "description": "20-ft rad all: blind while in, start turn in 2d6 Cold dmg, end turn in save or 2d6 Acid dmg", + "level": 3, + "school": "Conj", + "time": "1 a", + "range": "150 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "warlock" + ] }, "lightning arrow": { "name": "Lightning Arrow", @@ -297,7 +594,17 @@ "page": 255 } ], - "description": "Next rngd wea atk 4d8+1d8/SL Lightn. dmg, miss half; 10 ft all 2d8+1d8/SL Lightn. dmg, save half" + "description": "Next rngd wea atk 4d8+1d8/SL Lightn. dmg, miss half; 10 ft all 2d8+1d8/SL Lightn. dmg, save half", + "level": 3, + "school": "Trans", + "time": "1 bns", + "range": "Self", + "components": "V,S", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "ranger" + ] }, "phantasmal force": { "name": "Phantasmal Force", @@ -307,7 +614,19 @@ "page": 264 } ], - "description": "1 crea save or sees 10 ft cube illusion that does 1d6 Psychic dmg/rnd; Int(Investigation) vs. spell DC" + "description": "1 crea save or sees 10 ft cube illusion that does 1d6 Psychic dmg/rnd; Int(Investigation) vs. spell DC", + "level": 2, + "school": "Illus", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Int", + "classes": [ + "bard", + "sorcerer", + "wizard" + ] }, "power word heal": { "name": "Power Word Heal", @@ -317,7 +636,16 @@ "page": 266 } ], - "description": "1 crea heals all HP and stops being charmed, frightened, paralyzed, stunned; it can use rea to stand up" + "description": "1 crea heals all HP and stops being charmed, frightened, paralyzed, stunned; it can use rea to stand up", + "level": 9, + "school": "Evoc", + "time": "1 a", + "range": "Touch", + "components": "V,S", + "duration": "Instantaneous", + "classes": [ + "bard" + ] }, "ray of sickness": { "name": "Ray of Sickness", @@ -327,7 +655,18 @@ "page": 271 } ], - "description": "Spell attack for 2d8+1d8/SL Poison dmg; save or also poisoned until end of my next turn" + "description": "Spell attack for 2d8+1d8/SL Poison dmg; save or also poisoned until end of my next turn", + "level": 1, + "school": "Necro", + "time": "1 a", + "range": "60 ft", + "components": "V,S", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "sorcerer", + "wizard" + ] }, "searing smite": { "name": "Searing Smite", @@ -337,7 +676,17 @@ "page": 274 } ], - "description": "Next melee weapon hit +1d6+1d6/SL Fire dmg and target ignites: start of turn save to end or 1d6 dmg" + "description": "Next melee weapon hit +1d6+1d6/SL Fire dmg and target ignites: start of turn save to end or 1d6 dmg", + "level": 1, + "school": "Evoc", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "save": "Con", + "classes": [ + "paladin" + ] }, "staggering smite": { "name": "Staggering Smite", @@ -347,7 +696,17 @@ "page": 278 } ], - "description": "Next melee weapon hit +4d6 Psychic dmg and save or dis. on atks/chks, no rea, until end next turn" + "description": "Next melee weapon hit +4d6 Psychic dmg and save or dis. on atks/chks, no rea, until end next turn", + "level": 4, + "school": "Evoc", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "save": "Wis", + "classes": [ + "paladin" + ] }, "swift quiver": { "name": "Swift Quiver", @@ -357,7 +716,16 @@ "page": 279 } ], - "description": "Quiver gives nonmagical ammo; bns a to make 2 atks with weapon that uses ammo from that quiver" + "description": "Quiver gives nonmagical ammo; bns a to make 2 atks with weapon that uses ammo from that quiver", + "level": 5, + "school": "Trans", + "time": "1 bns", + "range": "Touch", + "components": "V,S,M", + "duration": "Conc, 1 min", + "classes": [ + "ranger" + ] }, "telepathy": { "name": "Telepathy", @@ -367,7 +735,16 @@ "page": 281 } ], - "description": "1 willing crea Int>0 and I telepathic link; share words, sensory information if on same plane" + "description": "1 willing crea Int>0 and I telepathic link; share words, sensory information if on same plane", + "level": 8, + "school": "Evoc", + "time": "1 a", + "range": "Unlimited", + "components": "V,S,M", + "duration": "24 h", + "classes": [ + "wizard" + ] }, "thorn whip": { "name": "Thorn Whip", @@ -377,7 +754,17 @@ "page": 282 } ], - "description": "Melee spell atk for 1d6 Piercing dmg and pull crea up to 10 ft towards me; +1d6 at CL 5, 11, and 17" + "description": "Melee spell atk for 1d6 Piercing dmg and pull crea up to 10 ft towards me; +1d6 at CL 5, 11, and 17", + "level": 0, + "school": "Trans", + "time": "1 a", + "range": "30 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "classes": [ + "artificer", + "druid" + ] }, "thunderous smite": { "name": "Thunderous Smite", @@ -387,7 +774,17 @@ "page": 282 } ], - "description": "Next melee weapon hit +2d6 Thunder dmg and save or 10 ft push and prone; audible in 300 ft" + "description": "Next melee weapon hit +2d6 Thunder dmg and save or 10 ft push and prone; audible in 300 ft", + "level": 1, + "school": "Evoc", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "save": "Str", + "classes": [ + "paladin" + ] }, "tsunami": { "name": "Tsunami", @@ -397,7 +794,17 @@ "page": 284 } ], - "description": "300\\xD750\\xD7300ft (l\\xD7w\\xD7h) wall of water moves away at 50 ft/rnd; 6d10 Bludg. dmg; save halves; see B" + "description": "300\\xD750\\xD7300ft (l\\xD7w\\xD7h) wall of water moves away at 50 ft/rnd; 6d10 Bludg. dmg; save halves; see B", + "level": 8, + "school": "Conj", + "time": "1 min", + "range": "Sight", + "components": "V,S", + "duration": "Conc, 6 rnds", + "save": "Str", + "classes": [ + "druid" + ] }, "witch bolt": { "name": "Witch Bolt", @@ -407,7 +814,18 @@ "page": 289 } ], - "description": "Rngd spell atk 1d12+1d12/SL Lightn. dmg; 1 a 1d12 Lightn. dmg; ends if out of range or I do other a" + "description": "Rngd spell atk 1d12+1d12/SL Lightn. dmg; 1 a 1d12 Lightn. dmg; ends if out of range or I do other a", + "level": 1, + "school": "Evoc", + "time": "1 a", + "range": "30 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "wrathful smite": { "name": "Wrathful Smite", @@ -417,7 +835,17 @@ "page": 289 } ], - "description": "Next melee weapon hit +1d6 Psychic dmg and save or frightened; it can take 1 a for extra save" + "description": "Next melee weapon hit +1d6 Psychic dmg and save or frightened; it can take 1 a for extra save", + "level": 1, + "school": "Evoc", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "save": "Wis", + "classes": [ + "paladin" + ] }, "abi-dalzim's horrid wilting": { "name": "Abi-Dalzim", @@ -431,7 +859,18 @@ "page": 15 } ], - "description": "30-ft cube all crea 12d8 Necrotic dmg; save halves; plants/water elem. dis. const/undead immune" + "description": "30-ft cube all crea 12d8 Necrotic dmg; save halves; plants/water elem. dis. const/undead immune", + "level": 8, + "school": "Necro", + "time": "1 a", + "range": "150 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "sorcerer", + "wizard" + ] }, "absorb elements": { "name": "Absorb Elements", @@ -445,7 +884,20 @@ "page": 15 } ], - "description": "Acid, Cold, Fire, Lightning, or Thunder resistance till next turn start; first melee hit +1d6+1d6/SL dmg" + "description": "Acid, Cold, Fire, Lightning, or Thunder resistance till next turn start; first melee hit +1d6+1d6/SL dmg", + "level": 1, + "school": "Abjur", + "time": "1 rea", + "range": "Self", + "components": "S", + "duration": "1 rnd", + "classes": [ + "artificer", + "druid", + "ranger", + "sorcerer", + "wizard" + ] }, "aganazzar's scorcher": { "name": "Aganazzar", @@ -459,7 +911,18 @@ "page": 15 } ], - "description": "30-ft long 5-ft wide line all creatures 3d8+1d8/SL Fire dmg; save halves" + "description": "30-ft long 5-ft wide line all creatures 3d8+1d8/SL Fire dmg; save halves", + "level": 2, + "school": "Evoc", + "time": "1 a", + "range": "30-ft line", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "sorcerer", + "wizard" + ] }, "beast bond": { "name": "Beast Bond", @@ -473,7 +936,17 @@ "page": 15 } ], - "description": "Telepathic link with 1 beast Int<4 while in line of sight; beast has adv. on attacks vs. crea I can see" + "description": "Telepathic link with 1 beast Int<4 while in line of sight; beast has adv. on attacks vs. crea I can see", + "level": 1, + "school": "Div", + "time": "1 a", + "range": "Touch", + "components": "V,S,M", + "duration": "Conc, 10 min", + "classes": [ + "druid", + "ranger" + ] }, "bones of the earth": { "name": "Bones of the Earth", @@ -487,7 +960,17 @@ "page": 15 } ], - "description": "6+2/SL 5-ft dia stone lift up 30 ft; \\u2265Medium crea save or lifted, 6d6 Bludg. dmg if hit ceiling; see B" + "description": "6+2/SL 5-ft dia stone lift up 30 ft; \\u2265Medium crea save or lifted, 6d6 Bludg. dmg if hit ceiling; see B", + "level": 6, + "school": "Trans", + "time": "1 a", + "range": "120 ft", + "components": "V,S", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "druid" + ] }, "catapult": { "name": "Catapult", @@ -501,7 +984,19 @@ "page": 15 } ], - "description": "Send 5+5/SL lb unattended object in 90 ft straight line; if crea hit, save or 3d8+1d8/SL Bludg. dmg" + "description": "Send 5+5/SL lb unattended object in 90 ft straight line; if crea hit, save or 3d8+1d8/SL Bludg. dmg", + "level": 1, + "school": "Trans", + "time": "1 a", + "range": "60 ft", + "components": "S", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "artificer", + "sorcerer", + "wizard" + ] }, "control flames": { "name": "Control Flames", @@ -515,7 +1010,18 @@ "page": 16 } ], - "description": "Nonmagical flame up to 5 cu ft; instant: expand/extinguish, 1h: brighten/dim/color/create shapes" + "description": "Nonmagical flame up to 5 cu ft; instant: expand/extinguish, 1h: brighten/dim/color/create shapes", + "level": 0, + "school": "Trans", + "time": "1 a", + "range": "60 ft", + "components": "S", + "duration": "Instant. or 1 h", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "control winds": { "name": "Control Winds", @@ -533,7 +1039,18 @@ "page": 8 } ], - "description": "100-ft cube of air either gusts, downdraft, or updraft; affects flying/jump/ranged; 1 a change; see B" + "description": "100-ft cube of air either gusts, downdraft, or updraft; affects flying/jump/ranged; 1 a change; see B", + "level": 5, + "school": "Trans", + "time": "1 a", + "range": "300 ft", + "components": "V,S", + "duration": "Conc, 1 h", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "create bonfire": { "name": "Create Bonfire", @@ -547,7 +1064,21 @@ "page": 16 } ], - "description": "5-ft cube all crea now/enter/end turn save or 1d8 Fire dmg; ignites flammable; +1d8 at CL 5/11/17" + "description": "5-ft cube all crea now/enter/end turn save or 1d8 Fire dmg; ignites flammable; +1d8 at CL 5/11/17", + "level": 0, + "school": "Conj", + "time": "1 a", + "range": "60 ft", + "components": "V,S", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "artificer", + "druid", + "sorcerer", + "warlock", + "wizard" + ] }, "dust devil": { "name": "Dust Devil", @@ -561,7 +1092,19 @@ "page": 17 } ], - "description": "5-ft cube; all in 5-ft 1d8+1d8/SL Bludg. dmg and pushed 10 ft away; save halves, no push; see book" + "description": "5-ft cube; all in 5-ft 1d8+1d8/SL Bludg. dmg and pushed 10 ft away; save halves, no push; see book", + "level": 2, + "school": "Conj", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Str", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "earthbind": { "name": "Earthbind", @@ -575,7 +1118,20 @@ "page": 17 } ], - "description": "1 creatures save or fly speed is reduced to 0; airborne creatures safely descend at 60 ft per round" + "description": "1 creatures save or fly speed is reduced to 0; airborne creatures safely descend at 60 ft per round", + "level": 2, + "school": "Trans", + "time": "1 a", + "range": "300 ft", + "components": "V", + "duration": "Conc, 1 min", + "save": "Str", + "classes": [ + "druid", + "sorcerer", + "warlock", + "wizard" + ] }, "earth tremor": { "name": "Earth Tremor", @@ -589,7 +1145,20 @@ "page": 17 } ], - "description": "All crea in range except me save or 1d6+1d6/SL Bludgeoning dmg and prone; loose ground is dif. ter." + "description": "All crea in range except me save or 1d6+1d6/SL Bludgeoning dmg and prone; loose ground is dif. ter.", + "level": 1, + "school": "Evoc", + "time": "1 a", + "range": "10 ft", + "components": "V,S", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "bard", + "druid", + "sorcerer", + "wizard" + ] }, "elemental bane": { "name": "Elemental Bane", @@ -603,7 +1172,20 @@ "page": 17 } ], - "description": "1+1/SL crea, each max 30 ft apart, save or 1 energy: lose resist. to it \\u0026 +2d6 to first dmg with it/turn" + "description": "1+1/SL crea, each max 30 ft apart, save or 1 energy: lose resist. to it \\u0026 +2d6 to first dmg with it/turn", + "level": 4, + "school": "Trans", + "time": "1 a", + "range": "90 ft", + "components": "V,S", + "duration": "Conc, 1 min", + "save": "Con", + "classes": [ + "artificer", + "druid", + "warlock", + "wizard" + ] }, "erupting earth": { "name": "Erupting Earth", @@ -617,7 +1199,19 @@ "page": 17 } ], - "description": "20-ft cube all crea 3d12+1d12/SL Bludgeoning dmg; save halves; area becomes difficult terrain" + "description": "20-ft cube all crea 3d12+1d12/SL Bludgeoning dmg; save halves; area becomes difficult terrain", + "level": 3, + "school": "Trans", + "time": "1 a", + "range": "120 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "flame arrows": { "name": "Flame Arrows", @@ -631,7 +1225,20 @@ "page": 18 } ], - "description": "12+2/SL ammunition drawn from touched quiver do +1d6 Fire damage on a successful hit" + "description": "12+2/SL ammunition drawn from touched quiver do +1d6 Fire damage on a successful hit", + "level": 3, + "school": "Trans", + "time": "1 a", + "range": "Touch", + "components": "V,S", + "duration": "Conc, 1 h", + "classes": [ + "artificer", + "druid", + "ranger", + "sorcerer", + "wizard" + ] }, "frostbite": { "name": "Frostbite", @@ -645,7 +1252,21 @@ "page": 18 } ], - "description": "1 crea save or 1d6 Cold dmg and dis. on next weapon attack roll; +1d6 at CL 5, 11, and 17" + "description": "1 crea save or 1d6 Cold dmg and dis. on next weapon attack roll; +1d6 at CL 5, 11, and 17", + "level": 0, + "school": "Evoc", + "time": "1 a", + "range": "60 ft", + "components": "V,S", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "artificer", + "druid", + "sorcerer", + "warlock", + "wizard" + ] }, "gust": { "name": "Gust", @@ -671,7 +1292,19 @@ "page": 107 } ], - "description": "Med. or smaller crea save or push 5 ft; or push unattended 5 lb obj 10 ft; or harmless sensory effect" + "description": "Med. or smaller crea save or push 5 ft; or push unattended 5 lb obj 10 ft; or harmless sensory effect", + "level": 0, + "school": "Trans", + "time": "1 a", + "range": "30 ft", + "components": "V,S", + "duration": "Instantaneous", + "save": "Str", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "ice knife": { "name": "Ice Knife", @@ -685,7 +1318,19 @@ "page": 19 } ], - "description": "Ranged atk for 1d10 Piercing dmg; hit/miss 5-ft rad on target all crea save or 2d6+1d6/SL Cold dmg" + "description": "Ranged atk for 1d10 Piercing dmg; hit/miss 5-ft rad on target all crea save or 2d6+1d6/SL Cold dmg", + "level": 1, + "school": "Conj", + "time": "1 a", + "range": "60 ft", + "components": "S,M", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "immolation": { "name": "Immolation", @@ -699,7 +1344,18 @@ "page": 19 } ], - "description": "1 crea save or 8d6 Fire dmg \\u0026 burns for 4d6 Fire dmg/rnd; save each rnd to end; save half, no burning" + "description": "1 crea save or 8d6 Fire dmg \\u0026 burns for 4d6 Fire dmg/rnd; save each rnd to end; save half, no burning", + "level": 5, + "school": "Evoc", + "time": "1 a", + "range": "90 ft", + "components": "V", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "sorcerer", + "wizard" + ] }, "investiture of flame": { "name": "Investiture of Flame", @@ -713,7 +1369,20 @@ "page": 19 } ], - "description": "Fire immune; Cold res.; 1d10 Fire dmg in 5 ft; 1 a 15-ft long 5-ft wide all crea 4d8 Fire dmg, save half" + "description": "Fire immune; Cold res.; 1d10 Fire dmg in 5 ft; 1 a 15-ft long 5-ft wide all crea 4d8 Fire dmg, save half", + "level": 6, + "school": "Trans", + "time": "1 a", + "range": "Self", + "components": "V,S", + "duration": "Conc, 10 min", + "save": "Dex", + "classes": [ + "druid", + "sorcerer", + "warlock", + "wizard" + ] }, "investiture of ice": { "name": "Investiture of Ice", @@ -727,7 +1396,20 @@ "page": 19 } ], - "description": "Cold im.; Fire res.; 10-ft rad dif. ter.; 1 a 15-ft cone all crea 4d6 Cold dmg, half spd; save half, no spd" + "description": "Cold im.; Fire res.; 10-ft rad dif. ter.; 1 a 15-ft cone all crea 4d6 Cold dmg, half spd; save half, no spd", + "level": 6, + "school": "Trans", + "time": "1 a", + "range": "Self", + "components": "V,S", + "duration": "Conc, 10 min", + "save": "Con", + "classes": [ + "druid", + "sorcerer", + "warlock", + "wizard" + ] }, "investiture of stone": { "name": "Investiture of Stone", @@ -741,7 +1423,20 @@ "page": 19 } ], - "description": "Nonmagical Bludg/Pierc/Slash resist.; 1 a 15-ft rad all crea save or prone; move through earth/stone" + "description": "Nonmagical Bludg/Pierc/Slash resist.; 1 a 15-ft rad all crea save or prone; move through earth/stone", + "level": 6, + "school": "Trans", + "time": "1 a", + "range": "Self", + "components": "V,S", + "duration": "Conc, 10 min", + "save": "Dex", + "classes": [ + "druid", + "sorcerer", + "warlock", + "wizard" + ] }, "investiture of wind": { "name": "Investiture of Wind", @@ -755,7 +1450,20 @@ "page": 20 } ], - "description": "Rngd wea atks dis. vs. me; fly 60 ft; 1 a 15-ft cube in 60 ft all 2d10 Bludg. dmg, push 10 ft, save half" + "description": "Rngd wea atks dis. vs. me; fly 60 ft; 1 a 15-ft cube in 60 ft all 2d10 Bludg. dmg, push 10 ft, save half", + "level": 6, + "school": "Trans", + "time": "1 a", + "range": "Self", + "components": "V,S", + "duration": "Conc, 10 min", + "save": "Con", + "classes": [ + "druid", + "sorcerer", + "warlock", + "wizard" + ] }, "maelstrom": { "name": "Maelstrom", @@ -769,7 +1477,17 @@ "page": 20 } ], - "description": "5-ft deep 30-ft rad dif. ter.; all crea starting turn in save or 6d6 Bludg. dmg and pulled 10 ft to center" + "description": "5-ft deep 30-ft rad dif. ter.; all crea starting turn in save or 6d6 Bludg. dmg and pulled 10 ft to center", + "level": 5, + "school": "Evoc", + "time": "1 a", + "range": "120 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Str", + "classes": [ + "druid" + ] }, "magic stone": { "name": "Magic Stone", @@ -783,7 +1501,18 @@ "page": 20 } ], - "description": "Imbue 3 pebbles for spell attacks, thrown 60 ft or with sling, do 1d6+spellcasting mod Bludg. dmg" + "description": "Imbue 3 pebbles for spell attacks, thrown 60 ft or with sling, do 1d6+spellcasting mod Bludg. dmg", + "level": 0, + "school": "Trans", + "time": "1 bns", + "range": "Touch", + "components": "V,S", + "duration": "1 min", + "classes": [ + "artificer", + "druid", + "warlock" + ] }, "maximilian's earthen grasp": { "name": "Maximilian", @@ -797,7 +1526,18 @@ "page": 20 } ], - "description": "Medium hand atks 1 crea: save or 2d6 Bludg. dmg \\u0026 restrained; 1 a hand moves/atks, releases; see B" + "description": "Medium hand atks 1 crea: save or 2d6 Bludg. dmg \\u0026 restrained; 1 a hand moves/atks, releases; see B", + "level": 2, + "school": "Trans", + "time": "1 a", + "range": "30 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Str", + "classes": [ + "sorcerer", + "wizard" + ] }, "melf's minute meteors": { "name": "Melf", @@ -811,7 +1551,18 @@ "page": 20 } ], - "description": "6+2/SL meteors; at casting/bns a send up to two 120 ft for 5-ft rad all crea 2d6 Fire dmg; save half" + "description": "6+2/SL meteors; at casting/bns a send up to two 120 ft for 5-ft rad all crea 2d6 Fire dmg; save half", + "level": 3, + "school": "Evoc", + "time": "1 a", + "range": "Self", + "components": "V,S,M", + "duration": "Conc, 10 min", + "save": "Dex", + "classes": [ + "sorcerer", + "wizard" + ] }, "mold earth": { "name": "Mold Earth", @@ -825,7 +1576,18 @@ "page": 21 } ], - "description": "5 cu ft earth; instant.: excavate; 1h: change to difficult or normal terrain, or change shape and color" + "description": "5 cu ft earth; instant.: excavate; 1h: change to difficult or normal terrain, or change shape and color", + "level": 0, + "school": "Trans", + "time": "1 a", + "range": "30 ft", + "components": "S", + "duration": "Instant. or 1 h", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "primordial ward": { "name": "Primordial Ward", @@ -839,7 +1601,16 @@ "page": 21 } ], - "description": "Acid, Cold, Fire, Lightning, and Thunder resistance; use rea to gain 1 immunity for 1 rnd, spell ends" + "description": "Acid, Cold, Fire, Lightning, and Thunder resistance; use rea to gain 1 immunity for 1 rnd, spell ends", + "level": 6, + "school": "Abjur", + "time": "1 a", + "range": "Self", + "components": "V,S", + "duration": "Conc, 1 min", + "classes": [ + "druid" + ] }, "pyrotechnics": { "name": "Pyrotechnics", @@ -853,7 +1624,20 @@ "page": 21 } ], - "description": "5 cu ft nonma. flame extinguish, or 10-ft rad all crea save or blind 1 rnd, or 20-ft rad hvy obsc. 1 min" + "description": "5 cu ft nonma. flame extinguish, or 10-ft rad all crea save or blind 1 rnd, or 20-ft rad hvy obsc. 1 min", + "level": 2, + "school": "Trans", + "time": "1 a", + "range": "60 ft", + "components": "V,S", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "artificer", + "bard", + "sorcerer", + "wizard" + ] }, "shape water": { "name": "Shape Water", @@ -871,7 +1655,18 @@ "page": 172 } ], - "description": "5 cu ft water; instant: move/change flow; 1h: simple shapes/change color or opacity/freeze" + "description": "5 cu ft water; instant: move/change flow; 1h: simple shapes/change color or opacity/freeze", + "level": 0, + "school": "Trans", + "time": "1 a", + "range": "30 ft", + "components": "S", + "duration": "Instant. or 1 h", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "skywrite": { "name": "Skywrite", @@ -885,7 +1680,20 @@ "page": 22 } ], - "description": "Write up to 10 words with clouds in a part of the sky I can see; strong wind can diperse the clouds" + "description": "Write up to 10 words with clouds in a part of the sky I can see; strong wind can diperse the clouds", + "level": 2, + "school": "Trans", + "time": "1 a", + "range": "Sight", + "components": "V,S", + "duration": "Conc, 1 h", + "ritual": true, + "classes": [ + "artificer", + "bard", + "druid", + "wizard" + ] }, "snilloc's snowball swarm": { "name": "Snilloc", @@ -899,7 +1707,18 @@ "page": 22 } ], - "description": "5-ft radius all creatures 3d6+1d6/SL Cold damage; save halves" + "description": "5-ft radius all creatures 3d6+1d6/SL Cold damage; save halves", + "level": 2, + "school": "Evoc", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "sorcerer", + "wizard" + ] }, "storm sphere": { "name": "Storm Sphere", @@ -913,7 +1732,18 @@ "page": 22 } ], - "description": "20-ft rad dif. ter., all now/end turn save or 2d6 Bludg. dmg; bns a 60 ft atk 4d6 Lightn. dmg; +1d6/SL" + "description": "20-ft rad dif. ter., all now/end turn save or 2d6 Bludg. dmg; bns a 60 ft atk 4d6 Lightn. dmg; +1d6/SL", + "level": 4, + "school": "Evoc", + "time": "1 a", + "range": "150 ft", + "components": "V,S", + "duration": "Conc, 1 min", + "save": "Str", + "classes": [ + "sorcerer", + "wizard" + ] }, "thunderclap": { "name": "Thunderclap", @@ -927,7 +1757,22 @@ "page": 22 } ], - "description": "100-ft rad audible; all crea but me in area save or 1d6 Thunder dmg; +1d6 at CL 5, 11, and 17" + "description": "100-ft rad audible; all crea but me in area save or 1d6 Thunder dmg; +1d6 at CL 5, 11, and 17", + "level": 0, + "school": "Evoc", + "time": "1 a", + "range": "5 ft", + "components": "S", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "artificer", + "bard", + "druid", + "sorcerer", + "warlock", + "wizard" + ] }, "tidal wave": { "name": "Tidal Wave", @@ -941,7 +1786,19 @@ "page": 22 } ], - "description": "30-ft x 10-ft, 10-ft high all crea 4d8 Bludg. dmg and prone; save halves not prone; extinguish flames" + "description": "30-ft x 10-ft, 10-ft high all crea 4d8 Bludg. dmg and prone; save halves not prone; extinguish flames", + "level": 3, + "school": "Conj", + "time": "1 a", + "range": "120 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "transmute rock": { "name": "Transmute Rock", @@ -955,7 +1812,18 @@ "page": 22 } ], - "description": "40 cu ft stone to mud or mud to stone; mud and stone restrains; mud from ceiling falls; see book" + "description": "40 cu ft stone to mud or mud to stone; mud and stone restrains; mud from ceiling falls; see book", + "level": 5, + "school": "Trans", + "time": "1 a", + "range": "120 ft", + "components": "V,S,M", + "duration": "Until dispelled", + "classes": [ + "artificer", + "druid", + "wizard" + ] }, "vitriolic sphere": { "name": "Vitriolic Sphere", @@ -969,7 +1837,18 @@ "page": 23 } ], - "description": "20-ft rad all crea 10d4+2d4/SL Acid dmg, +5d4 dmg next turn end; save half \\u0026 no dmg next turn" + "description": "20-ft rad all crea 10d4+2d4/SL Acid dmg, +5d4 dmg next turn end; save half \\u0026 no dmg next turn", + "level": 4, + "school": "Evoc", + "time": "1 a", + "range": "150 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "sorcerer", + "wizard" + ] }, "wall of sand": { "name": "Wall of Sand", @@ -983,7 +1862,16 @@ "page": 23 } ], - "description": "30\\xD710\\xD710ft (l\\xD7w\\xD7h) wall on the ground; blocks line of sight; blinded while inside; 1/3 move" + "description": "30\\xD710\\xD710ft (l\\xD7w\\xD7h) wall on the ground; blocks line of sight; blinded while inside; 1/3 move", + "level": 3, + "school": "Evoc", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M", + "duration": "Conc, 10 min", + "classes": [ + "wizard" + ] }, "wall of water": { "name": "Wall of Water", @@ -1005,7 +1893,18 @@ "page": 27 } ], - "description": "30\\xD71\\xD710ft (l\\xD7w\\xD7h) or 20-ft rad 20-ft high; dif. ter.; range wea dis.; Fire dmg half; Cold dmg freezes" + "description": "30\\xD71\\xD710ft (l\\xD7w\\xD7h) or 20-ft rad 20-ft high; dif. ter.; range wea dis.; Fire dmg half; Cold dmg freezes", + "level": 3, + "school": "Evoc", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M", + "duration": "Conc, 10 min", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "warding wind": { "name": "Warding Wind", @@ -1019,7 +1918,19 @@ "page": 23 } ], - "description": "Strong (20 mph) wind around me deafens/extinguishes unprotected flames/dif. ter./ranged wea dis." + "description": "Strong (20 mph) wind around me deafens/extinguishes unprotected flames/dif. ter./ranged wea dis.", + "level": 2, + "school": "Evoc", + "time": "1 a", + "range": "S:10-ft rad", + "components": "V", + "duration": "Conc, 10 min", + "classes": [ + "bard", + "druid", + "sorcerer", + "wizard" + ] }, "watery sphere": { "name": "Watery Sphere", @@ -1033,7 +1944,19 @@ "page": 23 } ], - "description": "5-ft rad all crea < Huge save or restrained; on save ejected; save each rnd; 1 a move sphere 30 ft" + "description": "5-ft rad all crea < Huge save or restrained; on save ejected; save each rnd; 1 a move sphere 30 ft", + "level": 4, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Str", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "whirlwind": { "name": "Whirlwind", @@ -1047,7 +1970,19 @@ "page": 24 } ], - "description": "10-ft rad 30-ft high all crea 10d6 Bludg. dmg; save halves; restrains; 1 a move 30 ft; see book" + "description": "10-ft rad 30-ft high all crea 10d6 Bludg. dmg; save halves; restrains; 1 a move 30 ft; see book", + "level": 7, + "school": "Evoc", + "time": "1 a", + "range": "300 ft", + "components": "V,M", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "booming blade": { "name": "Booming Blade", @@ -1061,7 +1996,19 @@ "page": 142 } ], - "description": "Melee wea atk with cast; hit: 0d8 Thunder dmg, if it moves next round +1d8; +1d8 at CL5, 11, \\u0026 17" + "description": "Melee wea atk with cast; hit: 0d8 Thunder dmg, if it moves next round +1d8; +1d8 at CL5, 11, \\u0026 17", + "level": 0, + "school": "Evoc", + "time": "1 a", + "range": "S:5-ft rad", + "components": "S,M\\u0192", + "duration": "1 round", + "classes": [ + "artificer", + "sorcerer", + "warlock", + "wizard" + ] }, "green-flame blade": { "name": "Green-Flame Blade", @@ -1075,7 +2022,19 @@ "page": 143 } ], - "description": "Melee wea atk with cast; hit: 0d8 Fire dmg, 1 crea in 5 ft 0d8+spell mod Fire dmg; +1d8 CL5/11/17" + "description": "Melee wea atk with cast; hit: 0d8 Fire dmg, 1 crea in 5 ft 0d8+spell mod Fire dmg; +1d8 CL5/11/17", + "level": 0, + "school": "Evoc", + "time": "1 a", + "range": "S:5-ft rad", + "components": "S,M\\u0192", + "duration": "Instantaneous", + "classes": [ + "artificer", + "sorcerer", + "warlock", + "wizard" + ] }, "lightning lure": { "name": "Lightning Lure", @@ -1089,7 +2048,20 @@ "page": 143 } ], - "description": "1 crea in 15 ft save or pulled 10 ft to me; if it ends in 5 ft, 1d8 Lightning dmg; +1d8 at CL 5, 11, \\u0026 17" + "description": "1 crea in 15 ft save or pulled 10 ft to me; if it ends in 5 ft, 1d8 Lightning dmg; +1d8 at CL 5, 11, \\u0026 17", + "level": 0, + "school": "Evoc", + "time": "1 a", + "range": "S:15-ft rad", + "components": "V", + "duration": "Instantaneous", + "save": "Str", + "classes": [ + "artificer", + "sorcerer", + "warlock", + "wizard" + ] }, "sword burst": { "name": "Sword Burst", @@ -1103,7 +2075,20 @@ "page": 143 } ], - "description": "All crea in range save or 1d6 Force damage; +1d6 at CL 5, 11, and 17" + "description": "All crea in range save or 1d6 Force damage; +1d6 at CL 5, 11, and 17", + "level": 0, + "school": "Conj", + "time": "1 a", + "range": "S:5-ft rad", + "components": "V", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "artificer", + "sorcerer", + "warlock", + "wizard" + ] }, "catnap": { "name": "Catnap", @@ -1113,7 +2098,19 @@ "page": 151 } ], - "description": "3+1/SL willing crea unconscious for 10 min to gain benefits of short rest; Ends if dmg or 1 a to wake" + "description": "3+1/SL willing crea unconscious for 10 min to gain benefits of short rest; Ends if dmg or 1 a to wake", + "level": 3, + "school": "Ench", + "time": "1 a", + "range": "30 ft", + "components": "S,M", + "duration": "10 min", + "classes": [ + "artificer", + "bard", + "sorcerer", + "wizard" + ] }, "cause fear": { "name": "Cause Fear", @@ -1123,7 +2120,18 @@ "page": 151 } ], - "description": "1+1/SL crea (not construct/undead), each max 30 ft apart, save or frightened; save end of each turn" + "description": "1+1/SL crea (not construct/undead), each max 30 ft apart, save or frightened; save end of each turn", + "level": 1, + "school": "Necro", + "time": "1 a", + "range": "60 ft", + "components": "V", + "duration": "Conc, 1 min", + "save": "Wis", + "classes": [ + "warlock", + "wizard" + ] }, "ceremony": { "name": "Ceremony", @@ -1133,7 +2141,18 @@ "page": 151 } ], - "description": "Perform religious ceremony on target(s) within 10 ft throughout the casting; see book (25gp cons.)" + "description": "Perform religious ceremony on target(s) within 10 ft throughout the casting; see book (25gp cons.)", + "level": 1, + "school": "Abjur", + "time": "1 h", + "range": "Touch", + "components": "V,S,M\\u2020", + "duration": "Instantaneous", + "ritual": true, + "classes": [ + "cleric", + "paladin" + ] }, "chaos bolt": { "name": "Chaos Bolt", @@ -1147,7 +2166,16 @@ "page": 67 } ], - "description": "Spell atk 2d8+1d6+1d6/SL dmg, d8s set dmg type, see B; double on d8s: new atk vs. crea in 30 ft" + "description": "Spell atk 2d8+1d6+1d6/SL dmg, d8s set dmg type, see B; double on d8s: new atk vs. crea in 30 ft", + "level": 1, + "school": "Evoc", + "time": "1 a", + "range": "120 ft", + "components": "V,S", + "duration": "Instantaneous", + "classes": [ + "sorcerer" + ] }, "charm monster": { "name": "Charm Monster", @@ -1157,7 +2185,21 @@ "page": 151 } ], - "description": "1+1/SL creatures, each max 30 ft apart, save or charmed; adv. on save if me/ally is fighting it" + "description": "1+1/SL creatures, each max 30 ft apart, save or charmed; adv. on save if me/ally is fighting it", + "level": 4, + "school": "Ench", + "time": "1 a", + "range": "30 ft", + "components": "V,S", + "duration": "1 h", + "save": "Wis", + "classes": [ + "bard", + "druid", + "sorcerer", + "warlock", + "wizard" + ] }, "create homunculus": { "name": "Create Homunculus", @@ -1167,7 +2209,16 @@ "page": 152 } ], - "description": "I take 2d4 piercing dmg to create a homunculus as my faithful companion; see book (1000gp)" + "description": "I take 2d4 piercing dmg to create a homunculus as my faithful companion; see book (1000gp)", + "level": 6, + "school": "Trans", + "time": "1 h", + "range": "Touch", + "components": "V,S,M\\u0192", + "duration": "Instantaneous", + "classes": [ + "wizard" + ] }, "crown of stars": { "name": "Crown of Stars", @@ -1177,7 +2228,18 @@ "page": 152 } ], - "description": "7+2/SL motes shed 30-ft light; bonus action to fire one as 120 ft ranged atk for 4d12 Radiant dmg" + "description": "7+2/SL motes shed 30-ft light; bonus action to fire one as 120 ft ranged atk for 4d12 Radiant dmg", + "level": 7, + "school": "Evoc", + "time": "1 a", + "range": "Self", + "components": "V,S", + "duration": "1 h", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "danse macabre": { "name": "Danse Macabre", @@ -1187,7 +2249,17 @@ "page": 153 } ], - "description": "5+2/SL small/medium corpses as zombie/skeleton; spellc. mod to atk/dmg; bns a command in 60 ft" + "description": "5+2/SL small/medium corpses as zombie/skeleton; spellc. mod to atk/dmg; bns a command in 60 ft", + "level": 5, + "school": "Necro", + "time": "1 a", + "range": "60 ft", + "components": "V,S", + "duration": "Conc, 1 h", + "classes": [ + "warlock", + "wizard" + ] }, "dawn": { "name": "Dawn", @@ -1197,7 +2269,18 @@ "page": 153 } ], - "description": "30-ft rad 40-ft high all crea 4d10 Radiant dmg at cast/end turn; bns a move it 60 ft (100gp)" + "description": "30-ft rad 40-ft high all crea 4d10 Radiant dmg at cast/end turn; bns a move it 60 ft (100gp)", + "level": 5, + "school": "Evoc", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 min", + "save": "Con", + "classes": [ + "cleric", + "wizard" + ] }, "dragon's breath": { "name": "Dragon", @@ -1207,7 +2290,18 @@ "page": 154 } ], - "description": "1 willing crea: 1 a breathe 15-ft cone all 3d6+1d6/SL Acid/Cold/Fire/Lightn./Poison dmg; save half" + "description": "1 willing crea: 1 a breathe 15-ft cone all 3d6+1d6/SL Acid/Cold/Fire/Lightn./Poison dmg; save half", + "level": 2, + "school": "Trans", + "time": "1 bns", + "range": "Touch", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "sorcerer", + "wizard" + ] }, "druid grove": { "name": "Druid Grove", @@ -1217,7 +2311,16 @@ "page": 154 } ], - "description": "Protect 30-ft to 90-ft cube outdoors or underground; see book for effects" + "description": "Protect 30-ft to 90-ft cube outdoors or underground; see book for effects", + "level": 6, + "school": "Abjur", + "time": "10 min", + "range": "Touch", + "components": "V,S,M\\u2020", + "duration": "24 h", + "classes": [ + "druid" + ] }, "enemies abound": { "name": "Enemies Abound", @@ -1227,7 +2330,20 @@ "page": 155 } ], - "description": "1 crea save or regard all creatures it can see as enemies, random targeting; save when damaged to end" + "description": "1 crea save or regard all creatures it can see as enemies, random targeting; save when damaged to end", + "level": 3, + "school": "Ench", + "time": "1 a", + "range": "120 ft", + "components": "V,S", + "duration": "Conc, 1 min", + "save": "Int", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "enervation": { "name": "Enervation", @@ -1237,7 +2353,19 @@ "page": 155 } ], - "description": "1 crea 2d8+1d8/SL Necrotic dmg, saved: ends; fail: +2d8 dmg and Act to repeat; I heal half; see B" + "description": "1 crea 2d8+1d8/SL Necrotic dmg, saved: ends; fail: +2d8 dmg and Act to repeat; I heal half; see B", + "level": 5, + "school": "Necro", + "time": "1 a", + "range": "60 ft", + "components": "V,S", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "far step": { "name": "Far Step", @@ -1247,7 +2375,18 @@ "page": 155 } ], - "description": "At casting and as bonus action for duration, I can teleport 60 ft to a space I can see" + "description": "At casting and as bonus action for duration, I can teleport 60 ft to a space I can see", + "level": 5, + "school": "Conj", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "find greater steed": { "name": "Find Greater Steed", @@ -1257,7 +2396,16 @@ "page": 156 } ], - "description": "Gain the services of a steed; can communicate with it telepathically; can share spells with it; see book" + "description": "Gain the services of a steed; can communicate with it telepathically; can share spells with it; see book", + "level": 4, + "school": "Conj", + "time": "10 min", + "range": "30 ft", + "components": "V,S", + "duration": "Instantaneous", + "classes": [ + "paladin" + ] }, "guardian of nature": { "name": "Guardian of Nature", @@ -1267,7 +2415,17 @@ "page": 157 } ], - "description": "I transform into a Primal Beast (offensive bonuses) or a Great Tree (defensive bonuses); see book" + "description": "I transform into a Primal Beast (offensive bonuses) or a Great Tree (defensive bonuses); see book", + "level": 4, + "school": "Trans", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "classes": [ + "druid", + "ranger" + ] }, "healing spirit": { "name": "Healing Spirit", @@ -1277,7 +2435,17 @@ "page": 157 } ], - "description": "5-ft cube; any living crea I see start/enter heals 1d6+1d6/SL HP; 1+spell mod uses; bns a move it 30 ft" + "description": "5-ft cube; any living crea I see start/enter heals 1d6+1d6/SL HP; 1+spell mod uses; bns a move it 30 ft", + "level": 2, + "school": "Conj", + "time": "1 bns", + "range": "60 ft", + "components": "V,S", + "duration": "Conc, 1 min", + "classes": [ + "druid", + "ranger" + ] }, "holy weapon": { "name": "Holy Weapon", @@ -1287,7 +2455,18 @@ "page": 157 } ], - "description": "Wea +2d8 Radiant dmg; bns a end spell: 30-ft rad all crea 4d8 Radiant dmg, blind; save half, no blind" + "description": "Wea +2d8 Radiant dmg; bns a end spell: 30-ft rad all crea 4d8 Radiant dmg, blind; save half, no blind", + "level": 5, + "school": "Evoc", + "time": "1 bns", + "range": "Touch", + "components": "V,S", + "duration": "Conc, 1 h", + "save": "Con", + "classes": [ + "cleric", + "paladin" + ] }, "illusory dragon": { "name": "Illusory Dragon", @@ -1297,7 +2476,17 @@ "page": 157 } ], - "description": "Huge shadowy dragon; see: Wis save or fright.; bns a move 60 ft \\u0026 breath wea 7d6 dmg; Int save half" + "description": "Huge shadowy dragon; see: Wis save or fright.; bns a move 60 ft \\u0026 breath wea 7d6 dmg; Int save half", + "level": 8, + "school": "Illus", + "time": "1 a", + "range": "120 ft", + "components": "S", + "duration": "Conc, 1 min", + "save": "W/I", + "classes": [ + "wizard" + ] }, "infernal calling": { "name": "Infernal Calling", @@ -1307,7 +2496,17 @@ "page": 158 } ], - "description": "Summon 1 devil of CR 6+1/SL; hostile to all, obeys my command if to its liking or Cha check; see B" + "description": "Summon 1 devil of CR 6+1/SL; hostile to all, obeys my command if to its liking or Cha check; see B", + "level": 5, + "school": "Conj", + "time": "1 min", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "warlock", + "wizard" + ] }, "infestation": { "name": "Infestation", @@ -1317,7 +2516,20 @@ "page": 158 } ], - "description": "1 crea save or 1d6 Poison dmg and moved 5 ft in random direction; +1d6 at CL 5, 11, and 17" + "description": "1 crea save or 1d6 Poison dmg and moved 5 ft in random direction; +1d6 at CL 5, 11, and 17", + "level": 0, + "school": "Conj", + "time": "1 a", + "range": "30 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "druid", + "sorcerer", + "warlock", + "wizard" + ] }, "invulnerability": { "name": "Invulnerability", @@ -1327,7 +2539,16 @@ "page": 160 } ], - "description": "Immune to all damage until the spell ends (500gp cons.)" + "description": "Immune to all damage until the spell ends (500gp cons.)", + "level": 9, + "school": "Abjur", + "time": "1 a", + "range": "Self", + "components": "V,S,M\\u2020", + "duration": "Conc, 10 min", + "classes": [ + "wizard" + ] }, "life transference": { "name": "Life Transference", @@ -1337,7 +2558,17 @@ "page": 160 } ], - "description": "I take 4d8+1d8/SL Necrotic dmg (in full) and 1 crea in range I can see heals twice that in HP" + "description": "I take 4d8+1d8/SL Necrotic dmg (in full) and 1 crea in range I can see heals twice that in HP", + "level": 3, + "school": "Necro", + "time": "1 a", + "range": "30 ft", + "components": "V,S", + "duration": "Instantaneous", + "classes": [ + "cleric", + "wizard" + ] }, "maddening darkness": { "name": "Maddening Darkness", @@ -1347,7 +2578,18 @@ "page": 160 } ], - "description": "60-ft rad darkness; darkvision, no light works; all crea starting turn in 8d8 Psychic dmg, save halves" + "description": "60-ft rad darkness; darkvision, no light works; all crea starting turn in 8d8 Psychic dmg, save halves", + "level": 8, + "school": "Evoc", + "time": "1 a", + "range": "150 ft", + "components": "V,M", + "duration": "Conc, 10 min", + "save": "Wis", + "classes": [ + "warlock", + "wizard" + ] }, "mass polymorph": { "name": "Mass Polymorph", @@ -1357,7 +2599,19 @@ "page": 160 } ], - "description": "10 crea save or take chosen beast form of CR \\u2264 its CR or half its char. level; can only act as beast; see B" + "description": "10 crea save or take chosen beast form of CR \\u2264 its CR or half its char. level; can only act as beast; see B", + "level": 9, + "school": "Trans", + "time": "1 a", + "range": "120 ft", + "components": "V,S,M", + "duration": "Conc, 1 h", + "save": "Wis", + "classes": [ + "bard", + "sorcerer", + "wizard" + ] }, "mental prison": { "name": "Mental Prison", @@ -1367,7 +2621,19 @@ "page": 161 } ], - "description": "1 crea 5d10 Psychic dmg; save or restrained, blind, deaf, and if moved: 10d10 dmg, ends; charm effect" + "description": "1 crea 5d10 Psychic dmg; save or restrained, blind, deaf, and if moved: 10d10 dmg, ends; charm effect", + "level": 6, + "school": "Illus", + "time": "1 a", + "range": "60 ft", + "components": "S", + "duration": "Conc, 1 min", + "save": "Int", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "mighty fortress": { "name": "Mighty Fortress", @@ -1377,7 +2643,16 @@ "page": 161 } ], - "description": "Create a stone fortress 120 ft on a side for 7 days; see book for effects (500gp cons.)" + "description": "Create a stone fortress 120 ft on a side for 7 days; see book for effects (500gp cons.)", + "level": 8, + "school": "Conj", + "time": "1 min", + "range": "1 mile", + "components": "V,S,M\\u2020", + "duration": "Instantaneous", + "classes": [ + "wizard" + ] }, "mind spike": { "name": "Mind Spike", @@ -1387,7 +2662,19 @@ "page": 162 } ], - "description": "1 crea 3d8+1d8/SL Psychic dmg, know its location, can't be invis for me; save half, no other benefits" + "description": "1 crea 3d8+1d8/SL Psychic dmg, know its location, can't be invis for me; save half, no other benefits", + "level": 2, + "school": "Div", + "time": "1 a", + "range": "60 ft", + "components": "S", + "duration": "Conc, 1 h", + "save": "Wis", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "negative energy flood": { "name": "Negative Energy Flood", @@ -1397,7 +2684,18 @@ "page": 163 } ], - "description": "1 crea: living 5d12 Necrotic dmg, save halves, rises as zombie if killed; undead 5d12/2 temp HP" + "description": "1 crea: living 5d12 Necrotic dmg, save halves, rises as zombie if killed; undead 5d12/2 temp HP", + "level": 5, + "school": "Necro", + "time": "1 a", + "range": "60 ft", + "components": "V,M", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "warlock", + "wizard" + ] }, "power word pain": { "name": "Power Word Pain", @@ -1407,7 +2705,18 @@ "page": 163 } ], - "description": "1 crea with 100 HP or less disadv. atk/check/save, conc. save to cast; save/rnd to end; charm effect" + "description": "1 crea with 100 HP or less disadv. atk/check/save, conc. save to cast; save/rnd to end; charm effect", + "level": 7, + "school": "Ench", + "time": "1 a", + "range": "60 ft", + "components": "V", + "duration": "Instantaneous", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "primal savagery": { "name": "Primal Savagery", @@ -1417,7 +2726,16 @@ "page": 163 } ], - "description": "Melee spell attack, 5 ft range, for 1d10 Acid dmg; +1d10 at CL 5, 11, and 17" + "description": "Melee spell attack, 5 ft range, for 1d10 Acid dmg; +1d10 at CL 5, 11, and 17", + "level": 0, + "school": "Trans", + "time": "1 a", + "range": "Self", + "components": "S", + "duration": "Instantaneous", + "classes": [ + "druid" + ] }, "psychic scream": { "name": "Psychic Scream", @@ -1427,7 +2745,20 @@ "page": 163 } ], - "description": "10 crea Int>2 save or 14d6 Psychic dmg and stunned; save halves, no stun; end of turn save to stop" + "description": "10 crea Int>2 save or 14d6 Psychic dmg and stunned; save halves, no stun; end of turn save to stop", + "level": 9, + "school": "Ench", + "time": "1 a", + "range": "90 ft", + "components": "S", + "duration": "Instantaneous", + "save": "Int", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "scatter": { "name": "Scatter", @@ -1437,7 +2768,19 @@ "page": 164 } ], - "description": "Up to 5 creatures in range, save or teleported 120 ft to a different space I can see on the ground" + "description": "Up to 5 creatures in range, save or teleported 120 ft to a different space I can see on the ground", + "level": 6, + "school": "Conj", + "time": "1 a", + "range": "30 ft", + "components": "V", + "duration": "Instantaneous", + "save": "Wis", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "shadow blade": { "name": "Shadow Blade", @@ -1447,7 +2790,18 @@ "page": 164 } ], - "description": "Sword 2d8 Psychic dmg, finesse, light, thrown (20/60 ft), adv. if target in dim/dark; +1d8 at SL3/5/7" + "description": "Sword 2d8 Psychic dmg, finesse, light, thrown (20/60 ft), adv. if target in dim/dark; +1d8 at SL3/5/7", + "level": 2, + "school": "Illus", + "time": "1 bns", + "range": "Self", + "components": "V,S", + "duration": "Conc, 1 min", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "shadow of moil": { "name": "Shadow of Moil", @@ -1457,7 +2811,16 @@ "page": 164 } ], - "description": "Me: heavy obsc., Radiant resistance; 10-ft rad: 1 step darker, hit vs. me get 2d8 Necrotic dmg (150gp)" + "description": "Me: heavy obsc., Radiant resistance; 10-ft rad: 1 step darker, hit vs. me get 2d8 Necrotic dmg (150gp)", + "level": 4, + "school": "Necro", + "time": "1 a", + "range": "Self", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 min", + "classes": [ + "warlock" + ] }, "sickening radiance": { "name": "Sickening Radiance", @@ -1467,7 +2830,19 @@ "page": 164 } ], - "description": "30-ft rad all enter/start turn save or 4d10 Radiant dmg, 1 level of exhaustion, and emit 5-ft rad light" + "description": "30-ft rad all enter/start turn save or 4d10 Radiant dmg, 1 level of exhaustion, and emit 5-ft rad light", + "level": 4, + "school": "Evoc", + "time": "1 a", + "range": "120 ft", + "components": "V,S", + "duration": "Conc, 10 min", + "save": "Con", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "skill empowerment": { "name": "Skill Empowerment", @@ -1477,7 +2852,19 @@ "page": 165 } ], - "description": "1 willing creature gains expertise in one skill of my choice that it is proficient with for the duration" + "description": "1 willing creature gains expertise in one skill of my choice that it is proficient with for the duration", + "level": 5, + "school": "Trans", + "time": "1 a", + "range": "Touch", + "components": "V,S", + "duration": "Conc, 1 h", + "classes": [ + "artificer", + "bard", + "sorcerer", + "wizard" + ] }, "snare": { "name": "Snare", @@ -1487,7 +2874,20 @@ "page": 165 } ], - "description": "5-ft rad trap; Investigation vs spell DC to see; save or restrained 3 ft in the air; save each rnd (5sp)" + "description": "5-ft rad trap; Investigation vs spell DC to see; save or restrained 3 ft in the air; save each rnd (5sp)", + "level": 1, + "school": "Abjur", + "time": "1 min", + "range": "Touch", + "components": "S,M\\u2020", + "duration": "8 h, till trigger", + "save": "Dex", + "classes": [ + "artificer", + "druid", + "ranger", + "wizard" + ] }, "soul cage": { "name": "Soul Cage", @@ -1497,7 +2897,17 @@ "page": 165 } ], - "description": "As a reaction when humanoid in range dies, I capture their soul in a tiny cage; see book (100gp)" + "description": "As a reaction when humanoid in range dies, I capture their soul in a tiny cage; see book (100gp)", + "level": 6, + "school": "Necro", + "time": "1 rea", + "range": "60 ft", + "components": "V,S,M\\u0192", + "duration": "8 h", + "classes": [ + "warlock", + "wizard" + ] }, "steel wind strike": { "name": "Steel Wind Strike", @@ -1507,7 +2917,17 @@ "page": 166 } ], - "description": "Melee spell attack vs. 5 crea in range; 6d10 Force dmg on hit; after, I teleport next to one target" + "description": "Melee spell attack vs. 5 crea in range; 6d10 Force dmg on hit; after, I teleport next to one target", + "level": 5, + "school": "Conj", + "time": "1 a", + "range": "30 ft", + "components": "S,M\\u0192", + "duration": "Instantaneous", + "classes": [ + "ranger", + "wizard" + ] }, "summon greater demon": { "name": "Summon Greater Demon", @@ -1517,7 +2937,18 @@ "page": 166 } ], - "description": "Summon 1 demon of CR 5+1/SL that obeys me; end of each of its turn, save to break free; see book" + "description": "Summon 1 demon of CR 5+1/SL that obeys me; end of each of its turn, save to break free; see book", + "level": 4, + "school": "Conj", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M", + "duration": "Conc, 1 h", + "save": "Cha", + "classes": [ + "warlock", + "wizard" + ] }, "summon lesser demons": { "name": "Summon Lesser Demons", @@ -1527,7 +2958,17 @@ "page": 167 } ], - "description": "Summon up to 8 (16 at SL6, 24 at SL8) CR \\u22641 1 demons, DM choice; attack nearest non-demons" + "description": "Summon up to 8 (16 at SL6, 24 at SL8) CR \\u22641 1 demons, DM choice; attack nearest non-demons", + "level": 3, + "school": "Conj", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M", + "duration": "Conc, 1 h", + "classes": [ + "warlock", + "wizard" + ] }, "synaptic static": { "name": "Synaptic Static", @@ -1537,7 +2978,20 @@ "page": 167 } ], - "description": "20-ft rad all crea Int>2 save or 8d6 Psychic dmg, -1d6 on atks/check/conc. save; save half, no -1d6" + "description": "20-ft rad all crea Int>2 save or 8d6 Psychic dmg, -1d6 on atks/check/conc. save; save half, no -1d6", + "level": 5, + "school": "Ench", + "time": "1 a", + "range": "120 ft", + "components": "V,S", + "duration": "Instant, 1 min", + "save": "Int", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "temple of the gods": { "name": "Temple of the Gods", @@ -1547,7 +3001,16 @@ "page": 167 } ], - "description": "Create a temple 120 ft on a side to the deity of a holy symbol used; see book for effects" + "description": "Create a temple 120 ft on a side to the deity of a holy symbol used; see book for effects", + "level": 7, + "school": "Conj", + "time": "1 h", + "range": "120 ft", + "components": "V,S,M\\u0192", + "duration": "24 h", + "classes": [ + "cleric" + ] }, "tenser's transformation": { "name": "Tenser", @@ -1557,7 +3020,16 @@ "page": 168 } ], - "description": "50 temp HP; prof Str/Con save, all wea/arm; extra atk; adv., wea atks +2d12 Force dmg; no spellc." + "description": "50 temp HP; prof Str/Con save, all wea/arm; extra atk; adv., wea atks +2d12 Force dmg; no spellc.", + "level": 6, + "school": "Trans", + "time": "1 a", + "range": "Self", + "components": "V,S,M", + "duration": "Conc, 10 min", + "classes": [ + "wizard" + ] }, "thunder step": { "name": "Thunder Step", @@ -1567,7 +3039,19 @@ "page": 168 } ], - "description": "Me + 1 willing crea teleport 90 ft; all crea in 10 ft of origin 3d10+1d10/SL Thunder dmg; save half" + "description": "Me + 1 willing crea teleport 90 ft; all crea in 10 ft of origin 3d10+1d10/SL Thunder dmg; save half", + "level": 3, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "tiny servant": { "name": "Tiny Servant", @@ -1577,7 +3061,17 @@ "page": 168 } ], - "description": "Animate 1+2/SL Tiny, nonmagical, unattended obj as tiny servants; bns a to command telepathically" + "description": "Animate 1+2/SL Tiny, nonmagical, unattended obj as tiny servants; bns a to command telepathically", + "level": 3, + "school": "Trans", + "time": "1 min", + "range": "Touch", + "components": "V,S", + "duration": "8 h", + "classes": [ + "artificer", + "wizard" + ] }, "toll the dead": { "name": "Toll the Dead", @@ -1591,7 +3085,19 @@ "page": 4 } ], - "description": "1 crea save or 1d12 Necrotic dmg (d8 instead of d12 if at full HP); +1d12/1d8 at CL 5, 11, \\u0026 17" + "description": "1 crea save or 1d12 Necrotic dmg (d8 instead of d12 if at full HP); +1d12/1d8 at CL 5, 11, \\u0026 17", + "level": 0, + "school": "Necro", + "time": "1 a", + "range": "60 ft", + "components": "V,S", + "duration": "Instantaneous", + "save": "Wis", + "classes": [ + "cleric", + "warlock", + "wizard" + ] }, "wall of light": { "name": "Wall of Light", @@ -1601,7 +3107,19 @@ "page": 170 } ], - "description": "60\\xD75\\xD710ft (l\\xD7w\\xD7h) 4d8+1d8/SL Radiant dmg \\u0026 blind; save half, not blind; 1 a rngd spell atk; see B" + "description": "60\\xD75\\xD710ft (l\\xD7w\\xD7h) 4d8+1d8/SL Radiant dmg \\u0026 blind; save half, not blind; 1 a rngd spell atk; see B", + "level": 5, + "school": "Evoc", + "time": "1 a", + "range": "120 ft", + "components": "V,S,M", + "duration": "Conc, 10 min", + "save": "Con", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "word of radiance": { "name": "Word of Radiance", @@ -1611,7 +3129,17 @@ "page": 171 } ], - "description": "Any crea within range save or 1d6 Radiant damage; +1d6 at CL 5, 11, and 17" + "description": "Any crea within range save or 1d6 Radiant damage; +1d6 at CL 5, 11, and 17", + "level": 0, + "school": "Evoc", + "time": "1 a", + "range": "5 ft", + "components": "V,M", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "cleric" + ] }, "wrath of nature": { "name": "Wrath of Nature", @@ -1621,7 +3149,17 @@ "page": 171 } ], - "description": "60-ft cu dif. ter.; rock: rngd atk 3d8 Bludg. dmg; tree: Dex or 4d6 Slash. dmg; root: Str or restr.; see B" + "description": "60-ft cu dif. ter.; rock: rngd atk 3d8 Bludg. dmg; tree: Dex or 4d6 Slash. dmg; root: Str or restr.; see B", + "level": 5, + "school": "Evoc", + "time": "1 a", + "range": "120 ft", + "components": "V,S", + "duration": "Conc, 1 min", + "classes": [ + "druid", + "ranger" + ] }, "zephyr strike": { "name": "Zephyr Strike", @@ -1631,7 +3169,16 @@ "page": 171 } ], - "description": "Moving doesn't provoke opportunity atks; once: adv. on wea atk, +1d8 Force dmg, +30 ft spd for turn" + "description": "Moving doesn't provoke opportunity atks; once: adv. on wea atk, +1d8 Force dmg, +30 ft spd for turn", + "level": 1, + "school": "Trans", + "time": "1 bns", + "range": "Self", + "components": "V", + "duration": "Conc, 1 min", + "classes": [ + "ranger" + ] }, "flock of familiars": { "name": "Flock of Familiars", @@ -1641,7 +3188,17 @@ "page": 57 } ], - "description": "Summon 3+1/SL familiars as Find Familiar; can see through their eyes and deliver touch spells; see B" + "description": "Summon 3+1/SL familiars as Find Familiar; can see through their eyes and deliver touch spells; see B", + "level": 2, + "school": "Conj", + "time": "1 min", + "range": "Touch", + "components": "V,S", + "duration": "Conc, 1 h", + "classes": [ + "warlock", + "wizard" + ] }, "galder's speedy courier": { "name": "Galder", @@ -1651,7 +3208,17 @@ "page": 57 } ], - "description": "Send 3\\xD73\\xD73 ft chest of items I put in it to named crea on same plane; SL8: other plane (25gp cons.)" + "description": "Send 3\\xD73\\xD73 ft chest of items I put in it to named crea on same plane; SL8: other plane (25gp cons.)", + "level": 4, + "school": "Conj", + "time": "1 a", + "range": "10 ft", + "components": "V,S,M\\u2020", + "duration": "10 min", + "classes": [ + "warlock", + "wizard" + ] }, "galder's tower": { "name": "Galder", @@ -1661,7 +3228,16 @@ "page": 57 } ], - "description": "Conjure round or square tower with 2+1/Sl stories, each 100 sq ft and 10 ft high; see book" + "description": "Conjure round or square tower with 2+1/Sl stories, each 100 sq ft and 10 ft high; see book", + "level": 3, + "school": "Conj", + "time": "10 min", + "range": "30 ft", + "components": "V,S,M", + "duration": "24 h", + "classes": [ + "wizard" + ] }, "encode thoughts": { "name": "Encode Thoughts", @@ -1671,7 +3247,14 @@ "page": 47 } ], - "description": "Make physical thought strand of memory or vice versa; works with detect thoughts \\u0026 modify memory" + "description": "Make physical thought strand of memory or vice versa; works with detect thoughts \\u0026 modify memory", + "level": 0, + "school": "Ench", + "time": "1 a", + "range": "Self", + "components": "S", + "duration": "Up to 8 h", + "classes": [] }, "distort value": { "name": "Distort Value", @@ -1681,7 +3264,19 @@ "page": 75 } ], - "description": "1 obj up to 1+1/SL cu ft doubles/halves in perceived value; Investigation vs. spell DC to see true value" + "description": "1 obj up to 1+1/SL cu ft doubles/halves in perceived value; Investigation vs. spell DC to see true value", + "level": 1, + "school": "Illus", + "time": "1 min", + "range": "Touch", + "components": "V", + "duration": "8 hours", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "fast friends": { "name": "Fast Friends", @@ -1691,7 +3286,19 @@ "page": 75 } ], - "description": "1+1/SL humanoid save or charmed and perform tasks I ask it to do; adv. save if me/ally is fighting it" + "description": "1+1/SL humanoid save or charmed and perform tasks I ask it to do; adv. save if me/ally is fighting it", + "level": 3, + "school": "Ench", + "time": "1 a", + "range": "30 ft", + "components": "V", + "duration": "Conc, 1 h", + "save": "Wis", + "classes": [ + "bard", + "cleric", + "wizard" + ] }, "gift of gab": { "name": "Gift of Gab", @@ -1701,7 +3308,17 @@ "page": 76 } ], - "description": "Cast when talking, any crea within 5 ft think what I said in the last 6 seconds was only to cast a spell" + "description": "Cast when talking, any crea within 5 ft think what I said in the last 6 seconds was only to cast a spell", + "level": 2, + "school": "Ench", + "time": "1 rea", + "range": "Self", + "components": "V,S,R\\u2020", + "duration": "Instantaneous", + "classes": [ + "bard", + "wizard" + ] }, "incite greed": { "name": "Incite Greed", @@ -1711,7 +3328,19 @@ "page": 76 } ], - "description": "Any crea that see me save or charmed, only move to me, if in 5 ft do nothing; save end of each turn" + "description": "Any crea that see me save or charmed, only move to me, if in 5 ft do nothing; save end of each turn", + "level": 3, + "school": "Ench", + "time": "1 a", + "range": "30 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 min", + "save": "Wis", + "classes": [ + "cleric", + "warlock", + "wizard" + ] }, "jim's glowing coin": { "name": "Jim", @@ -1721,7 +3350,17 @@ "page": 76 } ], - "description": "30-ft radius any creature I can see save or disadvantage on Perception and Initiative for duration" + "description": "30-ft radius any creature I can see save or disadvantage on Perception and Initiative for duration", + "level": 2, + "school": "Ench", + "time": "1 a", + "range": "60 ft", + "components": "V,M,R\\u2020", + "duration": "1 min", + "save": "Wis", + "classes": [ + "wizard" + ] }, "jim's magic missile": { "name": "Jim", @@ -1731,7 +3370,16 @@ "page": 76 } ], - "description": "3+1/SL darts, each spell atk for 2d4 Force dmg, 5d4 crit; any 1 to hit, all dmg me 1 (1+1/SL gp cons.)" + "description": "3+1/SL darts, each spell atk for 2d4 Force dmg, 5d4 crit; any 1 to hit, all dmg me 1 (1+1/SL gp cons.)", + "level": 1, + "school": "Evoc", + "time": "1 a", + "range": "120 ft", + "components": "V,S,R\\u2020", + "duration": "Instantaneous", + "classes": [ + "wizard" + ] }, "motivational speech": { "name": "Motivational Speech", @@ -1741,7 +3389,17 @@ "page": 77 } ], - "description": "5 crea that hear me 5+5/SL temp HP, adv. Wis saves, if hit adv. on next atk; stops when temp HP gone" + "description": "5 crea that hear me 5+5/SL temp HP, adv. Wis saves, if hit adv. on next atk; stops when temp HP gone", + "level": 3, + "school": "Ench", + "time": "1 min", + "range": "60 ft", + "components": "V", + "duration": "1 h", + "classes": [ + "bard", + "cleric" + ] }, "sapping sting": { "name": "Sapping Sting", @@ -1751,7 +3409,15 @@ "page": 189 } ], - "description": "1 creature that I can see save or 1d4 Necrotic dmg and fall prone; +1d4 at CL 5, 11, and 17" + "description": "1 creature that I can see save or 1d4 Necrotic dmg and fall prone; +1d4 at CL 5, 11, and 17", + "level": 0, + "school": "Necro", + "time": "1 a", + "range": "30 ft", + "components": "V,S", + "duration": "Instantaneous", + "save": "Con", + "classes": [] }, "gift of alacrity": { "name": "Gift of Alacrity", @@ -1761,7 +3427,14 @@ "page": 186 } ], - "description": "1 willing creature can add 1d8 to its initiative rolls for the duration" + "description": "1 willing creature can add 1d8 to its initiative rolls for the duration", + "level": 1, + "school": "Div", + "time": "1 min", + "range": "Touch", + "components": "V,S", + "duration": "8 h", + "classes": [] }, "magnify gravity": { "name": "Magnify Gravity", @@ -1771,7 +3444,15 @@ "page": 188 } ], - "description": "10-ft rad all crea 2d8+1d8/SL Force dmg, half spd; Save halves \\u0026 no spd reduce; Str check to move obj" + "description": "10-ft rad all crea 2d8+1d8/SL Force dmg, half spd; Save halves \\u0026 no spd reduce; Str check to move obj", + "level": 1, + "school": "Trans", + "time": "1 a", + "range": "60 ft", + "components": "V,S", + "duration": "1 rnd", + "save": "Con", + "classes": [] }, "fortune's favor": { "name": "Fortune", @@ -1781,7 +3462,14 @@ "page": 186 } ], - "description": "1+1/SL crea once roll extra d20 and select which to use for atk, check, save, or atk vs. it (100gp cons.)" + "description": "1+1/SL crea once roll extra d20 and select which to use for atk, check, save, or atk vs. it (100gp cons.)", + "level": 2, + "school": "Div", + "time": "1 min", + "range": "Touch", + "components": "V,S,M\\u2020", + "duration": "1 h", + "classes": [] }, "immovable object": { "name": "Immovable Object", @@ -1791,7 +3479,14 @@ "page": 187 } ], - "description": "1 obj <10 lb fixed in place; holds 4k lb; Str check move, except chosen/password; See B (25gp cons.)" + "description": "1 obj <10 lb fixed in place; holds 4k lb; Str check move, except chosen/password; See B (25gp cons.)", + "level": 2, + "school": "Trans", + "time": "1 a", + "range": "Touch", + "components": "V,S,M\\u2020", + "duration": "1 h", + "classes": [] }, "wristpocket": { "name": "Wristpocket", @@ -1801,7 +3496,15 @@ "page": 190 } ], - "description": "Store 1 held obj <5 lb in extradim. space; 1 a to summon obj in free hand or return; reappears at end" + "description": "Store 1 held obj <5 lb in extradim. space; 1 a to summon obj in free hand or return; reappears at end", + "level": 2, + "school": "Conj", + "time": "1 a", + "range": "Self", + "components": "S", + "duration": "Conc, 1 h", + "ritual": true, + "classes": [] }, "pulse wave": { "name": "Pulse Wave", @@ -1811,7 +3514,15 @@ "page": 188 } ], - "description": "6d6+1d6/SL Force dmg, pulled/pushed 15+5/SL ft from me (also free obj); save halves, no move" + "description": "6d6+1d6/SL Force dmg, pulled/pushed 15+5/SL ft from me (also free obj); save halves, no move", + "level": 3, + "school": "Evoc", + "time": "1 a", + "range": "S:30", + "components": "V,S", + "duration": "Instantaneous", + "save": "Con", + "classes": [] }, "gravity sinkhole": { "name": "Gravity Sinkhole", @@ -1821,7 +3532,15 @@ "page": 187 } ], - "description": "20-ft rad all crea 5d10+1d10/SL Force dmg, pulled to center of radius; save halves and not pulled" + "description": "20-ft rad all crea 5d10+1d10/SL Force dmg, pulled to center of radius; save halves and not pulled", + "level": 4, + "school": "Evoc", + "time": "1 a", + "range": "120 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Con", + "classes": [] }, "temporal shunt": { "name": "Temporal Shunt", @@ -1831,7 +3550,15 @@ "page": 189 } ], - "description": "Cast if see atk/cast, 1+1/SL crea, each max 30 ft apart, save or vanish until next turn, atk/cast wasted" + "description": "Cast if see atk/cast, 1+1/SL crea, each max 30 ft apart, save or vanish until next turn, atk/cast wasted", + "level": 5, + "school": "Trans", + "time": "1 rea", + "range": "120 ft", + "components": "V,S", + "duration": "1 rnd", + "save": "Wis", + "classes": [] }, "gravity fissure": { "name": "Gravity Fissure", @@ -1841,7 +3568,14 @@ "page": 187 } ], - "description": "100-ft long 5-ft wide all 8d8+1d8/SL Force dmg, save half; all in 10 ft of line save or dmg \\u0026 pull to it" + "description": "100-ft long 5-ft wide all 8d8+1d8/SL Force dmg, save half; all in 10 ft of line save or dmg \\u0026 pull to it", + "level": 6, + "school": "Evoc", + "time": "1 a", + "range": "S:100", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Con" }, "tether essence": { "name": "Tether Essence", @@ -1851,7 +3585,15 @@ "page": 189 } ], - "description": "2 crea save (dis. if in 30 ft) or if both fail take same dmg and same healing; ends if 0 hp (250gp cons.)" + "description": "2 crea save (dis. if in 30 ft) or if both fail take same dmg and same healing; ends if 0 hp (250gp cons.)", + "level": 7, + "school": "Necro", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M\\u2020", + "duration": "Conc, 1 h", + "save": "Con", + "classes": [] }, "dark star": { "name": "Dark Star", @@ -1861,7 +3603,15 @@ "page": 186 } ], - "description": "Up to 40-ft rad as Darkness spell, as Silence spell, dif. ter.; enter/start turn 8d10 Force dmg, save half" + "description": "Up to 40-ft rad as Darkness spell, as Silence spell, dif. ter.; enter/start turn 8d10 Force dmg, save half", + "level": 8, + "school": "Evoc", + "time": "1 a", + "range": "150 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Con", + "classes": [] }, "reality break": { "name": "Reality Break", @@ -1871,7 +3621,15 @@ "page": 189 } ], - "description": "1 crea save or can't take reactions, random effect each turn, see book; extra save at end of every turn" + "description": "1 crea save or can't take reactions, random effect each turn, see book; extra save at end of every turn", + "level": 8, + "school": "Conj", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Wis", + "classes": [] }, "ravenous void": { "name": "Ravenous Void", @@ -1881,7 +3639,15 @@ "page": 188 } ], - "description": "20-ft rad all enter/start 5d10 Force dmg, restrained; all enter/start in 100 ft save or pulled in; see B" + "description": "20-ft rad all enter/start 5d10 Force dmg, restrained; all enter/start in 100 ft save or pulled in; see B", + "level": 9, + "school": "Evoc", + "time": "1 a", + "range": "1000 ft", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Str", + "classes": [] }, "time ravage": { "name": "Time Ravage", @@ -1891,7 +3657,15 @@ "page": 189 } ], - "description": "1 crea 10d12 Necrotic dmg \\u0026 aged: dis. atk/chk/save, die in 30 days; save half, not aged (5k gp cons.)" + "description": "1 crea 10d12 Necrotic dmg \\u0026 aged: dis. atk/chk/save, die in 30 days; save half, not aged (5k gp cons.)", + "level": 9, + "school": "Necro", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u2020", + "duration": "Instantaneous", + "save": "Con", + "classes": [] }, "blade of disaster": { "name": "Blade of Disaster", @@ -1905,7 +3679,18 @@ "page": 318 } ], - "description": "Create weapon; 2 spell atks 4d12 Force dmg; crit on 18+, triple dmg; bns a to move 30 ft \\u0026 do 2 atks" + "description": "Create weapon; 2 spell atks 4d12 Force dmg; crit on 18+, triple dmg; bns a to move 30 ft \\u0026 do 2 atks", + "level": 9, + "school": "Conj", + "time": "1 bns", + "range": "60 ft", + "components": "V,S", + "duration": "Conc, 1 min", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "create magen": { "name": "Create Magen", @@ -1915,7 +3700,16 @@ "page": 318 } ], - "description": "Transform doll into magen (500gp cons.); obeys me; my HP max reduced by its CR; see book (1.5k gp)" + "description": "Transform doll into magen (500gp cons.); obeys me; my HP max reduced by its CR; see book (1.5k gp)", + "level": 7, + "school": "Trans", + "time": "1 h", + "range": "Touch", + "components": "V,S,M\\u2020", + "duration": "Instantaneous", + "classes": [ + "wizard" + ] }, "frost fingers": { "name": "Frost Fingers", @@ -1925,7 +3719,17 @@ "page": 318 } ], - "description": "All in area 2d8+1d8/SL Cold dmg; save halves; unattended nonmagical liquids freeze" + "description": "All in area 2d8+1d8/SL Cold dmg; save halves; unattended nonmagical liquids freeze", + "level": 1, + "school": "Evoc", + "time": "1 a", + "range": "S:15", + "components": "V,S", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "wizard" + ] }, "dream of the blue veil": { "name": "Dream of the Blue Veil", @@ -1935,7 +3739,19 @@ "page": 106 } ], - "description": "9 willing crea unconscious for duration, after that travel to origin material plane of magic item or crea" + "description": "9 willing crea unconscious for duration, after that travel to origin material plane of magic item or crea", + "level": 7, + "school": "Conj", + "time": "10 min", + "range": "20 ft", + "components": "V,S,M\\u0192", + "duration": "6 hours", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "intellect fortress": { "name": "Intellect Fortress", @@ -1945,7 +3761,20 @@ "page": 107 } ], - "description": "1+1/SL crea, each max 30 ft apart, has Psychic damage resistance and adv. on Int, Wis, and Cha saves" + "description": "1+1/SL crea, each max 30 ft apart, has Psychic damage resistance and adv. on Int, Wis, and Cha saves", + "level": 3, + "school": "Abjur", + "time": "1 a", + "range": "30 ft", + "components": "V", + "duration": "Conc, 1 h", + "classes": [ + "artificer", + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "mind sliver": { "name": "Mind Sliver", @@ -1967,7 +3796,19 @@ "page": 7 } ], - "description": "1 crea save or 1d6 Psychic dmg, -1d4 on first save before my next turn ends; +1d6 at CL 5, 11, and 17" + "description": "1 crea save or 1d6 Psychic dmg, -1d4 on first save before my next turn ends; +1d6 at CL 5, 11, and 17", + "level": 0, + "school": "Ench", + "time": "1 a", + "range": "60 ft", + "components": "V", + "duration": "1 rnd", + "save": "Int", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "spirit shroud": { "name": "Spirit Shroud", @@ -1977,7 +3818,19 @@ "page": 108 } ], - "description": "My atks +1d8+1d8/2SL Cold/Necro/Radiant dmg, no heal until next turn; any crea I see -10 ft spd" + "description": "My atks +1d8+1d8/2SL Cold/Necro/Radiant dmg, no heal until next turn; any crea I see -10 ft spd", + "level": 3, + "school": "Necro", + "time": "1 bns", + "range": "S:10-ft rad", + "components": "V,S", + "duration": "Conc, 1 min", + "classes": [ + "cleric", + "paladin", + "warlock", + "wizard" + ] }, "summon aberration": { "name": "Summon Aberration", @@ -1987,7 +3840,17 @@ "page": 109 } ], - "description": "Summon choice of Abberant Spirit; obeys commands; takes turn after mine; vanishes at 0 hp (400gp)" + "description": "Summon choice of Abberant Spirit; obeys commands; takes turn after mine; vanishes at 0 hp (400gp)", + "level": 4, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "warlock", + "wizard" + ] }, "summon beast": { "name": "Summon Beast", @@ -1997,7 +3860,17 @@ "page": 109 } ], - "description": "Summon choice of Bestial Spirit; obeys commands; takes turn after mine; disappears at 0 hp (200gp)" + "description": "Summon choice of Bestial Spirit; obeys commands; takes turn after mine; disappears at 0 hp (200gp)", + "level": 2, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "druid", + "ranger" + ] }, "summon celestial": { "name": "Summon Celestial", @@ -2007,7 +3880,17 @@ "page": 110 } ], - "description": "Summon choice of Celestial Spirit; obeys commands; takes turn after mine; disappears at 0 hp (500gp)" + "description": "Summon choice of Celestial Spirit; obeys commands; takes turn after mine; disappears at 0 hp (500gp)", + "level": 5, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "cleric", + "paladin" + ] }, "summon construct": { "name": "Summon Construct", @@ -2017,7 +3900,17 @@ "page": 111 } ], - "description": "Summon choice of Construct Spirit; obeys commands; takes turn after mine; vanishes at 0 hp (400gp)" + "description": "Summon choice of Construct Spirit; obeys commands; takes turn after mine; vanishes at 0 hp (400gp)", + "level": 4, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "artificer", + "wizard" + ] }, "summon elemental": { "name": "Summon Elemental", @@ -2027,7 +3920,18 @@ "page": 111 } ], - "description": "Summon choice of Elemental Spirit; obeys commands; takes turn after mine; vanishes at 0 hp (400gp)" + "description": "Summon choice of Elemental Spirit; obeys commands; takes turn after mine; vanishes at 0 hp (400gp)", + "level": 4, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "druid", + "ranger", + "wizard" + ] }, "summon fey": { "name": "Summon Fey", @@ -2037,7 +3941,19 @@ "page": 112 } ], - "description": "Summon choice of Fey Spirit; obeys commands; takes turn after mine; disappears at 0 hp (300gp)" + "description": "Summon choice of Fey Spirit; obeys commands; takes turn after mine; disappears at 0 hp (300gp)", + "level": 3, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "druid", + "ranger", + "warlock", + "wizard" + ] }, "summon fiend": { "name": "Summon Fiend", @@ -2047,7 +3963,17 @@ "page": 112 } ], - "description": "Summon choice of Fiendish Spirit; obeys commands; takes turn after mine; disappears at 0 hp (600gp)" + "description": "Summon choice of Fiendish Spirit; obeys commands; takes turn after mine; disappears at 0 hp (600gp)", + "level": 6, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "warlock", + "wizard" + ] }, "summon shadowspawn": { "name": "Summon Shadowspawn", @@ -2057,7 +3983,17 @@ "page": 113 } ], - "description": "Summon choice of Shadow Spirit; obeys commands; takes turn after mine; disappears at 0 hp (300gp)" + "description": "Summon choice of Shadow Spirit; obeys commands; takes turn after mine; disappears at 0 hp (300gp)", + "level": 3, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "warlock", + "wizard" + ] }, "summon undead": { "name": "Summon Undead", @@ -2067,7 +4003,17 @@ "page": 114 } ], - "description": "Summon choice of Undead Spirit; obeys commands; takes turn after mine; disappears at 0 hp (300gp)" + "description": "Summon choice of Undead Spirit; obeys commands; takes turn after mine; disappears at 0 hp (300gp)", + "level": 3, + "school": "Necro", + "time": "1 a", + "range": "90 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "warlock", + "wizard" + ] }, "tasha's caustic brew": { "name": "Tasha", @@ -2077,7 +4023,19 @@ "page": 115 } ], - "description": "30-ft long 5-ft wide all save or 2d4+2d4/SL Acid dmg at start of turn; action to clean self or adjacent" + "description": "30-ft long 5-ft wide all save or 2d4+2d4/SL Acid dmg at start of turn; action to clean self or adjacent", + "level": 1, + "school": "Evoc", + "time": "1 a", + "range": "S:30-ft line", + "components": "V,S,M", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "artificer", + "sorcerer", + "wizard" + ] }, "tasha's mind whip": { "name": "Tasha", @@ -2091,7 +4049,18 @@ "page": 8 } ], - "description": "1+1/SL crea, max 30 ft apart; 3d6 Psychic dmg; no rea; only move, act, or bns; save half, no act limit" + "description": "1+1/SL crea, max 30 ft apart; 3d6 Psychic dmg; no rea; only move, act, or bns; save half, no act limit", + "level": 2, + "school": "Ench", + "time": "1 a", + "range": "90 ft", + "components": "V", + "duration": "1 rnd", + "save": "Int", + "classes": [ + "sorcerer", + "wizard" + ] }, "tasha's otherworldly guise": { "name": "Tasha", @@ -2101,7 +4070,18 @@ "page": 116 } ], - "description": "Fire/Poison or Radiant/Necrotic/Charm immune; 40 ft fly; +2 AC; 2 atks; spellcast. abi atks (500gp)" + "description": "Fire/Poison or Radiant/Necrotic/Charm immune; 40 ft fly; +2 AC; 2 atks; spellcast. abi atks (500gp)", + "level": 6, + "school": "Trans", + "time": "1 bns", + "range": "Self", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 min", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "ashardalon's stride": { "name": "Ashardalon", @@ -2115,7 +4095,19 @@ "page": 6 } ], - "description": "+20+5/SL ft speed; provoke no opp atks for moving; all crea/obj in 5 ft of path 1d6+1d6/SL Fire dmg" + "description": "+20+5/SL ft speed; provoke no opp atks for moving; all crea/obj in 5 ft of path 1d6+1d6/SL Fire dmg", + "level": 3, + "school": "Trans", + "time": "1 bns", + "range": "Self", + "components": "V,S", + "duration": "Conc, 1 min", + "classes": [ + "artificer", + "ranger", + "sorcerer", + "wizard" + ] }, "draconic transformation": { "name": "Draconic Transformation", @@ -2125,7 +4117,19 @@ "page": 19 } ], - "description": "Blindsight 30 ft; 60 ft fly speed; at cast and 1 bns: 60-ft cone all 6d8 Force damage, save half (500gp)" + "description": "Blindsight 30 ft; 60 ft fly speed; at cast and 1 bns: 60-ft cone all 6d8 Force damage, save half (500gp)", + "level": 7, + "school": "Trans", + "time": "1 bns", + "range": "S:60", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 min", + "save": "Dex", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "fizban's platinum shield": { "name": "Fizban", @@ -2135,7 +4139,17 @@ "page": 20 } ], - "description": "1 crea Acid, Cold, Fire, Lightn. \\u0026 Poison resist., half cover, better Dex saves; 1 bns change crea (500gp)" + "description": "1 crea Acid, Cold, Fire, Lightn. \\u0026 Poison resist., half cover, better Dex saves; 1 bns change crea (500gp)", + "level": 6, + "school": "Abjur", + "time": "1 bns", + "range": "60 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 min", + "classes": [ + "sorcerer", + "wizard" + ] }, "nathair's mischief": { "name": "Nathair", @@ -2149,7 +4163,19 @@ "page": 6 } ], - "description": "20-ft cube of magic, roll d4 for effect; At start of my turn, move cube 10 ft and reroll effect; see book" + "description": "20-ft cube of magic, roll d4 for effect; At start of my turn, move cube 10 ft and reroll effect; see book", + "level": 2, + "school": "Illus", + "time": "1 a", + "range": "60 ft", + "components": "S,M", + "duration": "Conc, 1 min", + "save": "Var", + "classes": [ + "bard", + "sorcerer", + "wizard" + ] }, "raulothim's psychic lance": { "name": "Raulothim", @@ -2159,7 +4185,20 @@ "page": 21 } ], - "description": "1 crea I see or can name 7d6+1d6/SL Psychic dmg \\u0026 incap. till start of my turn; save half, not incap." + "description": "1 crea I see or can name 7d6+1d6/SL Psychic dmg \\u0026 incap. till start of my turn; save half, not incap.", + "level": 4, + "school": "Ench", + "time": "1 a", + "range": "120 ft", + "components": "V", + "duration": "Instantaneous", + "save": "Int", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "rime's binding ice": { "name": "Rime", @@ -2173,7 +4212,18 @@ "page": 6 } ], - "description": "All in area 3d8+1d8/SL Cold dmg and speed 0 for 1 min until 1 a to undo; save halves, normal speed" + "description": "All in area 3d8+1d8/SL Cold dmg and speed 0 for 1 min until 1 a to undo; save halves, normal speed", + "level": 2, + "school": "Evoc", + "time": "1 a", + "range": "S:30", + "components": "S,M", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "sorcerer", + "wizard" + ] }, "summon draconic spirit": { "name": "Summon Draconic Spirit", @@ -2187,7 +4237,18 @@ "page": 7 } ], - "description": "Summon choice of Draconic Spirit; obeys commands; takes turn after mine; vanishes at 0 hp (500gp)" + "description": "Summon choice of Draconic Spirit; obeys commands; takes turn after mine; vanishes at 0 hp (500gp)", + "level": 5, + "school": "Conj", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "borrowed knowledge": { "name": "Borrowed Knowledge", @@ -2197,7 +4258,19 @@ "page": 37 } ], - "description": "Gain proficiency with one skill; ends early if cast again (25gp)" + "description": "Gain proficiency with one skill; ends early if cast again (25gp)", + "level": 2, + "school": "Div", + "time": "1 a", + "range": "Self", + "components": "V,S,M\\u0192", + "duration": "1 h", + "classes": [ + "bard", + "cleric", + "warlock", + "wizard" + ] }, "kinetic jaunt": { "name": "Kinetic Jaunt", @@ -2207,7 +4280,19 @@ "page": 37 } ], - "description": "+10 ft walk spd; provoke no opportunity atks; move through crea space, counts not as difficult terrain" + "description": "+10 ft walk spd; provoke no opportunity atks; move through crea space, counts not as difficult terrain", + "level": 2, + "school": "Trans", + "time": "1 bns", + "range": "Self", + "components": "S", + "duration": "Conc, 1 min", + "classes": [ + "artificer", + "bard", + "sorcerer", + "wizard" + ] }, "silvery barbs": { "name": "Silvery Barbs", @@ -2217,7 +4302,18 @@ "page": 38 } ], - "description": "1 crea reroll d20 and use lowest for atk, check, or save; 1 crea adv. next atk, check, or save in 1 min" + "description": "1 crea reroll d20 and use lowest for atk, check, or save; 1 crea adv. next atk, check, or save in 1 min", + "level": 1, + "school": "Ench", + "time": "1 rea", + "range": "60 ft", + "components": "V", + "duration": "Instantaneous", + "classes": [ + "bard", + "sorcerer", + "wizard" + ] }, "vortex warp": { "name": "Vortex Warp", @@ -2227,7 +4323,19 @@ "page": 38 } ], - "description": "1 crea save or teleported to a sufficiently empty space of my choice within range; +30 ft/SL range" + "description": "1 crea save or teleported to a sufficiently empty space of my choice within range; +30 ft/SL range", + "level": 2, + "school": "Conj", + "time": "1 a", + "range": "90 ft", + "components": "V,S", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "artificer", + "sorcerer", + "wizard" + ] }, "wither and bloom": { "name": "Wither and Bloom", @@ -2237,7 +4345,19 @@ "page": 38 } ], - "description": "10-ft rad any crea 2d6+1d6/SL Necrotic dmg, save half; 1 crea can heal using 1+1/SL HD; see B" + "description": "10-ft rad any crea 2d6+1d6/SL Necrotic dmg, save half; 1 crea can heal using 1+1/SL HD; see B", + "level": 2, + "school": "Necro", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Con", + "classes": [ + "druid", + "sorcerer", + "wizard" + ] }, "air bubble": { "name": "Air Bubble", @@ -2247,7 +4367,20 @@ "page": 22 } ], - "description": "Create spectral globe of fresh air around a head of 1+2/SL willing creatures, lasts for the duration" + "description": "Create spectral globe of fresh air around a head of 1+2/SL willing creatures, lasts for the duration", + "level": 2, + "school": "Conj", + "time": "1 a", + "range": "60 ft", + "components": "S", + "duration": "24 h", + "classes": [ + "artificer", + "druid", + "ranger", + "sorcerer", + "wizard" + ] }, "create spelljamming helm": { "name": "Create Spelljamming Helm", @@ -2257,7 +4390,17 @@ "page": 22 } ], - "description": "One Large or smaller unoccupied chair I touch transforms into a spelljamming helm (5000gp cons.)" + "description": "One Large or smaller unoccupied chair I touch transforms into a spelljamming helm (5000gp cons.)", + "level": 5, + "school": "Trans", + "time": "1 a", + "range": "Touch", + "components": "V,S,M\\u2020", + "duration": "Instantaneous", + "classes": [ + "artificer", + "wizard" + ] }, "gate seal": { "name": "Gate Seal", @@ -2267,7 +4410,18 @@ "page": 12 } ], - "description": "30-ft cube wherein all portals close and can't be opened, and no planar travel; SL6: until dispelled" + "description": "30-ft cube wherein all portals close and can't be opened, and no planar travel; SL6: until dispelled", + "level": 4, + "school": "Abjur", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M\\u2020", + "duration": "24 h", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "warp sense": { "name": "Warp Sense", @@ -2277,7 +4431,18 @@ "page": 12 } ], - "description": "Know presence of portals in 30 ft; 1 a DC 15 spell ability chk to see destination \\u0026 portal key, ends spell" + "description": "Know presence of portals in 30 ft; 1 a DC 15 spell ability chk to see destination \\u0026 portal key, ends spell", + "level": 2, + "school": "Div", + "time": "1 a", + "range": "Self", + "components": "V,S,M", + "duration": "Conc, 1 min", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "antagonize": { "name": "Antagonize", @@ -2287,7 +4452,20 @@ "page": 50 } ], - "description": "1 crea 4d4+1d4/SL Psychic dmg, use rea to melee atk vs. crea I see (or dis. atk 1 rnd); save half, no rea" + "description": "1 crea 4d4+1d4/SL Psychic dmg, use rea to melee atk vs. crea I see (or dis. atk 1 rnd); save half, no rea", + "level": 3, + "school": "Ench", + "time": "1 a", + "range": "30 ft", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Wis", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] }, "spirit of death": { "name": "Spirit of Death", @@ -2297,7 +4475,18 @@ "page": 50 } ], - "description": "Summon a Reaper Spirit; obeys commands; takes turn after mine; disappears at 0 hp (400gp)" + "description": "Summon a Reaper Spirit; obeys commands; takes turn after mine; disappears at 0 hp (400gp)", + "level": 4, + "school": "Necro", + "time": "1 a", + "range": "60 ft", + "components": "V,S,M\\u0192", + "duration": "Conc, 1 h", + "classes": [ + "sorcerer", + "warlock", + "wizard" + ] }, "spray of cards": { "name": "Spray of Cards", @@ -2307,6 +4496,19 @@ "page": 50 } ], - "description": "All in area 2d10+1d10/SL Force dmg and blinded until their next turn ends; save halves \\u0026 not blinded" + "description": "All in area 2d10+1d10/SL Force dmg and blinded until their next turn ends; save halves \\u0026 not blinded", + "level": 2, + "school": "Conj", + "time": "1 a", + "range": "S:15", + "components": "V,S,M", + "duration": "Instantaneous", + "save": "Dex", + "classes": [ + "bard", + "sorcerer", + "warlock", + "wizard" + ] } } \ No newline at end of file diff --git a/src/features/compendium/registry.tsx b/src/features/compendium/registry.tsx index c9821b1..7221ff7 100644 --- a/src/features/compendium/registry.tsx +++ b/src/features/compendium/registry.tsx @@ -185,13 +185,14 @@ export const CATEGORIES: CategoryDef[] = [ { id: '5e-spells', system: '5e', label: 'Spells', linkAs: 'spell', load: () => loadSpells() as unknown as Promise, - searchKeys: ['name', 'school'], - meta: (e) => { const l = (e as unknown as Spell).level_int; return l === 0 ? 'Cantrip' : `Lv ${l ?? '?'}`; }, + searchKeys: ['name', 'school', 'source'], + meta: (e) => { const s = e as unknown as Spell; const l = s.level_int; const lvl = l === 0 ? 'Cantrip' : `Lv ${l ?? '?'}`; return s.source && s.source !== 'SRD' ? `${lvl} · ${s.source}` : lvl; }, detail: (e) => , numericSort: { label: 'Level', get: (e) => Number(e.level_int) }, filters: [ { key: 'level', label: 'Level', kind: 'eq', get: (e) => e.level_int as number, options: (d) => numericOptions(d, (e) => e.level_int, (n) => (n === 0 ? 'Cantrip' : `Level ${n}`)) }, { key: 'school', label: 'School', kind: 'eq', get: (e) => e.school as string, options: (d) => distinctStrings(d, (e) => e.school) }, + { key: 'source', label: 'Source', kind: 'eq', get: (e) => e.source as string, options: (d) => distinctStrings(d, (e) => e.source) }, ], }, { diff --git a/src/lib/compendium/index.ts b/src/lib/compendium/index.ts index f9ea199..6e6485e 100644 --- a/src/lib/compendium/index.ts +++ b/src/lib/compendium/index.ts @@ -1,5 +1,6 @@ import type { SystemId } from '@/lib/rules'; import type { RulesetClass } from '@/lib/ruleset/normalize'; +import { normalizeMpmbSpell, type MpmbSpell } from './mpmb'; import type { Monster, Spell, @@ -30,8 +31,21 @@ export async function loadMonsters(): Promise { export async function loadSpells(): Promise { if (!spellsCache) { - const mod = await import('@/data/srd/spells-srd.json'); - spellsCache = mod.default as unknown as Spell[]; + const [srdMod, mpmbMod] = await Promise.all([ + import('@/data/srd/spells-srd.json'), + import('@/data/srd/mpmb-spells.json'), + ]); + const srd = (srdMod.default as unknown as Spell[]).map((s) => ({ ...s, source: s.source ?? 'SRD' })); + // Merge non-SRD MPMB spells (XGtE/TCE/etc.), deduped by name — SRD wins on overlap. + const have = new Set(srd.map((s) => s.name.trim().toLowerCase())); + const mpmbRaw = mpmbMod.default as Record; + const extra: Spell[] = []; + for (const raw of Object.values(mpmbRaw)) { + if (have.has((raw.name ?? '').trim().toLowerCase())) continue; + const s = normalizeMpmbSpell(raw); + if (s) extra.push(s); + } + spellsCache = [...srd, ...extra].sort((a, b) => a.name.localeCompare(b.name)); } return spellsCache; } diff --git a/src/lib/compendium/mpmb.test.ts b/src/lib/compendium/mpmb.test.ts new file mode 100644 index 0000000..75d0875 --- /dev/null +++ b/src/lib/compendium/mpmb.test.ts @@ -0,0 +1,50 @@ +import { describe, it, expect } from 'vitest'; +import { normalizeMpmbSpell, sourceLabel, mpmbPrimarySource } from './mpmb'; + +describe('normalizeMpmbSpell', () => { + it('maps an XGtE cantrip to the Open5e spell shape', () => { + const s = normalizeMpmbSpell({ + name: 'Toll the Dead', + source: [{ source: 'X', page: 169 }, { source: 'UA:SS', page: 4 }], + level: 0, + school: 'Necro', + time: '1 a', + range: '60 ft', + components: 'V,S', + duration: 'Instantaneous', + save: 'Wis', + classes: ['cleric', 'warlock', 'wizard'], + description: '1 crea save or 1d12 Necrotic dmg', + })!; + expect(s).toMatchObject({ + slug: 'toll-the-dead', + name: 'Toll the Dead', + level_int: 0, + level: 'Cantrip', + school: 'Necromancy', + casting_time: '1 action', + range: '60 ft', + components: 'V,S', + source: 'XGtE', // primary (first) source code mapped + dnd_class: 'Cleric, Warlock, Wizard', + }); + expect(s.requires_concentration).toBe(false); + }); + + it('flags concentration from the duration', () => { + const s = normalizeMpmbSpell({ name: 'Wall of Light', level: 5, school: 'Evoc', duration: 'Conc, 10 min', source: [{ source: 'X', page: 170 }] })!; + expect(s.requires_concentration).toBe(true); + expect(s.concentration).toBe('yes'); + expect(s.level).toBe('Level 5'); + }); + + it('passes unknown source codes through; maps known ones', () => { + expect(sourceLabel('T')).toBe('TCE'); + expect(sourceLabel('ZZZ')).toBe('ZZZ'); + expect(mpmbPrimarySource({ source: [{ source: 'X' }, { source: 'UA' }] })).toBe('X'); + }); + + it('returns null without a name', () => { + expect(normalizeMpmbSpell({ name: '' })).toBeNull(); + }); +}); diff --git a/src/lib/compendium/mpmb.ts b/src/lib/compendium/mpmb.ts new file mode 100644 index 0000000..d1f9cf8 --- /dev/null +++ b/src/lib/compendium/mpmb.ts @@ -0,0 +1,76 @@ +import type { Spell } from './types'; + +/** A parsed MPMB spell entry (scripts/parse_mpmb.py output). */ +export interface MpmbSpell { + name: string; + source?: { source: string; page: number | null }[]; + level?: number; + school?: string; + time?: string; + range?: string; + components?: string; + duration?: string; + save?: string; + ritual?: boolean; + classes?: string[]; + description?: string; +} + +// MPMB sourcebook codes → readable labels. Unknown codes pass through unchanged. +const SOURCE_LABEL: Record = { + P: 'PHB', X: 'XGtE', T: 'TCE', V: 'VGtM', M: 'MToF', MM: 'MM', + E: 'Eberron', 'E:RLW': 'Eberron', WGtE: 'Wayfinder', MOT: 'Theros', + G: 'GGtR', S: 'SCAG', SCC: 'Strixhaven', FToD: "Fizban's", BoMT: 'BoMT', + AcqInc: 'Acq. Inc.', RotF: 'Rime', 'S:AiS': 'Spelljammer', 'P:AitM': 'Planescape', + LLoK: 'Lost Lab', W: 'Witchlight', DMG: 'DMG', +}; + +const SCHOOL: Record = { + abjur: 'Abjuration', conj: 'Conjuration', div: 'Divination', ench: 'Enchantment', + evoc: 'Evocation', illus: 'Illusion', necro: 'Necromancy', trans: 'Transmutation', +}; + +const TIME: Record = { + '1 a': '1 action', '1 bns': '1 bonus action', '1 rea': '1 reaction', + '1 min': '1 minute', '10 min': '10 minutes', '1 h': '1 hour', '8 h': '8 hours', '24 h': '24 hours', +}; + +/** The primary (canonical, first-listed) source code of a parsed MPMB entry. */ +export function mpmbPrimarySource(raw: { source?: { source: string }[] }): string { + return raw.source?.[0]?.source ?? ''; +} + +/** Readable label for an MPMB source code (e.g. 'X' -> 'XGtE'). */ +export function sourceLabel(code: string): string { + return SOURCE_LABEL[code] ?? code; +} + +function slugify(name: string): string { + return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, ''); +} + +/** Normalize a parsed MPMB spell into the app's Open5e-shaped Spell. */ +export function normalizeMpmbSpell(raw: MpmbSpell): Spell | null { + if (!raw.name) return null; + const level = typeof raw.level === 'number' ? raw.level : 0; + const conc = /conc/i.test(raw.duration ?? ''); + const school = raw.school ? SCHOOL[raw.school.toLowerCase()] ?? raw.school : ''; + return { + slug: slugify(raw.name), + name: raw.name, + desc: raw.description ?? '', + level_int: level, + level: level === 0 ? 'Cantrip' : `Level ${level}`, + school, + casting_time: raw.time ? TIME[raw.time] ?? raw.time : '', + range: raw.range ?? '', + duration: raw.duration ?? '', + concentration: conc ? 'yes' : 'no', + requires_concentration: conc, + ritual: raw.ritual ? 'yes' : 'no', + can_be_cast_as_ritual: !!raw.ritual, + components: raw.components ?? '', + dnd_class: (raw.classes ?? []).map((c) => c.charAt(0).toUpperCase() + c.slice(1)).join(', '), + source: sourceLabel(mpmbPrimarySource(raw)), + }; +} diff --git a/src/lib/compendium/types.ts b/src/lib/compendium/types.ts index ad1a914..047a340 100644 --- a/src/lib/compendium/types.ts +++ b/src/lib/compendium/types.ts @@ -71,6 +71,8 @@ export interface Spell { components?: string; material?: string; dnd_class?: string; + /** sourcebook label (e.g. 'PHB', 'XGtE', 'TCE'); '' / undefined = SRD. */ + source?: string; } export interface MagicItem { diff --git a/tsconfig.app.tsbuildinfo b/tsconfig.app.tsbuildinfo index f4e1a70..17793f3 100644 --- a/tsconfig.app.tsbuildinfo +++ b/tsconfig.app.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/main.tsx","./src/router.tsx","./src/vite-env.d.ts","./src/app/NotFound.tsx","./src/app/RootLayout.tsx","./src/components/CommandPalette.tsx","./src/components/ui/Button.tsx","./src/components/ui/Codex.tsx","./src/components/ui/ErrorBoundary.tsx","./src/components/ui/Input.tsx","./src/components/ui/Modal.tsx","./src/components/ui/NumberField.tsx","./src/components/ui/Page.tsx","./src/components/ui/RollTray.tsx","./src/components/ui/useConfirm.tsx","./src/features/assistant/AssistantPage.tsx","./src/features/assistant/CampaignInsights.tsx","./src/features/assistant/EncounterTipCard.tsx","./src/features/assistant/NpcGenCard.tsx","./src/features/assistant/SessionPrepCard.tsx","./src/features/assistant/SignalsBell.tsx","./src/features/assistant/useEncounterAdvisor.ts","./src/features/assistant/useLevelUpAdvisor.ts","./src/features/assistant/useSignalAction.ts","./src/features/campaigns/CampaignsPage.tsx","./src/features/campaigns/hooks.ts","./src/features/characters/CharacterSheet.tsx","./src/features/characters/CharacterSheetPage.tsx","./src/features/characters/CharactersPage.tsx","./src/features/characters/hooks.ts","./src/features/characters/builder/CreationWizard.tsx","./src/features/characters/builder/origin.test.ts","./src/features/characters/builder/origin.ts","./src/features/characters/builder/overview.test.ts","./src/features/characters/builder/overview.ts","./src/features/characters/sheet/AbilityGenModal.tsx","./src/features/characters/sheet/AttacksSection.tsx","./src/features/characters/sheet/DefensesSection.tsx","./src/features/characters/sheet/FeatsSection.tsx","./src/features/characters/sheet/InventorySection.tsx","./src/features/characters/sheet/LevelUpAdvisor.tsx","./src/features/characters/sheet/LevelUpModal.tsx","./src/features/characters/sheet/ResourcesSection.tsx","./src/features/characters/sheet/SpellcastingSection.tsx","./src/features/characters/sheet/common.tsx","./src/features/characters/sheet/labels.ts","./src/features/cloud/SyncStatusIndicator.tsx","./src/features/cloud/useCloudAutosave.ts","./src/features/combat/CombatPage.tsx","./src/features/combat/EncounterTracker.tsx","./src/features/combat/hooks.ts","./src/features/combat/useConditionGlossary.ts","./src/features/compendium/CompendiumPage.tsx","./src/features/compendium/MonsterDetail.tsx","./src/features/compendium/details.tsx","./src/features/compendium/registry.test.ts","./src/features/compendium/registry.tsx","./src/features/dice/DicePage.tsx","./src/features/play/HandoutControl.tsx","./src/features/play/PlayerConnection.tsx","./src/features/play/SessionControl.tsx","./src/features/play/SessionSidebar.tsx","./src/features/play/usePlayerConnection.ts","./src/features/play/useSessionBroadcaster.ts","./src/features/player/ActionGuide.tsx","./src/features/player/MyCharacterPanel.tsx","./src/features/player/PlayerBoards.tsx","./src/features/player/PlayerMapView.tsx","./src/features/player/PlayerSetupPage.tsx","./src/features/player/PlayerViewPage.tsx","./src/features/player/RollFeed.tsx","./src/features/player/SeatClaimScreen.tsx","./src/features/settings/AssistantSettings.tsx","./src/features/settings/CloudCampaigns.tsx","./src/features/settings/SettingsPage.tsx","./src/features/world/CalendarPage.tsx","./src/features/world/DashboardPage.tsx","./src/features/world/HomebrewPage.tsx","./src/features/world/MapsPage.tsx","./src/features/world/NotesPage.tsx","./src/features/world/NpcsPage.tsx","./src/features/world/QuestsPage.tsx","./src/features/world/homebrew.ts","./src/features/world/hooks.ts","./src/features/world/map/MapCanvas.tsx","./src/features/world/map/MapEditor.tsx","./src/features/world/map/TokenPalette.test.ts","./src/features/world/map/TokenPalette.tsx","./src/features/world/map/tokens.ts","./src/lib/cn.ts","./src/lib/format.ts","./src/lib/ids.ts","./src/lib/rng.ts","./src/lib/sample.ts","./src/lib/useDebouncedCallback.ts","./src/lib/useRoll.ts","./src/lib/wikilinks.test.ts","./src/lib/wikilinks.ts","./src/lib/assistant/actions.ts","./src/lib/assistant/advisors.test.ts","./src/lib/assistant/advisors.ts","./src/lib/assistant/builder.ts","./src/lib/assistant/context.test.ts","./src/lib/assistant/context.ts","./src/lib/assistant/encounter.ts","./src/lib/assistant/levelup.test.ts","./src/lib/assistant/levelup.ts","./src/lib/assistant/patterns.test.ts","./src/lib/assistant/patterns.ts","./src/lib/assistant/prompts.test.ts","./src/lib/assistant/prompts.ts","./src/lib/assistant/session.ts","./src/lib/assistant/signals.test.ts","./src/lib/assistant/signals.ts","./src/lib/cloud/campaigns.ts","./src/lib/cloud/client.ts","./src/lib/combat/budget.test.ts","./src/lib/combat/budget.ts","./src/lib/combat/engine.test.ts","./src/lib/combat/engine.ts","./src/lib/combat/playerProjection.test.ts","./src/lib/combat/playerProjection.ts","./src/lib/compendium/index.ts","./src/lib/compendium/types.ts","./src/lib/db/db.ts","./src/lib/db/repositories.test.ts","./src/lib/db/repositories.ts","./src/lib/dice/check.test.ts","./src/lib/dice/check.ts","./src/lib/dice/notation.test.ts","./src/lib/dice/notation.ts","./src/lib/img/resize.test.ts","./src/lib/img/resize.ts","./src/lib/io/backup.test.ts","./src/lib/io/backup.ts","./src/lib/io/character.test.ts","./src/lib/io/character.ts","./src/lib/io/file.ts","./src/lib/io/pathbuilder.test.ts","./src/lib/io/pathbuilder.ts","./src/lib/llm/client.test.ts","./src/lib/llm/client.ts","./src/lib/llm/types.ts","./src/lib/map/distance.ts","./src/lib/map/fog.ts","./src/lib/map/grid.ts","./src/lib/map/index.ts","./src/lib/map/map.test.ts","./src/lib/map/projection.test.ts","./src/lib/map/projection.ts","./src/lib/map/shapes.ts","./src/lib/map/types.ts","./src/lib/map/viewport.test.ts","./src/lib/map/viewport.ts","./src/lib/map/vision.test.ts","./src/lib/map/vision.ts","./src/lib/mechanics/cast.ts","./src/lib/mechanics/conditionEffects.ts","./src/lib/mechanics/creatureState.test.ts","./src/lib/mechanics/creatureState.ts","./src/lib/mechanics/deathSaves.ts","./src/lib/mechanics/enforce.test.ts","./src/lib/mechanics/index.ts","./src/lib/mechanics/resources.ts","./src/lib/mechanics/result.ts","./src/lib/mechanics/types.ts","./src/lib/mechanics/normalize/armor.ts","./src/lib/mechanics/normalize/monsterDefenses.ts","./src/lib/mechanics/normalize/normalize.test.ts","./src/lib/mechanics/normalize/spell.ts","./src/lib/rules/abilities.ts","./src/lib/rules/abilityGen.test.ts","./src/lib/rules/abilityGen.ts","./src/lib/rules/conditions.ts","./src/lib/rules/depth.test.ts","./src/lib/rules/index.ts","./src/lib/rules/multiclass.test.ts","./src/lib/rules/progression.test.ts","./src/lib/rules/progression.ts","./src/lib/rules/rest.ts","./src/lib/rules/rules.test.ts","./src/lib/rules/types.ts","./src/lib/rules/dnd5e/index.ts","./src/lib/rules/dnd5e/progression.ts","./src/lib/rules/dnd5e/skills.ts","./src/lib/rules/pf2e/abilities.test.ts","./src/lib/rules/pf2e/abilities.ts","./src/lib/rules/pf2e/index.ts","./src/lib/rules/pf2e/progression.ts","./src/lib/rules/pf2e/skills.ts","./src/lib/ruleset/normalize.test.ts","./src/lib/ruleset/normalize.ts","./src/lib/schemas/campaign.ts","./src/lib/schemas/character.ts","./src/lib/schemas/common.ts","./src/lib/schemas/dice.ts","./src/lib/schemas/encounter.ts","./src/lib/schemas/index.ts","./src/lib/schemas/sessionLog.ts","./src/lib/schemas/world.ts","./src/lib/sync/index.ts","./src/lib/sync/messages.test.ts","./src/lib/sync/messages.ts","./src/lib/sync/playerLink.test.ts","./src/lib/sync/playerLink.ts","./src/lib/sync/snapshot.ts","./src/lib/sync/wsSync.ts","./src/lib/vtt/uvtt.test.ts","./src/lib/vtt/uvtt.ts","./src/stores/assistantStore.ts","./src/stores/connectivityStore.ts","./src/stores/macroStore.ts","./src/stores/playerSessionStore.ts","./src/stores/rollStore.ts","./src/stores/sessionStore.ts","./src/stores/uiStore.ts","./vitest.setup.ts"],"version":"5.9.3"} \ No newline at end of file +{"root":["./src/main.tsx","./src/router.tsx","./src/vite-env.d.ts","./src/app/NotFound.tsx","./src/app/RootLayout.tsx","./src/components/CommandPalette.tsx","./src/components/ui/Button.tsx","./src/components/ui/Codex.tsx","./src/components/ui/ErrorBoundary.tsx","./src/components/ui/Input.tsx","./src/components/ui/Modal.tsx","./src/components/ui/NumberField.tsx","./src/components/ui/Page.tsx","./src/components/ui/RollTray.tsx","./src/components/ui/useConfirm.tsx","./src/features/assistant/AssistantPage.tsx","./src/features/assistant/CampaignInsights.tsx","./src/features/assistant/EncounterTipCard.tsx","./src/features/assistant/NpcGenCard.tsx","./src/features/assistant/SessionPrepCard.tsx","./src/features/assistant/SignalsBell.tsx","./src/features/assistant/useEncounterAdvisor.ts","./src/features/assistant/useLevelUpAdvisor.ts","./src/features/assistant/useSignalAction.ts","./src/features/campaigns/CampaignsPage.tsx","./src/features/campaigns/hooks.ts","./src/features/characters/CharacterSheet.tsx","./src/features/characters/CharacterSheetPage.tsx","./src/features/characters/CharactersPage.tsx","./src/features/characters/hooks.ts","./src/features/characters/builder/CreationWizard.tsx","./src/features/characters/builder/origin.test.ts","./src/features/characters/builder/origin.ts","./src/features/characters/builder/overview.test.ts","./src/features/characters/builder/overview.ts","./src/features/characters/sheet/AbilityGenModal.tsx","./src/features/characters/sheet/AttacksSection.tsx","./src/features/characters/sheet/DefensesSection.tsx","./src/features/characters/sheet/FeatsSection.tsx","./src/features/characters/sheet/InventorySection.tsx","./src/features/characters/sheet/LevelUpAdvisor.tsx","./src/features/characters/sheet/LevelUpModal.tsx","./src/features/characters/sheet/ResourcesSection.tsx","./src/features/characters/sheet/SpellcastingSection.tsx","./src/features/characters/sheet/common.tsx","./src/features/characters/sheet/labels.ts","./src/features/cloud/SyncStatusIndicator.tsx","./src/features/cloud/useCloudAutosave.ts","./src/features/combat/CombatPage.tsx","./src/features/combat/EncounterTracker.tsx","./src/features/combat/hooks.ts","./src/features/combat/useConditionGlossary.ts","./src/features/compendium/CompendiumPage.tsx","./src/features/compendium/MonsterDetail.tsx","./src/features/compendium/details.tsx","./src/features/compendium/registry.test.ts","./src/features/compendium/registry.tsx","./src/features/dice/DicePage.tsx","./src/features/play/HandoutControl.tsx","./src/features/play/PlayerConnection.tsx","./src/features/play/SessionControl.tsx","./src/features/play/SessionSidebar.tsx","./src/features/play/usePlayerConnection.ts","./src/features/play/useSessionBroadcaster.ts","./src/features/player/ActionGuide.tsx","./src/features/player/MyCharacterPanel.tsx","./src/features/player/PlayerBoards.tsx","./src/features/player/PlayerMapView.tsx","./src/features/player/PlayerSetupPage.tsx","./src/features/player/PlayerViewPage.tsx","./src/features/player/RollFeed.tsx","./src/features/player/SeatClaimScreen.tsx","./src/features/settings/AssistantSettings.tsx","./src/features/settings/CloudCampaigns.tsx","./src/features/settings/SettingsPage.tsx","./src/features/world/CalendarPage.tsx","./src/features/world/DashboardPage.tsx","./src/features/world/HomebrewPage.tsx","./src/features/world/MapsPage.tsx","./src/features/world/NotesPage.tsx","./src/features/world/NpcsPage.tsx","./src/features/world/QuestsPage.tsx","./src/features/world/homebrew.ts","./src/features/world/hooks.ts","./src/features/world/map/MapCanvas.tsx","./src/features/world/map/MapEditor.tsx","./src/features/world/map/TokenPalette.test.ts","./src/features/world/map/TokenPalette.tsx","./src/features/world/map/tokens.ts","./src/lib/cn.ts","./src/lib/format.ts","./src/lib/ids.ts","./src/lib/rng.ts","./src/lib/sample.ts","./src/lib/useDebouncedCallback.ts","./src/lib/useRoll.ts","./src/lib/wikilinks.test.ts","./src/lib/wikilinks.ts","./src/lib/assistant/actions.ts","./src/lib/assistant/advisors.test.ts","./src/lib/assistant/advisors.ts","./src/lib/assistant/builder.ts","./src/lib/assistant/context.test.ts","./src/lib/assistant/context.ts","./src/lib/assistant/encounter.ts","./src/lib/assistant/levelup.test.ts","./src/lib/assistant/levelup.ts","./src/lib/assistant/patterns.test.ts","./src/lib/assistant/patterns.ts","./src/lib/assistant/prompts.test.ts","./src/lib/assistant/prompts.ts","./src/lib/assistant/session.ts","./src/lib/assistant/signals.test.ts","./src/lib/assistant/signals.ts","./src/lib/cloud/campaigns.ts","./src/lib/cloud/client.ts","./src/lib/combat/budget.test.ts","./src/lib/combat/budget.ts","./src/lib/combat/engine.test.ts","./src/lib/combat/engine.ts","./src/lib/combat/playerProjection.test.ts","./src/lib/combat/playerProjection.ts","./src/lib/compendium/index.ts","./src/lib/compendium/mpmb.test.ts","./src/lib/compendium/mpmb.ts","./src/lib/compendium/types.ts","./src/lib/db/db.ts","./src/lib/db/repositories.test.ts","./src/lib/db/repositories.ts","./src/lib/dice/check.test.ts","./src/lib/dice/check.ts","./src/lib/dice/notation.test.ts","./src/lib/dice/notation.ts","./src/lib/img/resize.test.ts","./src/lib/img/resize.ts","./src/lib/io/backup.test.ts","./src/lib/io/backup.ts","./src/lib/io/character.test.ts","./src/lib/io/character.ts","./src/lib/io/file.ts","./src/lib/io/pathbuilder.test.ts","./src/lib/io/pathbuilder.ts","./src/lib/llm/client.test.ts","./src/lib/llm/client.ts","./src/lib/llm/types.ts","./src/lib/map/distance.ts","./src/lib/map/fog.ts","./src/lib/map/grid.ts","./src/lib/map/index.ts","./src/lib/map/map.test.ts","./src/lib/map/projection.test.ts","./src/lib/map/projection.ts","./src/lib/map/shapes.ts","./src/lib/map/types.ts","./src/lib/map/viewport.test.ts","./src/lib/map/viewport.ts","./src/lib/map/vision.test.ts","./src/lib/map/vision.ts","./src/lib/mechanics/cast.ts","./src/lib/mechanics/conditionEffects.ts","./src/lib/mechanics/creatureState.test.ts","./src/lib/mechanics/creatureState.ts","./src/lib/mechanics/deathSaves.ts","./src/lib/mechanics/enforce.test.ts","./src/lib/mechanics/index.ts","./src/lib/mechanics/resources.ts","./src/lib/mechanics/result.ts","./src/lib/mechanics/types.ts","./src/lib/mechanics/normalize/armor.ts","./src/lib/mechanics/normalize/monsterDefenses.ts","./src/lib/mechanics/normalize/normalize.test.ts","./src/lib/mechanics/normalize/spell.ts","./src/lib/rules/abilities.ts","./src/lib/rules/abilityGen.test.ts","./src/lib/rules/abilityGen.ts","./src/lib/rules/conditions.ts","./src/lib/rules/depth.test.ts","./src/lib/rules/index.ts","./src/lib/rules/multiclass.test.ts","./src/lib/rules/progression.test.ts","./src/lib/rules/progression.ts","./src/lib/rules/rest.ts","./src/lib/rules/rules.test.ts","./src/lib/rules/types.ts","./src/lib/rules/dnd5e/index.ts","./src/lib/rules/dnd5e/progression.ts","./src/lib/rules/dnd5e/skills.ts","./src/lib/rules/pf2e/abilities.test.ts","./src/lib/rules/pf2e/abilities.ts","./src/lib/rules/pf2e/index.ts","./src/lib/rules/pf2e/progression.ts","./src/lib/rules/pf2e/skills.ts","./src/lib/ruleset/normalize.test.ts","./src/lib/ruleset/normalize.ts","./src/lib/schemas/campaign.ts","./src/lib/schemas/character.ts","./src/lib/schemas/common.ts","./src/lib/schemas/dice.ts","./src/lib/schemas/encounter.ts","./src/lib/schemas/index.ts","./src/lib/schemas/sessionLog.ts","./src/lib/schemas/world.ts","./src/lib/sync/index.ts","./src/lib/sync/messages.test.ts","./src/lib/sync/messages.ts","./src/lib/sync/playerLink.test.ts","./src/lib/sync/playerLink.ts","./src/lib/sync/snapshot.ts","./src/lib/sync/wsSync.ts","./src/lib/vtt/uvtt.test.ts","./src/lib/vtt/uvtt.ts","./src/stores/assistantStore.ts","./src/stores/connectivityStore.ts","./src/stores/macroStore.ts","./src/stores/playerSessionStore.ts","./src/stores/rollStore.ts","./src/stores/sessionStore.ts","./src/stores/uiStore.ts","./vitest.setup.ts"],"version":"5.9.3"} \ No newline at end of file