Add Container class with lock/trap detection, corpse drops, and numbered duplicate corpses
This commit is contained in:
221
spell_list.py
Normal file
221
spell_list.py
Normal file
@@ -0,0 +1,221 @@
|
||||
from enum_list import SpellSchool, SaveType, DamageType
|
||||
|
||||
|
||||
class Spell:
|
||||
"""Base class for all spells, built from the D&D 5e SRD."""
|
||||
def __init__(self, name, level, school, casting_time, range_, components,
|
||||
duration, description, classes, damage=None, dmg_type=None,
|
||||
scaling_damage=None, save=SaveType.NONE, heal=None,
|
||||
ritual=False, concentration=False):
|
||||
self.name = name
|
||||
self.level = level # 0 = cantrip
|
||||
self.school = school
|
||||
self.casting_time = casting_time
|
||||
self.range = range_
|
||||
self.components = components
|
||||
self.duration = duration
|
||||
self.description = description
|
||||
self.classes = classes # list of class names that can cast this, e.g. ["Wizard"]
|
||||
self.damage = damage # base damage dice string e.g. "1d10"
|
||||
self.dmg_type = dmg_type
|
||||
self.scaling_damage = scaling_damage # dice added per extra slot level/character level, if any
|
||||
self.save = save
|
||||
self.heal = heal # healing dice string, e.g. "1d8"
|
||||
self.ritual = ritual
|
||||
self.concentration = concentration
|
||||
|
||||
def __repr__(self):
|
||||
level_str = "Cantrip" if self.level == 0 else f"Level {self.level}"
|
||||
tags = []
|
||||
if self.ritual:
|
||||
tags.append("Ritual")
|
||||
if self.concentration:
|
||||
tags.append("Concentration")
|
||||
tag_str = f" ({', '.join(tags)})" if tags else ""
|
||||
return (f"{self.name} - {level_str} {self.school.name}{tag_str}\n"
|
||||
f"=====\n"
|
||||
f"Casting Time: {self.casting_time}\n"
|
||||
f"Range: {self.range}\n"
|
||||
f"Components: {self.components}\n"
|
||||
f"Duration: {self.duration}\n\n"
|
||||
f"{self.description}")
|
||||
|
||||
|
||||
# ----- Wizard Cantrips -----
|
||||
fire_bolt = Spell(
|
||||
name="Fire Bolt", level=0, school=SpellSchool.Evocation,
|
||||
casting_time="1 action", range_="120 feet", components="V, S",
|
||||
duration="Instantaneous",
|
||||
description="You hurl a mote of fire at a creature or object within range. Make a ranged "
|
||||
"spell attack against the target. On a hit, the target takes fire damage. "
|
||||
"A flammable object hit by this spell ignites if it isn't being worn or carried.",
|
||||
classes=["Wizard"], damage="1d10", dmg_type=DamageType.Fire,
|
||||
scaling_damage={5: "2d10", 11: "3d10", 17: "4d10"}
|
||||
)
|
||||
|
||||
ray_of_frost = Spell(
|
||||
name="Ray of Frost", level=0, school=SpellSchool.Evocation,
|
||||
casting_time="1 action", range_="60 feet", components="V, S",
|
||||
duration="Instantaneous",
|
||||
description="A frigid beam of blue-white light streaks toward a creature within range. "
|
||||
"Make a ranged spell attack against the target. On a hit, it takes cold "
|
||||
"damage and its speed is reduced by 10 feet until the start of your next turn.",
|
||||
classes=["Wizard"], damage="1d8", dmg_type=DamageType.Cold,
|
||||
scaling_damage={5: "2d8", 11: "3d8", 17: "4d8"}
|
||||
)
|
||||
|
||||
mage_hand = Spell(
|
||||
name="Mage Hand", level=0, school=SpellSchool.Conjuration,
|
||||
casting_time="1 action", range_="30 feet", components="V, S",
|
||||
duration="1 minute",
|
||||
description="A spectral, floating hand appears at a point you choose within range. "
|
||||
"The hand lasts for the duration and can manipulate objects, open unlocked "
|
||||
"containers, and carry up to 10 pounds.",
|
||||
classes=["Wizard"]
|
||||
)
|
||||
|
||||
prestidigitation = Spell(
|
||||
name="Prestidigitation", level=0, school=SpellSchool.Transmutation,
|
||||
casting_time="1 action", range_="10 feet", components="V, S",
|
||||
duration="Up to 1 hour",
|
||||
description="This spell is a minor magical trick: create a harmless sensory effect, "
|
||||
"light or snuff a small flame, clean or soil an object, chill/warm/flavor "
|
||||
"a small amount of nonliving material, or make a small mark or symbol appear.",
|
||||
classes=["Wizard"]
|
||||
)
|
||||
|
||||
# ----- Wizard Level 1 Spells -----
|
||||
magic_missile = Spell(
|
||||
name="Magic Missile", level=1, school=SpellSchool.Evocation,
|
||||
casting_time="1 action", range_="120 feet", components="V, S",
|
||||
duration="Instantaneous",
|
||||
description="You create three glowing darts of magical force. Each dart hits a creature "
|
||||
"of your choice that you can see within range, dealing force damage. The "
|
||||
"darts all strike simultaneously and automatically hit - no attack roll needed.",
|
||||
classes=["Wizard"], damage="3d4+3", dmg_type=DamageType.Force,
|
||||
scaling_damage={"per_slot_level": "1d4+1"}
|
||||
)
|
||||
|
||||
shield = Spell(
|
||||
name="Shield", level=1, school=SpellSchool.Abjuration,
|
||||
casting_time="1 reaction", range_="Self", components="V, S",
|
||||
duration="1 round",
|
||||
description="An invisible barrier of magical force appears and protects you. Until the "
|
||||
"start of your next turn, you have a +5 bonus to AC and you take no damage "
|
||||
"from Magic Missile.",
|
||||
classes=["Wizard"]
|
||||
)
|
||||
|
||||
burning_hands = Spell(
|
||||
name="Burning Hands", level=1, school=SpellSchool.Evocation,
|
||||
casting_time="1 action", range_="Self (15-foot cone)", components="V, S",
|
||||
duration="Instantaneous",
|
||||
description="A thin sheet of flames shoots forth from your outstretched fingertips. Each "
|
||||
"creature in a 15-foot cone must make a Dexterity saving throw. A creature "
|
||||
"takes fire damage on a failed save, or half as much on a successful one.",
|
||||
classes=["Wizard"], damage="3d6", dmg_type=DamageType.Fire, save=SaveType.Dexterity,
|
||||
scaling_damage={"per_slot_level": "1d6"}
|
||||
)
|
||||
|
||||
detect_magic = Spell(
|
||||
name="Detect Magic", level=1, school=SpellSchool.Divination,
|
||||
casting_time="1 action", range_="Self", components="V, S",
|
||||
duration="Concentration, up to 10 minutes",
|
||||
description="For the duration, you sense the presence of magic within 30 feet of you. "
|
||||
"If you sense magic in this way, you can use your action to see a faint "
|
||||
"aura around any visible creature or object that bears magic.",
|
||||
classes=["Wizard", "Cleric"], ritual=True, concentration=True
|
||||
)
|
||||
|
||||
# ----- Cleric Cantrips -----
|
||||
sacred_flame = Spell(
|
||||
name="Sacred Flame", level=0, school=SpellSchool.Evocation,
|
||||
casting_time="1 action", range_="60 feet", components="V, S",
|
||||
duration="Instantaneous",
|
||||
description="Flame-like radiance descends on a creature that you can see within range. "
|
||||
"The target must succeed on a Dexterity saving throw or take radiant damage. "
|
||||
"The target gains no benefit from cover for this saving throw.",
|
||||
classes=["Cleric"], damage="1d8", dmg_type=DamageType.Radiant, save=SaveType.Dexterity,
|
||||
scaling_damage={5: "2d8", 11: "3d8", 17: "4d8"}
|
||||
)
|
||||
|
||||
guidance = Spell(
|
||||
name="Guidance", level=0, school=SpellSchool.Divination,
|
||||
casting_time="1 action", range_="Touch", components="V, S",
|
||||
duration="Concentration, up to 1 minute",
|
||||
description="You touch one willing creature. Once before the spell ends, the target "
|
||||
"can roll a d4 and add the number rolled to one ability check of its choice.",
|
||||
classes=["Cleric"], concentration=True
|
||||
)
|
||||
|
||||
spare_the_dying = Spell(
|
||||
name="Spare the Dying", level=0, school=SpellSchool.Necromancy,
|
||||
casting_time="1 action", range_="Touch", components="V, S",
|
||||
duration="Instantaneous",
|
||||
description="You touch a living creature that has 0 hit points. The creature becomes "
|
||||
"stable. This spell has no effect on undead or constructs.",
|
||||
classes=["Cleric"]
|
||||
)
|
||||
|
||||
# ----- Cleric Level 1 Spells -----
|
||||
cure_wounds = Spell(
|
||||
name="Cure Wounds", level=1, school=SpellSchool.Evocation,
|
||||
casting_time="1 action", range_="Touch", components="V, S",
|
||||
duration="Instantaneous",
|
||||
description="A creature you touch regains a number of hit points.",
|
||||
classes=["Cleric"], heal="1d8", scaling_damage={"per_slot_level": "1d8"}
|
||||
)
|
||||
|
||||
bless = Spell(
|
||||
name="Bless", level=1, school=SpellSchool.Enchantment,
|
||||
casting_time="1 action", range_="30 feet", components="V, S, M",
|
||||
duration="Concentration, up to 1 minute",
|
||||
description="You bless up to three creatures of your choice within range. Whenever a "
|
||||
"target makes an attack roll or a saving throw before the spell ends, the "
|
||||
"target can add 1d4 to the attack roll or saving throw.",
|
||||
classes=["Cleric"], concentration=True
|
||||
)
|
||||
|
||||
guiding_bolt = Spell(
|
||||
name="Guiding Bolt", level=1, school=SpellSchool.Evocation,
|
||||
casting_time="1 action", range_="120 feet", components="V, S",
|
||||
duration="1 round",
|
||||
description="A flash of light streaks toward a creature of your choice within range. "
|
||||
"Make a ranged spell attack against the target. On a hit, the target takes "
|
||||
"radiant damage, and the next attack roll made against this target before "
|
||||
"the end of your next turn has advantage.",
|
||||
classes=["Cleric"], damage="4d6", dmg_type=DamageType.Radiant,
|
||||
scaling_damage={"per_slot_level": "1d6"}
|
||||
)
|
||||
|
||||
healing_word = Spell(
|
||||
name="Healing Word", level=1, school=SpellSchool.Evocation,
|
||||
casting_time="1 bonus action", range_="60 feet", components="V",
|
||||
duration="Instantaneous",
|
||||
description="A creature of your choice that you can see within range regains hit points.",
|
||||
classes=["Cleric"], heal="1d4", scaling_damage={"per_slot_level": "1d4"}
|
||||
)
|
||||
|
||||
|
||||
# Master lookup: {class_name: {spell_level: [Spell, ...]}}
|
||||
SPELL_LISTS = {
|
||||
"Wizard": {
|
||||
0: [fire_bolt, ray_of_frost, mage_hand, prestidigitation],
|
||||
1: [magic_missile, shield, burning_hands, detect_magic],
|
||||
},
|
||||
"Cleric": {
|
||||
0: [sacred_flame, guidance, spare_the_dying],
|
||||
1: [cure_wounds, bless, guiding_bolt, healing_word, detect_magic],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def get_spell_by_name(name):
|
||||
"""Looks up a Spell object across all class lists by (case-insensitive) name."""
|
||||
name = name.lower().strip()
|
||||
for class_spells in SPELL_LISTS.values():
|
||||
for level_spells in class_spells.values():
|
||||
for spell in level_spells:
|
||||
if spell.name.lower() == name:
|
||||
return spell
|
||||
return None
|
||||
Reference in New Issue
Block a user