Allow using inventory items, and dropping items
This commit is contained in:
parent
2b708b3b7f
commit
c54ae75f08
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user