tabletop-frog/test/test_items.py
2024-08-29 15:14:47 -07:00

156 lines
5.3 KiB
Python

from ttfrog.db.schema.constants import DamageType, Defenses
from ttfrog.db.schema.item import Armor, ItemProperty, Rarity, RechargeTime, Shield, Weapon
from ttfrog.db.schema.modifiers import Modifier
def test_weapons(db):
with db.transaction():
longbow = Weapon(
name="longbow",
damage_die="1d6",
damage_type=DamageType.piercing,
martial=True,
two_handed=True,
ammunition=True,
targets=1,
attack_range=150,
attack_range_long=600,
)
dagger = Weapon(
name="Dagger",
damage_die="1d4",
damage_type=DamageType.slashing,
melee=True,
finesse=True,
light=True,
thrown=True,
attack_range=20,
attack_range_long=60,
)
db.add_or_update([longbow, dagger])
assert longbow.martial
assert longbow.ranged
assert not longbow.melee
assert not dagger.martial
assert dagger.ranged
assert dagger.melee
def test_charges(db, carl):
with db.transaction():
for_the_lulz = ItemProperty(
name="For the Lulz",
description="""
On a hit against a creature with a mouth, spend one charge to force the target to roll a DC 13 Wisdom
saving throw. On a failure, the target is forced to grin for one minute. While grinning, the target
cannot speak. The target can repeat the saving throw at the start of their turn."
""",
charge_cost=1,
)
# from sqlalchemy.orm import relationship
# help(relationship)
dagger_of_lulz = Weapon(
name="Dagger of Lulz",
description="This magical dagger has 6 charges. It regains 1d6 charges after a short rest.",
damage_die="1d4",
damage_type=DamageType.slashing,
melee=True,
finesse=True,
light=True,
thrown=True,
attack_range=20,
attack_range_long=60,
magical=True,
charges=6,
recharge_time=RechargeTime.SHORT_REST,
recharge_amount="1d6",
rarity=Rarity["Very Rare"],
requires_attunement=True,
properties=[for_the_lulz],
)
db.add_or_update([carl, dagger_of_lulz])
assert for_the_lulz in dagger_of_lulz.properties
assert carl.equipment.add(dagger_of_lulz)
db.add_or_update(carl)
carls_dagger = carl.equipment.get(dagger_of_lulz)
assert carl.equip(carls_dagger)
assert carl.attune(carls_dagger)
assert len(carls_dagger.charges) == dagger_of_lulz.charges == 6
assert len(carls_dagger.charges_available) == dagger_of_lulz.charges == 6
assert carls_dagger.use(for_the_lulz)
def test_attunement(db, carl):
with db.transaction():
helm = Armor(
name="Iron Helm",
rarity=Rarity.Common,
)
helm.add_modifier(Modifier("+1 AC (helmet)", target="armor_class", relative_value=1, stacks=True))
shield = Shield(
name="Shield of Missile Attraction",
description="""
While holding this shield, you have resistance to damage from ranged weapon attacks.
**Curse.** This shield is cursed. Attuning to it curses you until you are targeted by the remove curse spell
or similar magic. Removing the shield fails to end the curse on you. Whenever a ranged weapon attack is made
against a target within 10 feet of you, the curse causes you to become the target instead.
""",
rarity=Rarity.Rare,
requires_attunement=True,
)
plus_two_ac = Modifier("+2 AC (Shield", target="armor_class", relative_value=2, stacks=True)
ranged_resistance = Modifier(
"Resistance to Damage From Ranged Weapon Attacks (Shield of Missle Attraction)",
target=DamageType.ranged_weapon_attacks,
new_value=Defenses.resistant,
requires_attunement=True,
)
shield.add_modifier(plus_two_ac)
shield.add_modifier(ranged_resistance)
db.add_or_update([carl, helm, shield])
assert carl.equipment.add(shield)
assert carl.equipment.add(helm)
db.add_or_update(carl)
carls_shield = carl.equipment.get(shield)
assert carl.armor_class == 10
assert len(carl.attuned_items) == 0
carl.equip(carls_shield)
assert plus_two_ac in carl.modifiers["armor_class"]
assert ranged_resistance not in carl.modifiers[DamageType.ranged_weapon_attacks]
assert carl.armor_class == 12
assert carls_shield not in carl.attuned_items
carl.attune(carls_shield)
assert carl.armor_class == 12
assert plus_two_ac in carl.modifiers["armor_class"]
assert ranged_resistance in carl.modifiers[DamageType.ranged_weapon_attacks]
assert carls_shield in carl.attuned_items
assert carl.equip(carl.equipment.get(helm))
assert carl.armor_class == 13
assert carl.unattune(carls_shield)
assert carl.armor_class == 13
assert ranged_resistance not in carl.modifiers[DamageType.ranged_weapon_attacks]
assert carl.unequip(carls_shield)
assert carl.armor_class == 11