Skip to content

Commit f654803

Browse files
committed
finished parts 12 and 13!
1 parent cedce6c commit f654803

File tree

12 files changed

+355
-58
lines changed

12 files changed

+355
-58
lines changed

actions.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ def target_actor(self) -> Optional[Actor]:
7272

7373
def perform(self) -> None:
7474
"""Invoke the items ability, this action will be given to provide context."""
75-
self.item.consumable.activate(self)
75+
if self.item.consumable:
76+
self.item.consumable.activate(self)
7677

7778
class MeleeAction(ActionWithDirection):
7879
def perform(self) -> None:
@@ -165,4 +166,20 @@ def perform(self) -> None:
165166
"You descend the staircase.", color.descend
166167
)
167168
else:
168-
raise exceptions.Impossible("There are no stairs here.")
169+
raise exceptions.Impossible("There are no stairs here.")
170+
171+
class EquipAction(Action):
172+
def __init__(self, entity: Actor, item: Item):
173+
super().__init__(entity)
174+
175+
self.item = item
176+
177+
def perform(self) -> None:
178+
self.entity.equipment.toggle_equip(self.item)
179+
180+
class DropItem(ItemAction):
181+
def perform(self) -> None:
182+
if self.entity.equipment.item_is_equipped(self.item):
183+
self.entity.equipment.toggle_equip(self.item)
184+
185+
self.entity.inventory.drop(self.item)

components/equipment.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from __future__ import annotations
2+
3+
from typing import Optional, TYPE_CHECKING
4+
5+
from components.base_component import BaseComponent
6+
from equipment_types import EquipmentType
7+
8+
if TYPE_CHECKING:
9+
from entity import Actor, Item
10+
11+
12+
class Equipment(BaseComponent):
13+
parent: Actor
14+
15+
def __init__(self, weapon: Optional[Item] = None, armor: Optional[Item] = None):
16+
self.weapon = weapon
17+
self.armor = armor
18+
19+
@property
20+
def defense_bonus(self) -> int:
21+
bonus = 0
22+
23+
if self.weapon is not None and self.weapon.equippable is not None:
24+
bonus += self.weapon.equippable.defense_bonus
25+
26+
if self.armor is not None and self.armor.equippable is not None:
27+
bonus += self.armor.equippable.defense_bonus
28+
29+
return bonus
30+
31+
@property
32+
def power_bonus(self) -> int:
33+
bonus = 0
34+
35+
if self.weapon is not None and self.weapon.equippable is not None:
36+
bonus += self.weapon.equippable.power_bonus
37+
38+
if self.armor is not None and self.armor.equippable is not None:
39+
bonus += self.armor.equippable.power_bonus
40+
41+
return bonus
42+
43+
def item_is_equipped(self, item: Item) -> bool:
44+
return self.weapon == item or self.armor == item
45+
46+
def unequip_message(self, item_name: str) -> None:
47+
self.parent.gamemap.engine.message_log.add_message(
48+
f"You remove the {item_name}."
49+
)
50+
51+
def equip_message(self, item_name: str) -> None:
52+
self.parent.gamemap.engine.message_log.add_message(
53+
f"You equip the {item_name}."
54+
)
55+
56+
def equip_to_slot(self, slot: str, item: Item, add_message: bool) -> None:
57+
current_item = getattr(self, slot)
58+
59+
if current_item is not None:
60+
self.unequip_from_slot(slot, add_message)
61+
62+
setattr(self, slot, item)
63+
64+
if add_message:
65+
self.equip_message(item.name)
66+
67+
def unequip_from_slot(self, slot: str, add_message: bool) -> None:
68+
current_item = getattr(self, slot)
69+
70+
if add_message:
71+
self.unequip_message(current_item.name)
72+
73+
setattr(self, slot, None)
74+
75+
def toggle_equip(self, equippable_item: Item, add_message: bool = True) -> None:
76+
if (
77+
equippable_item.equippable
78+
and equippable_item.equippable.equipment_type == EquipmentType.WEAPON
79+
):
80+
slot = "weapon"
81+
else:
82+
slot = "armor"
83+
84+
if getattr(self, slot) == equippable_item:
85+
self.unequip_from_slot(slot, add_message)
86+
else:
87+
self.equip_to_slot(slot, equippable_item, add_message)

components/equippable.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING
4+
5+
from components.base_component import BaseComponent
6+
from equipment_types import EquipmentType
7+
8+
if TYPE_CHECKING:
9+
from entity import Item
10+
11+
12+
class Equippable(BaseComponent):
13+
parent: Item
14+
15+
def __init__(
16+
self,
17+
equipment_type: EquipmentType,
18+
power_bonus: int = 0,
19+
defense_bonus: int = 0,
20+
):
21+
self.equipment_type = equipment_type
22+
23+
self.power_bonus = power_bonus
24+
self.defense_bonus = defense_bonus
25+
26+
class PocketKinfe(Equippable):
27+
def __init__(self) -> None:
28+
super().__init__(equipment_type=EquipmentType.WEAPON, power_bonus=1)
29+
30+
class OldKinfe(Equippable):
31+
def __init__(self) -> None:
32+
super().__init__(equipment_type=EquipmentType.WEAPON, power_bonus=2)
33+
34+
35+
class SharpKinfe(Equippable):
36+
def __init__(self) -> None:
37+
super().__init__(equipment_type=EquipmentType.WEAPON, power_bonus=4)
38+
39+
class ScrapChestPlate(Equippable):
40+
def __init__(self) -> None:
41+
super().__init__(equipment_type=EquipmentType.ARMOR, defense_bonus=1)
42+
43+
class IronChestPlate(Equippable):
44+
def __init__(self) -> None:
45+
super().__init__(equipment_type=EquipmentType.ARMOR, defense_bonus=2)
46+
47+
48+
class SteelChestPlate(Equippable):
49+
def __init__(self) -> None:
50+
super().__init__(equipment_type=EquipmentType.ARMOR, defense_bonus=3)

components/fighter.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,33 @@
1313
class Fighter(BaseComponent):
1414
parent: Actor
1515

16-
def __init__(self, hp: int, defense: int, power: int):
16+
def __init__(self, hp: int, base_defense: int, base_power: int):
1717
self.max_hp = hp
1818
self._hp = hp
19-
self.defense = defense
20-
self.power = power
19+
self.base_defense = base_defense
20+
self.base_power = base_power
21+
22+
@property
23+
def defense(self) -> int:
24+
return self.base_defense + self.defense_bonus
25+
26+
@property
27+
def power(self) -> int:
28+
return self.base_power + self.power_bonus
29+
30+
@property
31+
def defense_bonus(self) -> int:
32+
if self.parent.equipment:
33+
return self.parent.equipment.defense_bonus
34+
else:
35+
return 0
36+
37+
@property
38+
def power_bonus(self) -> int:
39+
if self.parent.equipment:
40+
return self.parent.equipment.power_bonus
41+
else:
42+
return 0
2143

2244
@property
2345
def hp(self) -> int:

components/level.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@ def increase_max_hp(self, amount: int = 20) -> None:
6060
self.increase_level()
6161

6262
def increase_power(self, amount: int = 1) -> None:
63-
self.parent.fighter.power += amount
63+
self.parent.fighter.base_power += amount
6464

6565
self.engine.message_log.add_message("You feel stronger!")
6666

6767
self.increase_level()
6868

6969
def increase_defense(self, amount: int = 1) -> None:
70-
self.parent.fighter.defense += amount
70+
self.parent.fighter.base_defense += amount
7171

7272
self.engine.message_log.add_message("Your movements are getting swifter!")
7373

entity.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
from components.ai import BaseAI
1111
from components.fighter import Fighter
1212
from components.consumable import Consumable
13+
from components.equipment import Equipment
14+
from components.equippable import Equippable
1315
from components.inventory import Inventory
1416
from components.level import Level
1517
from game_map import GameMap
@@ -105,6 +107,7 @@ def __init__(
105107
name: str = "<Unnamed>",
106108
inspect_message: Optional[str] = "I don't know what this thing is.",
107109
ai_cls: Type[BaseAI],
110+
equipment: Equipment,
108111
fighter: Fighter,
109112
inventory: Inventory,
110113
level: Level,
@@ -122,6 +125,9 @@ def __init__(
122125

123126
self.ai: Optional[BaseAI] = ai_cls(self)
124127

128+
self.equipment: Equipment = equipment
129+
self.equipment.parent = self
130+
125131
self.fighter = fighter
126132
self.fighter.parent = self
127133

@@ -149,7 +155,8 @@ def __init__(
149155
color: Tuple[int, int, int] = (255, 255, 255),
150156
name: str = "<Unnamed>",
151157
inspect_message: Optional[str] = "I don't know what this thing is.",
152-
consumable: Consumable,
158+
consumable: Optional[Consumable] = None,
159+
equippable: Optional[Equippable] = None,
153160
):
154161
super().__init__(
155162
x=x,
@@ -163,4 +170,10 @@ def __init__(
163170
)
164171

165172
self.consumable = consumable
166-
self.consumable.parent = self
173+
if self.consumable:
174+
self.consumable.parent = self
175+
176+
self.equippable = equippable
177+
178+
if self.equippable:
179+
self.equippable.parent = self

entity_factories.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,44 @@
11
from components.ai import HostileEnemy
2-
from components import consumable
2+
from components import consumable, equippable
33
from components.fighter import Fighter
44
from components.inventory import Inventory
55
from components.level import Level
66
from entity import Actor, Item
7+
from components.equipment import Equipment
78

89
player = Actor(
910
char="@",
1011
color=(255, 255, 0),
1112
name="Player",
1213
ai_cls=HostileEnemy,
13-
fighter=Fighter(hp=30, defense=2, power=5),
14+
fighter=Fighter(hp=30, base_defense=1, base_power=2),
1415
inventory=Inventory(capacity=26),
1516
inspect_message="It's yourself. What would you ask for?",
1617
level=Level(level_up_base=200),
18+
equipment=Equipment(),
1719
)
1820

1921
smile_mold = Actor(
2022
char="m",
2123
color=(255, 80, 80),
2224
name="Slime Mold",
2325
ai_cls=HostileEnemy,
24-
fighter=Fighter(hp=10, defense=0, power=3),
26+
fighter=Fighter(hp=10, base_defense=0, base_power=3),
2527
inventory=Inventory(capacity=0),
2628
inspect_message="It's a slime mold... That is alive! It looks hungry for your flesh.",
2729
level=Level(xp_given=35),
30+
equipment=Equipment(),
2831
)
2932
rusty_automaton = Actor(
3033
char="a",
3134
color=(200, 174, 137),
3235
name="Rusty Automaton",
3336
ai_cls=HostileEnemy,
34-
fighter=Fighter(hp=16, defense=1, power=4),
37+
fighter=Fighter(hp=16, base_defense=1, base_power=4),
3538
inventory=Inventory(capacity=0),
3639
inspect_message="He looks like he's been here a while. I Won't say he's having a great time existing.",
3740
level=Level(xp_given=100),
41+
equipment=Equipment(),
3842
)
3943

4044
healing_gel = Item(
@@ -58,10 +62,41 @@
5862
consumable=consumable.ConfusionConsumable(number_of_turns=10),
5963
inspect_message="Bright flashes always makes everyone disoriented. I'd get confused if i were to look at it.",
6064
)
61-
fireball_Gun = Item(
65+
fireball_gun = Item(
6266
char="~",
6367
color=(255, 0, 0),
6468
name="Fireball Gun",
6569
consumable=consumable.FireballDamageConsumable(damage=12, radius=3),
6670
inspect_message="It's a gun that shoots fireballs. Like the ones from fantasy games. It's pretty effective!",
71+
)
72+
73+
pocket_kinfe = Item( char="/", color=(102, 255, 255), name="Pocket kinfe", equippable=equippable.PocketKinfe(),
74+
inspect_message="The most pesonal kinfe you'll ever find. Use it if you're in a pinch."
75+
)
76+
77+
old_kinfe = Item(
78+
char="/", color=(102, 255, 255), name="Old kinfe", equippable=equippable.OldKinfe(),
79+
inspect_message="It's a old rusty kitchen kinfe. It's not very sharp, but it's still effective."
80+
)
81+
sharp_kinfe = Item(char="/", color=(102, 255, 255), name="Sharp kinfe", equippable=equippable.SharpKinfe(),
82+
inspect_message="It's a kitchen kinfe that was not let outside at least."
83+
)
84+
85+
scrap_chest_plate = Item(
86+
char="[",
87+
color=(102, 255, 255),
88+
name="Scrap chest plate",
89+
equippable=equippable.ScrapChestPlate(),
90+
inspect_message="It's a chest plate made of scrap metal. It's not very strong, but it's still effective.",
91+
)
92+
iron_chest_plate = Item(
93+
char="[",
94+
color=(102, 255, 255),
95+
name="Iron chest plate",
96+
equippable=equippable.IronChestPlate(),
97+
inspect_message="It's a chest plate made of iron. Put it on and you'll be able to take a beating.")
98+
99+
steel_chest_plate = Item(
100+
char="[", color=(102, 255, 255), name="Steel chest plate", equippable=equippable.SteelChestPlate(),
101+
inspect_message="It's a chest plate, now made of steel. You'll be able to take quite the beating!"
67102
)

equipment_types.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from enum import auto, Enum
2+
3+
4+
class EquipmentType(Enum):
5+
WEAPON = auto()
6+
ARMOR = auto()

0 commit comments

Comments
 (0)