1
0
Fork 0

Allow using inventory items, and dropping items

This commit is contained in:
Timothy Warren 2022-01-12 16:44:57 -05:00
parent 2b708b3b7f
commit c54ae75f08
2 changed files with 142 additions and 0 deletions

View File

@ -87,6 +87,11 @@ class EscapeAction(Action):
raise SystemExit()
class DropItem(ItemAction):
def perform(self) -> None:
self.entity.inventory.drop(self.item)
class WaitAction(Action):
def perform(self) -> None:
pass

View File

@ -4,6 +4,7 @@ from typing import overload, Optional, TYPE_CHECKING
import tcod.event
import actions
from actions import (
Action,
BumpAction,
@ -16,6 +17,7 @@ import exceptions
if TYPE_CHECKING:
from engine import Engine
from entity import Item
MOVE_KEYS = {
# Arrow keys
@ -94,6 +96,136 @@ class EventHandler(tcod.event.EventDispatch[Action]):
self.engine.render(console)
class AskUserEventHandler(EventHandler):
"""Handles user input for actions which require special input."""
def handle_action(self, action: Optional[Action]) -> bool:
"""Return to the main event handler when a valid action was performed."""
if super().handle_action(action):
self.engine.event_handler = MainGameEventHandler(self.engine)
return True
return False
def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
"""By default any key exits this input handler."""
# Ignore modifier keys.
if event.sym in {
tcod.event.K_LSHIFT,
tcod.event.K_RSHIFT,
tcod.event.K_LCTRL,
tcod.event.K_RCTRL,
tcod.event.K_LALT,
tcod.event.K_RALT,
}:
return None
return self.on_exit()
def ev_mousebuttondown(self, event: tcod.event.MouseButtonDown) -> Optional[Action]:
"""By default any mouse click exits this input handler."""
return self.on_exit()
def on_exit(self) -> Optional[Action]:
"""Called when the user is trying to exit or cancel an action.
By default this returns to the main event handler.
"""
self.engine.event_handler = MainGameEventHandler(self.engine)
return None
class InventoryEventHandler(AskUserEventHandler):
"""This handler lets the user select an item.
What happens then depends on the subclass.
"""
TITLE = "<missing title>"
def on_render(self, console: tcod.Console) -> None:
"""Render an inventory menu, which displays the items in the inventory, and the letter
to select them. Will move to a different position based on where the player is located, so
the player can always see where they are.
"""
super().on_render(console)
number_of_items_in_inventory = len(self.engine.player.inventory.items)
height = number_of_items_in_inventory + 2
if height <= 3:
height = 3
if self.engine.player.x <= 30:
x = 40
else:
x = 0
y = 0
width = len(self.TITLE) + 4
console.draw_frame(
x,
y,
width,
height,
title=self.TITLE,
clear=True,
fg=(255, 255, 255),
bg=(0, 0, 0),
)
if number_of_items_in_inventory > 0:
for i, item in enumerate(self.engine.player.inventory.items):
item_key = chr(ord("a") + i)
console.print(x + 1, y + i + 1, f"({item_key}) {item.name}")
else:
console.print(x + 1, y + 1, "(Empty)")
def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
player = self.engine.player
key = event.sym
index = key - tcod.event.K_a
if 0 <= index <= 26:
try:
selected_item = player.inventory.items[index]
except IndexError:
self.engine.message_log.add_message("Invalid entry.", color.invalid)
return None
return self.on_item_selected(selected_item)
return super().ev_keydown(event)
@overload
def on_item_selected(self, item: Item) -> Optional[Action]:
"""Called when the user selects a valid item."""
class InventoryActivateHandler(InventoryEventHandler):
"""Handle using an inventory item."""
TITLE = "Select an item to use"
def on_item_selected(self, item: Item) -> Optional[Action]:
"""Return the action for the selected item."""
return item.consumable.get_action(self.engine.player)
class InventoryDropHandler(InventoryEventHandler):
"""Handle dropping an inventory item."""
TITLE = "Select an item to drop"
def on_item_selected(self, item: Item) -> Optional[Action]:
"""Drop this item."""
return actions.DropItem(self.engine.player, item)
class MainGameEventHandler(EventHandler):
def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
action: Optional[Action] = None
@ -117,6 +249,11 @@ class MainGameEventHandler(EventHandler):
elif key == tcod.event.K_g:
action = PickupAction(player)
elif key == tcod.event.K_i:
self.engine.event_handler = InventoryActivateHandler(self.engine)
elif key == tcod.event.K_d:
self.engine.event_handler = InventoryDropHandler(self.engine)
# No valid key was pressed
return action