reimplementing inventories
This commit is contained in:
+79
-39
@@ -1,5 +1,19 @@
|
||||
from ttfrog.db.schema.container import Container
|
||||
from ttfrog.db.schema.item import Item, ItemType, Spell
|
||||
from ttfrog.db.schema import prototypes
|
||||
from ttfrog.db.schema.inventory import InventoryType
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
def test_spell_inventory(db, carl):
|
||||
with db.transaction():
|
||||
fireball = prototypes.BaseSpell(name="Fireball", level=3, concentration=False)
|
||||
db.add_or_update([fireball, carl])
|
||||
|
||||
assert carl.spells.add(fireball)
|
||||
db.add_or_update(carl)
|
||||
|
||||
assert not carl.equipment.add(fireball)
|
||||
assert fireball in carl.spells
|
||||
assert fireball not in carl.equipment
|
||||
|
||||
|
||||
def test_equipment_inventory(db, carl):
|
||||
@@ -8,21 +22,18 @@ def test_equipment_inventory(db, carl):
|
||||
db.add_or_update(carl)
|
||||
|
||||
# create some items
|
||||
ten_foot_pole = Item(name="10ft. Pole", item_type=ItemType.ITEM, consumable=False)
|
||||
fireball = Spell(name="Fireball", level=3, concentration=False)
|
||||
db.add_or_update([ten_foot_pole, fireball])
|
||||
ten_foot_pole = prototypes.BaseItem(name="10ft. Pole", item_type=prototypes.ItemType.ITEM, consumable=False)
|
||||
db.add_or_update(ten_foot_pole)
|
||||
|
||||
# add the pole to carl's equipment, and the spell to his spell list.
|
||||
assert carl.equipment.add(ten_foot_pole)
|
||||
assert carl.spells.add(fireball)
|
||||
|
||||
# can't mix and match inventory item types
|
||||
assert not carl.equipment.add(fireball)
|
||||
assert not carl.spells.add(ten_foot_pole)
|
||||
|
||||
# add two more 10 foot poles. You can never have too many.
|
||||
carl.equipment.add(ten_foot_pole)
|
||||
carl.equipment.add(ten_foot_pole)
|
||||
assert carl.equipment.add(ten_foot_pole)
|
||||
assert carl.equipment.add(ten_foot_pole)
|
||||
db.add_or_update(carl)
|
||||
|
||||
all_carls_poles = carl.equipment.get_all(ten_foot_pole)
|
||||
@@ -31,8 +42,6 @@ def test_equipment_inventory(db, carl):
|
||||
# check the "contains" logic
|
||||
assert ten_foot_pole in carl.equipment
|
||||
assert ten_foot_pole not in carl.spells
|
||||
assert fireball in carl.spells
|
||||
assert fireball not in carl.equipment
|
||||
|
||||
pole_one = all_carls_poles[0]
|
||||
|
||||
@@ -42,11 +51,6 @@ def test_equipment_inventory(db, carl):
|
||||
# can't equip it twice
|
||||
assert not pole_one.equip()
|
||||
|
||||
# can't prepare or cast an item
|
||||
assert not pole_one.prepare()
|
||||
assert not pole_one.unprepare()
|
||||
assert not pole_one.cast()
|
||||
|
||||
# not consumable or attunable
|
||||
assert not pole_one.consume()
|
||||
assert not pole_one.attune()
|
||||
@@ -60,6 +64,7 @@ def test_equipment_inventory(db, carl):
|
||||
# drop one pole
|
||||
assert carl.equipment.remove(pole_one)
|
||||
assert ten_foot_pole in carl.equipment
|
||||
return
|
||||
|
||||
# drop the remaining poles
|
||||
assert carl.equipment.remove(all_carls_poles[1])
|
||||
@@ -72,10 +77,12 @@ def test_equipment_inventory(db, carl):
|
||||
|
||||
def test_inventory_bundles(db, carl):
|
||||
with db.transaction():
|
||||
arrows = Item(name="Arrows", item_type=ItemType.ITEM, consumable=True, count=20)
|
||||
arrows = prototypes.BaseItem(name="Arrows", item_type=prototypes.ItemType.ITEM, consumable=True, count=20)
|
||||
db.add_or_update([carl, arrows])
|
||||
quiver = carl.equipment.add(arrows)
|
||||
db.add_or_update(carl)
|
||||
db.add_or_update([carl, quiver])
|
||||
|
||||
assert quiver.container == carl.equipment
|
||||
|
||||
# full quiver
|
||||
assert arrows in carl.equipment
|
||||
@@ -98,8 +105,8 @@ def test_inventory_bundles(db, carl):
|
||||
|
||||
def test_spell_slots(db, carl, wizard):
|
||||
with db.transaction():
|
||||
prestidigitation = Spell(name="Prestidigitation", level=0, concentration=False)
|
||||
fireball = Spell(name="Fireball", level=3, concentration=False)
|
||||
prestidigitation = prototypes.BaseSpell(name="Prestidigitation", level=0, concentration=False)
|
||||
fireball = prototypes.BaseSpell(name="Fireball", level=3, concentration=False)
|
||||
db.add_or_update([carl, prestidigitation, fireball])
|
||||
|
||||
carl.spells.add(prestidigitation)
|
||||
@@ -160,45 +167,79 @@ def test_spell_slots(db, carl, wizard):
|
||||
|
||||
def test_containers(db, carl):
|
||||
with db.transaction():
|
||||
ten_foot_pole = Item(name="10ft. Pole")
|
||||
rope = Item(name="50 ft. of Rope", consumable=True, count=50)
|
||||
bag_of_holding = Container(name="Bag of Holding")
|
||||
db.add_or_update([carl, ten_foot_pole, rope, bag_of_holding])
|
||||
ten_foot_pole = prototypes.BaseItem(name="10ft. Pole")
|
||||
coil_of_rope = prototypes.BaseItem(name="50 ft. of Rope", consumable=True, count=50)
|
||||
bag_of_holding = prototypes.BaseItem(name="Bag of Holding", inventory_type=InventoryType.EQUIPMENT)
|
||||
db.add_or_update([ten_foot_pole, coil_of_rope, bag_of_holding])
|
||||
|
||||
pole = carl.equipment.add(ten_foot_pole)
|
||||
rope = carl.equipment.add(coil_of_rope)
|
||||
bag = carl.equipment.add(bag_of_holding)
|
||||
db.add_or_update(carl)
|
||||
|
||||
# verify the bag of holding's inventory is created automatically.
|
||||
assert bag.inventory_type is not None
|
||||
assert bag.inventory is not None
|
||||
|
||||
# the existing instances are found using the get() method
|
||||
assert carl.equipment.get(bag_of_holding) == bag
|
||||
assert carl.equipment.get(ten_foot_pole) == pole
|
||||
assert carl.equipment.get(coil_of_rope) == rope
|
||||
|
||||
# backreferences are populated correctly
|
||||
assert pole.container == carl.equipment
|
||||
|
||||
# add some items to the bag of holding
|
||||
assert bag_of_holding.add(ten_foot_pole)
|
||||
assert bag_of_holding.add(rope)
|
||||
db.add_or_update(bag_of_holding)
|
||||
assert pole.move_to(bag)
|
||||
assert rope.move_to(bag)
|
||||
|
||||
pole_from_bag = bag_of_holding.get(ten_foot_pole)
|
||||
rope_from_bag = bag_of_holding.get(rope)
|
||||
assert pole.container.id == bag.inventory.id
|
||||
assert pole.container == bag.inventory
|
||||
assert pole in bag.inventory
|
||||
assert pole in bag
|
||||
|
||||
assert pole_from_bag.item == ten_foot_pole
|
||||
assert pole_from_bag in bag_of_holding
|
||||
assert pole_from_bag not in carl.equipment
|
||||
assert pole not in carl.equipment.contents
|
||||
assert pole.container == bag.inventory
|
||||
|
||||
# add the bag of holding to carl's equipment
|
||||
assert carl.equipment.add(bag_of_holding)
|
||||
db.add_or_update(bag_of_holding)
|
||||
pole_from_bag = bag.inventory.get(ten_foot_pole)
|
||||
rope_from_bag = bag.inventory.get(coil_of_rope)
|
||||
|
||||
assert pole_from_bag.prototype == ten_foot_pole
|
||||
assert pole_from_bag in bag
|
||||
|
||||
bag_inventory_size = 2 # one pole, one rope
|
||||
equipment_size = 1 # one bag
|
||||
|
||||
# one bag, one pole, one rope
|
||||
total_inventory_size = bag_inventory_size + equipment_size
|
||||
|
||||
pprint(list(carl.equipment.all_contents))
|
||||
|
||||
assert len(list(bag.inventory.contents)) == bag_inventory_size
|
||||
assert len(list(carl.equipment.contents)) == equipment_size
|
||||
assert len(list(carl.equipment.all_contents)) == total_inventory_size
|
||||
|
||||
# nested containers!
|
||||
assert pole_from_bag in carl.equipment
|
||||
assert rope_from_bag in carl.equipment
|
||||
|
||||
# test equality of mappings
|
||||
carls_bag = carl.equipment.get(bag_of_holding)
|
||||
carls_pole = carl.equipment.get(ten_foot_pole)
|
||||
carls_rope = carl.equipment.get(rope)
|
||||
carls_rope = carl.equipment.get(coil_of_rope)
|
||||
assert carls_pole == pole_from_bag
|
||||
assert carls_rope == rope_from_bag
|
||||
|
||||
# use some rope
|
||||
carls_rope.consume(10)
|
||||
assert carls_rope.consume(10)
|
||||
assert carls_rope.count == 40
|
||||
|
||||
# move the rope out of the bag of holding, but not the pole
|
||||
assert carls_rope in carls_bag
|
||||
assert carls_rope.move_to(carl.equipment)
|
||||
assert carls_rope not in carls_bag
|
||||
|
||||
assert carls_pole in carls_bag
|
||||
db.add_or_update(carl)
|
||||
|
||||
# get the db record anew, in case the in-memory representation isn't
|
||||
# what's recorded in the database. Then make sure we didn't break
|
||||
@@ -213,6 +254,5 @@ def test_containers(db, carl):
|
||||
|
||||
# use the rest of the rope
|
||||
assert carls_rope.consume(40) == 0
|
||||
print(rope_from_bag.inventory)
|
||||
assert rope_from_bag not in carl.equipment
|
||||
assert rope_from_bag not in carl.equipment.get(bag_of_holding)
|
||||
|
||||
+14
-15
@@ -1,6 +1,7 @@
|
||||
from ttfrog.db.schema import prototypes
|
||||
from ttfrog.db.schema.constants import DamageType, Defenses
|
||||
from ttfrog.db.schema.item import Armor, Item, ItemProperty, Rarity, RechargeTime, Shield, Weapon
|
||||
from ttfrog.db.schema.modifiers import Modifier
|
||||
from ttfrog.db.schema.prototypes import Weapon
|
||||
|
||||
|
||||
def test_weapons(db):
|
||||
@@ -28,7 +29,6 @@ def test_weapons(db):
|
||||
attack_range=20,
|
||||
attack_range_long=60,
|
||||
)
|
||||
|
||||
db.add_or_update([longbow, dagger])
|
||||
|
||||
assert longbow.martial
|
||||
@@ -42,7 +42,7 @@ def test_weapons(db):
|
||||
|
||||
def test_charges(db, carl):
|
||||
with db.transaction():
|
||||
for_the_lulz = ItemProperty(
|
||||
for_the_lulz = prototypes.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
|
||||
@@ -52,10 +52,7 @@ def test_charges(db, carl):
|
||||
charge_cost=2,
|
||||
)
|
||||
|
||||
# from sqlalchemy.orm import relationship
|
||||
# help(relationship)
|
||||
|
||||
dagger_of_lulz = Weapon(
|
||||
dagger_of_lulz = prototypes.Weapon(
|
||||
name="Dagger of Lulz",
|
||||
description="This magical dagger has 6 charges. It regains 1d6 charges after a short rest.",
|
||||
damage_die="1d4",
|
||||
@@ -68,9 +65,9 @@ def test_charges(db, carl):
|
||||
attack_range_long=60,
|
||||
magical=True,
|
||||
charges=6,
|
||||
recharge_time=RechargeTime.SHORT_REST,
|
||||
recharge_time=prototypes.RechargeTime.SHORT_REST,
|
||||
recharge_amount="1d6",
|
||||
rarity=Rarity["Very Rare"],
|
||||
rarity=prototypes.Rarity["Very Rare"],
|
||||
requires_attunement=True,
|
||||
properties=[for_the_lulz],
|
||||
)
|
||||
@@ -100,8 +97,10 @@ def test_charges(db, carl):
|
||||
|
||||
|
||||
def test_nocharges(db, carl):
|
||||
smiles = ItemProperty(name="Smile!", description="The target grins for one minute.", charge_cost=None)
|
||||
wand_of_unlimited_smiles = Item(name="Wand of Unlimited Smiles", description="description", properties=[smiles])
|
||||
smiles = prototypes.ItemProperty(name="Smile!", description="The target grins for one minute.", charge_cost=None)
|
||||
wand_of_unlimited_smiles = prototypes.BaseItem(
|
||||
name="Wand of Unlimited Smiles", description="description", properties=[smiles]
|
||||
)
|
||||
db.add_or_update(wand_of_unlimited_smiles)
|
||||
|
||||
carl.equipment.add(wand_of_unlimited_smiles)
|
||||
@@ -115,13 +114,13 @@ def test_nocharges(db, carl):
|
||||
|
||||
def test_attunement(db, carl):
|
||||
with db.transaction():
|
||||
helm = Armor(
|
||||
helm = prototypes.Armor(
|
||||
name="Iron Helm",
|
||||
rarity=Rarity.Common,
|
||||
rarity=prototypes.Rarity.Common,
|
||||
)
|
||||
helm.add_modifier(Modifier("+1 AC (helmet)", target="armor_class", relative_value=1, stacks=True))
|
||||
|
||||
shield = Shield(
|
||||
shield = prototypes.Shield(
|
||||
name="Shield of Missile Attraction",
|
||||
description="""
|
||||
While holding this shield, you have resistance to damage from ranged weapon attacks.
|
||||
@@ -130,7 +129,7 @@ def test_attunement(db, carl):
|
||||
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,
|
||||
rarity=prototypes.Rarity.Rare,
|
||||
requires_attunement=True,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user