Changed equipment behaviour, now equipped items stay in the inventory

This commit is contained in:
Nicolas Margulies 2021-01-10 22:15:32 +01:00
parent 44b967625c
commit 88471f4361
4 changed files with 51 additions and 68 deletions

View File

@ -12,16 +12,19 @@ class Item(Entity):
""" """
A class for items. A class for items.
""" """
held: bool
held_by: Optional[InventoryHolder] held_by: Optional[InventoryHolder]
price: int price: int
def __init__(self, held: bool = False, def __init__(self, equipped: bool = False,
held_by: Optional[InventoryHolder] = None, held_by: Optional[InventoryHolder] = None,
hold_slot: str = "equipped_secondary",
price: int = 2, *args, **kwargs): price: int = 2, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.held = held
self.held_by = held_by self.held_by = held_by
self.equipped = equipped
self.hold_slot = hold_slot
if equipped:
self.equip()
self.price = price self.price = price
@property @property
@ -35,11 +38,11 @@ class Item(Entity):
""" """
The item is dropped from the inventory onto the floor. The item is dropped from the inventory onto the floor.
""" """
if self.held: if self.held_by is not None:
self.unequip()
self.held_by.remove_from_inventory(self) self.held_by.remove_from_inventory(self)
self.held_by.map.add_entity(self) self.held_by.map.add_entity(self)
self.move(self.held_by.y, self.held_by.x) self.move(self.held_by.y, self.held_by.x)
self.held = False
self.held_by = None self.held_by = None
def use(self) -> None: def use(self) -> None:
@ -52,28 +55,41 @@ class Item(Entity):
Indicates what should be done when the item is thrown. Indicates what should be done when the item is thrown.
""" """
def on_equip(self) -> None:
"""
Indicates a special behaviour when equipping
"""
def on_unequip(self) -> None:
"""
Indicates a special behaviour when unequipping
"""
def equip(self) -> None: def equip(self) -> None:
""" """
Indicates what should be done when the item is equipped. Indicates what should be done when the item is equipped.
""" """
# Other objects are only equipped as secondary. # Other objects are only equipped as secondary.
if self.held_by.equipped_secondary: if not self.equipped:
self.held_by.equipped_secondary.unequip() if getattr(self.held_by, self.hold_slot):
self.held_by.remove_from_inventory(self) getattr(self.held_by, self.hold_slot).unequip()
self.held_by.equipped_secondary = self self.equipped = True
setattr(self.held_by, self.hold_slot, self)
self.on_equip()
def unequip(self) -> None: def unequip(self) -> None:
""" """
Indicates what should be done when the item is unequipped. Indicates what should be done when the item is unequipped.
""" """
self.held_by.remove_from_inventory(self) if self.equipped:
self.held_by.add_to_inventory(self) setattr(self.held_by, self.hold_slot, None)
self.equipped = False
self.on_unequip()
def hold(self, holder: InventoryHolder) -> None: def hold(self, holder: InventoryHolder) -> None:
""" """
The item is taken from the floor and put into the inventory. The item is taken from the floor and put into the inventory.
""" """
self.held = True
self.held_by = holder self.held_by = holder
self.held_by.map.remove_entity(self) self.held_by.map.remove_entity(self)
holder.add_to_inventory(self) holder.add_to_inventory(self)
@ -83,7 +99,7 @@ class Item(Entity):
Saves the state of the item into a dictionary. Saves the state of the item into a dictionary.
""" """
d = super().save_state() d = super().save_state()
d["held"] = self.held d["equipped"] = self.equipped
return d return d
@staticmethod @staticmethod
@ -103,10 +119,12 @@ class Item(Entity):
inventory. inventory.
""" """
if for_free: if for_free:
self.unequip() if self.equipped else None
self.hold(buyer) self.hold(buyer)
seller.remove_from_inventory(self) seller.remove_from_inventory(self)
return True return True
elif buyer.hazel >= self.price: elif buyer.hazel >= self.price:
self.unequip() if self.equipped else None
self.hold(buyer) self.hold(buyer)
seller.remove_from_inventory(self) seller.remove_from_inventory(self)
buyer.change_hazel_balance(-self.price) buyer.change_hazel_balance(-self.price)
@ -169,7 +187,7 @@ class Bomb(Item):
""" """
When the bomb is used, it is thrown and then it explodes. When the bomb is used, it is thrown and then it explodes.
""" """
if self.held: if self.held_by is not None:
self.owner = self.held_by self.owner = self.held_by
super().drop() super().drop()
self.exploding = True self.exploding = True
@ -236,7 +254,7 @@ class Weapon(Item):
damage: int damage: int
def __init__(self, damage: int = 3, *args, **kwargs): def __init__(self, damage: int = 3, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(hold_slot="equipped_main", *args, **kwargs)
self.damage = damage self.damage = damage
@property @property
@ -251,20 +269,17 @@ class Weapon(Item):
d["damage"] = self.damage d["damage"] = self.damage
return d return d
def equip(self) -> None: def on_equip(self) -> None:
""" """
When a weapon is equipped, the player gains strength. When a weapon is equipped, the player gains strength.
""" """
self.held_by.remove_from_inventory(self)
self.held_by.equipped_main = self
self.held_by.strength += self.damage self.held_by.strength += self.damage
def unequip(self) -> None: def on_unequip(self) -> None:
""" """
Remove the strength earned by the weapon. Remove the strength earned by the weapon.
:return: :return:
""" """
super().unequip()
self.held_by.strength -= self.damage self.held_by.strength -= self.damage
@ -301,12 +316,10 @@ class Armor(Item):
return f"CON+{self.constitution}" if self.constitution \ return f"CON+{self.constitution}" if self.constitution \
else super().description else super().description
def equip(self) -> None: def on_equip(self) -> None:
super().equip()
self.held_by.constitution += self.constitution self.held_by.constitution += self.constitution
def unequip(self) -> None: def on_unequip(self) -> None:
super().unequip()
self.held_by.constitution -= self.constitution self.held_by.constitution -= self.constitution
def save_state(self) -> dict: def save_state(self) -> dict:
@ -332,13 +345,7 @@ class Helmet(Armor):
def __init__(self, name: str = "helmet", constitution: int = 2, def __init__(self, name: str = "helmet", constitution: int = 2,
price: int = 18, *args, **kwargs): price: int = 18, *args, **kwargs):
super().__init__(name=name, constitution=constitution, price=price, super().__init__(name=name, constitution=constitution, price=price,
*args, **kwargs) hold_slot="equipped_helmet", *args, **kwargs)
def equip(self) -> None:
if self.held_by.equipped_helmet:
self.held_by.equipped_helmet.unequip()
self.held_by.remove_from_inventory(self)
self.held_by.equipped_helmet = self
class Chestplate(Armor): class Chestplate(Armor):
@ -348,13 +355,7 @@ class Chestplate(Armor):
def __init__(self, name: str = "chestplate", constitution: int = 4, def __init__(self, name: str = "chestplate", constitution: int = 4,
price: int = 30, *args, **kwargs): price: int = 30, *args, **kwargs):
super().__init__(name=name, constitution=constitution, price=price, super().__init__(name=name, constitution=constitution, price=price,
*args, **kwargs) hold_slot="equipped_armor", *args, **kwargs)
def equip(self) -> None:
if self.held_by.equipped_armor:
self.held_by.equipped_armor.unequip()
self.held_by.remove_from_inventory(self)
self.held_by.equipped_armor = self
class BodySnatchPotion(Item): class BodySnatchPotion(Item):
@ -426,8 +427,7 @@ class Ring(Item):
("CRI", self.critical), ("XP", self.experience)] ("CRI", self.critical), ("XP", self.experience)]
return ", ".join(f"{key}+{value}" for key, value in fields if value) return ", ".join(f"{key}+{value}" for key, value in fields if value)
def equip(self) -> None: def on_equip(self) -> None:
super().equip()
self.held_by.maxhealth += self.maxhealth self.held_by.maxhealth += self.maxhealth
self.held_by.strength += self.strength self.held_by.strength += self.strength
self.held_by.intelligence += self.intelligence self.held_by.intelligence += self.intelligence
@ -437,8 +437,7 @@ class Ring(Item):
self.held_by.critical += self.critical self.held_by.critical += self.critical
self.held_by.xp_buff += self.experience self.held_by.xp_buff += self.experience
def unequip(self) -> None: def on_unequip(self) -> None:
super().unequip()
self.held_by.maxhealth -= self.maxhealth self.held_by.maxhealth -= self.maxhealth
self.held_by.strength -= self.strength self.held_by.strength -= self.strength
self.held_by.intelligence -= self.intelligence self.held_by.intelligence -= self.intelligence
@ -557,13 +556,6 @@ class LongRangeWeapon(Weapon):
self.held_by.map.logs.add_message(line) self.held_by.map.logs.add_message(line)
return (to_kill.y, to_kill.x) if to_kill else None return (to_kill.y, to_kill.x) if to_kill else None
def equip(self) -> None:
"""
Equip the weapon.
"""
self.held_by.remove_from_inventory(self)
self.held_by.equipped_main = self
@property @property
def stat(self) -> str: def stat(self) -> str:
""" """

View File

@ -837,6 +837,7 @@ class InventoryHolder(Entity):
for i in range(len(inventory)): for i in range(len(inventory)):
if isinstance(inventory[i], dict): if isinstance(inventory[i], dict):
inventory[i] = self.dict_to_item(inventory[i]) inventory[i] = self.dict_to_item(inventory[i])
inventory[i].held_by = self
return inventory return inventory
def dict_to_item(self, item_dict: dict) -> Entity: def dict_to_item(self, item_dict: dict) -> Entity:

View File

@ -155,9 +155,9 @@ class TestEntities(unittest.TestCase):
""" """
item = Item() item = Item()
self.map.add_entity(item) self.map.add_entity(item)
self.assertFalse(item.held) self.assertIsNone(item.held_by)
item.hold(self.player) item.hold(self.player)
self.assertTrue(item.held) self.assertEqual(item.held_by, self.player)
item.drop() item.drop()
self.assertEqual(item.y, 1) self.assertEqual(item.y, 1)
self.assertEqual(item.x, 6) self.assertEqual(item.x, 6)
@ -165,7 +165,6 @@ class TestEntities(unittest.TestCase):
# Pick up item # Pick up item
self.player.move_left() self.player.move_left()
self.player.move_right() self.player.move_right()
self.assertTrue(item.held)
self.assertEqual(item.held_by, self.player) self.assertEqual(item.held_by, self.player)
self.assertIn(item, self.player.inventory) self.assertIn(item, self.player.inventory)
self.assertNotIn(item, self.map.entities) self.assertNotIn(item, self.map.entities)
@ -208,7 +207,7 @@ class TestEntities(unittest.TestCase):
# The player can't hold the explosion # The player can't hold the explosion
explosion.hold(self.player) explosion.hold(self.player)
self.assertNotIn(explosion, self.player.inventory) self.assertNotIn(explosion, self.player.inventory)
self.assertFalse(explosion.held) self.assertIsNone(explosion.held_by)
# The explosion disappears after one tick # The explosion disappears after one tick
explosion.act(self.map) explosion.act(self.map)

View File

@ -491,10 +491,8 @@ class TestGame(unittest.TestCase):
# Drop an item # Drop an item
bomb = self.game.player.inventory[-1] bomb = self.game.player.inventory[-1]
self.assertEqual(self.game.inventory_menu.validate(), bomb) self.assertEqual(self.game.inventory_menu.validate(), bomb)
self.assertTrue(bomb.held)
self.assertEqual(bomb.held_by, self.game.player) self.assertEqual(bomb.held_by, self.game.player)
self.game.handle_key_pressed(KeyValues.DROP) self.game.handle_key_pressed(KeyValues.DROP)
self.assertFalse(bomb.held)
self.assertIsNone(bomb.held_by) self.assertIsNone(bomb.held_by)
self.assertIsNone(bomb.owner) self.assertIsNone(bomb.owner)
self.assertFalse(bomb.exploding) self.assertFalse(bomb.exploding)
@ -504,10 +502,8 @@ class TestGame(unittest.TestCase):
# Use the bomb # Use the bomb
bomb = self.game.player.inventory[-1] bomb = self.game.player.inventory[-1]
self.assertEqual(self.game.inventory_menu.validate(), bomb) self.assertEqual(self.game.inventory_menu.validate(), bomb)
self.assertTrue(bomb.held)
self.assertEqual(bomb.held_by, self.game.player) self.assertEqual(bomb.held_by, self.game.player)
self.game.handle_key_pressed(KeyValues.USE) self.game.handle_key_pressed(KeyValues.USE)
self.assertFalse(bomb.held)
self.assertIsNone(bomb.held_by) self.assertIsNone(bomb.held_by)
self.assertEqual(bomb.owner, self.game.player) self.assertEqual(bomb.owner, self.game.player)
self.assertTrue(bomb.exploding) self.assertTrue(bomb.exploding)
@ -660,42 +656,37 @@ class TestGame(unittest.TestCase):
sword.hold(self.game.player) sword.hold(self.game.player)
self.game.handle_key_pressed(KeyValues.EQUIP) self.game.handle_key_pressed(KeyValues.EQUIP)
self.assertEqual(self.game.player.equipped_main, sword) self.assertEqual(self.game.player.equipped_main, sword)
self.assertFalse(self.game.player.inventory)
# shield goes into the secondary equipment slot # shield goes into the secondary equipment slot
shield = Shield() shield = Shield()
shield.hold(self.game.player) shield.hold(self.game.player)
self.game.handle_key_pressed(KeyValues.EQUIP) shield.equip()
self.assertEqual(self.game.player.equipped_secondary, shield) self.assertEqual(self.game.player.equipped_secondary, shield)
self.assertFalse(self.game.player.inventory)
# helmet goes into the helmet slot # helmet goes into the helmet slot
helmet = Helmet() helmet = Helmet()
helmet.hold(self.game.player) helmet.hold(self.game.player)
self.game.handle_key_pressed(KeyValues.EQUIP) helmet.equip()
self.assertEqual(self.game.player.equipped_helmet, helmet) self.assertEqual(self.game.player.equipped_helmet, helmet)
self.assertFalse(self.game.player.inventory)
# helmet goes into the armor slot # helmet goes into the armor slot
chestplate = Chestplate() chestplate = Chestplate()
chestplate.hold(self.game.player) chestplate.hold(self.game.player)
self.game.handle_key_pressed(KeyValues.EQUIP) chestplate.equip()
self.assertEqual(self.game.player.equipped_armor, chestplate) self.assertEqual(self.game.player.equipped_armor, chestplate)
self.assertFalse(self.game.player.inventory)
# Use bomb # Use bomb
bomb = Bomb() bomb = Bomb()
bomb.hold(self.game.player) bomb.hold(self.game.player)
self.game.handle_key_pressed(KeyValues.EQUIP) bomb.equip()
self.assertEqual(self.game.player.equipped_secondary, bomb) self.assertEqual(self.game.player.equipped_secondary, bomb)
self.assertIn(shield, self.game.player.inventory) self.assertFalse(shield.equipped)
self.game.state = GameMode.PLAY self.game.state = GameMode.PLAY
self.game.handle_key_pressed(KeyValues.USE) self.game.handle_key_pressed(KeyValues.USE)
self.assertIsNone(self.game.player.equipped_secondary) self.assertIsNone(self.game.player.equipped_secondary)
self.game.state = GameMode.INVENTORY self.game.state = GameMode.INVENTORY
self.game.handle_key_pressed(KeyValues.EQUIP) shield.equip()
self.assertEqual(self.game.player.equipped_secondary, shield) self.assertEqual(self.game.player.equipped_secondary, shield)
self.assertFalse(self.game.player.inventory)
# Reequip, which is useless but covers code # Reequip, which is useless but covers code
sword.equip() sword.equip()