from DnD_5e.weapons import Weapon
[docs]
class SimpleWeapon(Weapon):
"""Mostly used to determine if a character has proficiency with a weapon"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
[docs]
class MartialWeapon(Weapon):
"""Mostly used to determine if a character has proficiency with a weapon"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
[docs]
class MeleeWeapon(Weapon):
"""Weapon for melee attacks. MeleeWeapons may do ranged attacks, but they are primarily for melee"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
[docs]
class RangedWeapon(Weapon):
"""Weapon for ranged attacks"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
[docs]
class Club(SimpleWeapon, MeleeWeapon): # pragma: no cover
"""
Simple Melee Weapon
:Damage: 1d4 bludgeoning
:Melee range: 5
Properties: light
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Club"})
kwargs.update({"damage_dice": "1d4", "damage_type": "bludgeoning", "light": 1})
super().__init__(**kwargs)
[docs]
class Dagger(SimpleWeapon, MeleeWeapon): # pragma: no cover
"""
Simple Melee Weapon
:Damage: 1d4 piercing
:Melee range: 5
:Range: 20/60
:Properties: finesse, light
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Dagger"})
kwargs.update({"damage_dice": "1d4", "damage_type": "piercing", "finesse": 1, "light": 1, "melee_range": 5, "range": (20, 60)})
super().__init__(**kwargs)
[docs]
class Greatclub(SimpleWeapon, MeleeWeapon): # pragma: no cover
"""
Simple Melee Weapon
:Damage: 1d8 bludgeoning
:Melee range: 5
:Properties: two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Greatclub"})
kwargs.update({"damage_dice": "1d8", "damage_type": "bludgeoning", "two_handed": 1})
super().__init__(**kwargs)
[docs]
class Javelin(SimpleWeapon, MeleeWeapon): # pragma: no cover
"""
Simple Melee Weapon
:Damage: 1d6 piercing
:Melee range: 5
:Range: 30/120
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Javelin"})
kwargs.update({"damage_dice": "1d6", "damage_type": "piercing", "range": (30, 120), "melee_range": 5})
super().__init__(**kwargs)
[docs]
class LightHammer(SimpleWeapon, MeleeWeapon): # pragma: no cover
"""
Simple Melee Weapon
:Damage: 1d4 bludgeoning
:Melee range: 5
:Range: 20/60
:Properties: light
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Light Hammer"})
kwargs.update({"damage_dice": "1d4", "damage_type": "bludgeoning", "light": 1, "range": (20, 60), "melee_range": 5})
super().__init__(**kwargs)
[docs]
class Mace(SimpleWeapon, MeleeWeapon): # pragma: no cover
"""
Simple Melee Weapon
:Damage: 1d6 bludgeoning
:Melee range: 5
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Mace"})
kwargs.update({"damage_dice": "1d6", "damage_type": "bludgeoning"})
super().__init__(**kwargs)
[docs]
class Quarterstaff(SimpleWeapon, MeleeWeapon): # pragma: no cover
"""
Simple Melee Weapon
:Damage: 1d6 bludgeoning
:Versatile damage dice: 1d8
:Melee range: 5
:Properties: versatile
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Quarterstaff"})
kwargs.update({"damage_dice": "1d6", "damage_type": "bludgeoning", "versatile": "1d8"})
super().__init__(**kwargs)
[docs]
class Sickle(SimpleWeapon, MeleeWeapon): # pragma: no cover
"""
Simple Melee Weapon
:Damage: 1d4 slashing
:Melee range: 5
:Properties: light
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Sickle"})
kwargs.update({"damage_dice": "1d4", "damage_type": "slashing", "light": 1})
super().__init__(**kwargs)
[docs]
class Spear(SimpleWeapon, MeleeWeapon): # pragma: no cover
"""
Simple Melee Weapon
:Damage: 1d6 piercing
:Versatile damage dice: 1d8
:Melee range: 5
:Range: 20/60
:Properties: versatile
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Spear"})
kwargs.update({"damage_dice": "1d6", "damage_type": "piercing", "range": (20, 60), "melee_range": 5, "versatile": "1d8"})
super().__init__(**kwargs)
# Simple Ranged
[docs]
class LightCrossbow(SimpleWeapon, RangedWeapon): # pragma: no cover
"""
Simple Ranged Weapon
:Damage: 1d8 piercing
:Range: 80/320
:Properties: loading, two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Light Crossbow"})
kwargs.update({"damage_dice": "1d8", "damage_type": "piercing", "loading": 1, "two_handed": 1, "range": (80, 320)})
super().__init__(**kwargs)
[docs]
class Dart(SimpleWeapon, RangedWeapon): # pragma: no cover
"""
Simple Ranged Weapon
:Damage: 1d4 piercing
:Range: 20/60
:Properties: finesse
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Dart"})
kwargs.update({"damage_dice": "1d4", "damage_type": "piercing", "finesse": 1, "range": (20, 60)})
super().__init__(**kwargs)
[docs]
class Shortbow(SimpleWeapon, RangedWeapon): # pragma: no cover
"""
Simple Melee Weapon
:Damage: 1d6 piercing
:Range: 80/320
:Properties: two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Shortbow"})
kwargs.update({"damage_dice": "1d6", "damage_type": "piercing", "two_handed": 1, "range": (80, 320)})
super().__init__(**kwargs)
[docs]
class Sling(SimpleWeapon, RangedWeapon): # pragma: no cover
"""
Simple Ranged Weapon
:Damage: 1d4 bludgeoning
:Range: 30/120
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Sling"})
kwargs.update({"damage_dice": "1d4", "damage_type": "bludgeoning", "range": (30, 120)})
super().__init__(**kwargs)
# Martial Melee
[docs]
class Battleaxe(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d8 slashing
:Versatile damage dice: 1d10
:Melee range: 5
:Properties: versatile
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Battleaxe"})
kwargs.update({"damage_dice": "1d8", "damage_type": "slashing", "versatile": "1d10"})
super().__init__(**kwargs)
[docs]
class Flail(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d8 bludgeoning
:Melee range: 5
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Flail"})
kwargs.update({"damage_dice": "1d8", "damage_type": "bludgeoning"})
super().__init__(**kwargs)
[docs]
class Glaive(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d10 slashing
:Melee range: 10
:Properties: heavy, reach, two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Glaive"})
kwargs.update({"damage_dice": "1d10", "damage_type": "slashing", "heavy": 1, "reach": 1, "two_handed": 1})
super().__init__(**kwargs)
[docs]
class Greataxe(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d12 slashing
:Melee range: 5
:Properties: heavy, two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Greataxe"})
kwargs.update({"damage_dice": "1d12", "damage_type": "slashing", "heavy": 1, "two_handed": 1})
super().__init__(**kwargs)
[docs]
class Greatsword(MartialWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 2d6 slashing
:Melee range: 5
:Properties: heavy, two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Greatsword"})
kwargs.update({"damage_dice": "2d6", "damage_type": "slashing", "heavy": 1, "two_handed": 1})
super().__init__(**kwargs)
[docs]
class Halberd(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d10 slashing
:Melee range: 10
:Properties: heavy, reach, two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Halberd"})
kwargs.update({"damage_dice": "1d10", "damage_type": "slashing", "heavy": 1, "reach": 1, "two_handed": 1})
super().__init__(**kwargs)
[docs]
class Lance(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d12 piercing
:Melee range: 10
.. Note:: Lance has special rules
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Lance"})
kwargs.update({"damage_dice": "1d12", "damage_type": "piercing", "reach": 1})
super().__init__(**kwargs)
[docs]
class Longsword(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d8 slashing
:Versatile damage dice: 1d10
:Melee range: 5
:Properties: versatile
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Longsword"})
kwargs.update({"damage_dice": "1d8", "damage_type": "slashing", "versatile": "1d10"})
super().__init__(**kwargs)
[docs]
class Maul(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 2d6 bludgeoning
:Melee range: 5
:Properties: heavy, two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Maul"})
kwargs.update({"damage_dice": "2d6", "damage_type": "bludgeoning", "heavy": 1, "two_handed": 1})
super().__init__(**kwargs)
[docs]
class Morningstar(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d8 piercing
:Melee raange: 5
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Morningstar"})
kwargs.update({"damage_dice": "1d8", "damage_type": "piercing"})
super().__init__(**kwargs)
[docs]
class Pike(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d10 piercing
:Melee range: 10
:Properties: heavy, reach, two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Pike"})
kwargs.update({"damage_dice": "1d10", "damage_type": "piercing", "heavy": 1, "reach": 1, "two_handed": 1})
super().__init__(**kwargs)
[docs]
class Rapier(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d8 piercing
:Melee range: 5
:Properties: finesse
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Rapier"})
kwargs.update({"damage_dice": "1d8", "damage_type": "piercing", "finesse": 1})
super().__init__(**kwargs)
[docs]
class Scimitar(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d6 slashing
:Melee range: 5
:Properties: finesse, light
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Scimitar"})
kwargs.update({"damage_dice": "1d6", "damage_type": "slashing", "finesse": 1, "light": 1})
super().__init__(**kwargs)
[docs]
class Shortsword(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d6 piercing
:Melee range: 5
:Properties: finesse, light
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Shortsword"})
kwargs.update({"damage_dice": "1d6", "damage_type": "piercing", "finesse": 1, "light": 1})
super().__init__(**kwargs)
[docs]
class Trident(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d6 piercing
:Versatile damage dice: 1d8
:Melee range: 5
:Range: 20/60
:Properties: versatile
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Trident"})
kwargs.update({"damage_dice": "1d6", "damage_type": "piercing", "range": (20, 60), "melee_range": 5, "versatile": "1d8"})
super().__init__(**kwargs)
[docs]
class WarPick(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d8 piercing
:Melee range: 5
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "War Pick"})
kwargs.update({"damage_dice": "1d8", "damage_type": "piercing"})
super().__init__(**kwargs)
[docs]
class Warhammer(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d8 bludgeoning
:Versatile damage dice: 1d10
:Melee range: 5
:Properties: versatile
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Warhammer"})
kwargs.update({"damage_dice": "1d8", "damage_type": "bludgeoning", "versatile": "1d10"})
super().__init__(**kwargs)
[docs]
class Whip(MartialWeapon, MeleeWeapon): # pragma: no cover
"""
Martial Melee Weapon
:Damage: 1d4 slashing
:Melee range: 10
:Properties: finesse, reach
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Whip"})
kwargs.update({"damage_dice": "1d4", "damage_type": "slashing", "finesse": 1, "reach": 1})
super().__init__(**kwargs)
# Martial Ranged
[docs]
class Blowgun(MartialWeapon, RangedWeapon): # pragma: no cover
"""
Martial Ranged Weapon
:Damage: 1d1 piercing
:Range: 25/100
:Properties: loading
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Blowgun"})
kwargs.update({"damage_dice": "1d1", "damage_type": "piercing", "loading": 1, "range": (25, 100)})
super().__init__(**kwargs)
[docs]
class HandCrossbow(MartialWeapon, RangedWeapon): # pragma: no cover
"""
Martial Ranged Weapon
:Damage: 1d6
:Range: 30/120
:Properties: light, loading
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Hand Crossbow"})
kwargs.update({"damage_dice": "1d6", "damage_type": "piercing", "light": 1, "loading": 1, "range": (30, 120)})
super().__init__(**kwargs)
[docs]
class HeavyCrossbow(MartialWeapon, RangedWeapon): # pragma: no cover
"""
Martial Ranged Weapon
:Damage: 1d10 piercing
:Range: 100/400
:Properties: heavy, loading, two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Heavy Crossbow"})
kwargs.update({"damage_dice": "1d10", "damage_type": "piercing", "heavy": 1, "loading": 1, "two_handed": 1, "range": (100, 400)})
super().__init__(**kwargs)
[docs]
class Longbow(MartialWeapon, RangedWeapon): # pragma: no cover
"""
Martial Ranged Weapon
:Damage: 1d8 piercing
:Range: 150/600
:Properties: heavy, two_handed
"""
def __init__(self, **kwargs):
if not kwargs.get("name"):
kwargs.update({"name": "Longbow"})
kwargs.update({"damage_dice": "1d8", "damage_type": "piercing", "heavy": 1, "two_handed": 1, "range": (150, 600)})
super().__init__(**kwargs)
# Don't count Net
[docs]
def is_monk_weapon(weapon: Weapon) -> bool:
"""
Determine whether a given weapon is a Monk weapon.
Monk weapons are shortswords and Simple Melee Weapons that are not heavy or two_handed.
:param weapon: the Weapon to check
:type weapon: Weapon
:return: True if *weapon* is a Monk weapon, False otherwise
:rtype: bool
"""
# placed here instead of in weapons to avoid circular dependency
if not isinstance(weapon, Weapon):
return False
return isinstance(weapon, Shortsword) or (
isinstance(weapon, SimpleWeapon) and isinstance(weapon, MeleeWeapon) and not weapon.has_prop("two_handed")
and not weapon.has_prop("heavy"))