563 lines
19 KiB
Python
563 lines
19 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""Item Manager - Coordinates item pickup/drop across multiple widgets
|
||
|
|
|
||
|
|
This module provides:
|
||
|
|
- ItemManager: Central coordinator for item transfers
|
||
|
|
- ItemSlot: Frame-based equipment slot widget
|
||
|
|
- Item: Data class for item properties
|
||
|
|
|
||
|
|
The manager allows entities to move between:
|
||
|
|
- Grid widgets (inventory, shop displays)
|
||
|
|
- ItemSlot widgets (equipment slots)
|
||
|
|
- The cursor (when held)
|
||
|
|
|
||
|
|
Usage:
|
||
|
|
manager = ItemManager()
|
||
|
|
manager.register_grid("inventory", inventory_grid)
|
||
|
|
manager.register_slot("weapon", weapon_slot)
|
||
|
|
|
||
|
|
# Widgets call manager methods on click:
|
||
|
|
manager.pickup_from_grid("inventory", cell_pos)
|
||
|
|
manager.drop_to_slot("weapon")
|
||
|
|
"""
|
||
|
|
import mcrfpy
|
||
|
|
|
||
|
|
|
||
|
|
class ItemEntity(mcrfpy.Entity):
|
||
|
|
"""Entity subclass that can hold item data."""
|
||
|
|
|
||
|
|
def __init__(self):
|
||
|
|
super().__init__()
|
||
|
|
self.item = None # Will be set after adding to grid
|
||
|
|
|
||
|
|
|
||
|
|
class Item:
|
||
|
|
"""Data class representing an item's properties."""
|
||
|
|
|
||
|
|
def __init__(self, sprite_index, name, **stats):
|
||
|
|
"""
|
||
|
|
Args:
|
||
|
|
sprite_index: Texture sprite index
|
||
|
|
name: Display name
|
||
|
|
**stats: Arbitrary stats (atk, def, int, price, etc.)
|
||
|
|
"""
|
||
|
|
self.sprite_index = sprite_index
|
||
|
|
self.name = name
|
||
|
|
self.stats = stats
|
||
|
|
|
||
|
|
def __repr__(self):
|
||
|
|
return f"Item({self.name}, sprite={self.sprite_index})"
|
||
|
|
|
||
|
|
@property
|
||
|
|
def price(self):
|
||
|
|
return self.stats.get('price', 0)
|
||
|
|
|
||
|
|
@property
|
||
|
|
def atk(self):
|
||
|
|
return self.stats.get('atk', 0)
|
||
|
|
|
||
|
|
@property
|
||
|
|
def def_(self):
|
||
|
|
return self.stats.get('def', 0)
|
||
|
|
|
||
|
|
@property
|
||
|
|
def slot_type(self):
|
||
|
|
"""Equipment slot this item fits in (weapon, shield, etc.)"""
|
||
|
|
return self.stats.get('slot_type', None)
|
||
|
|
|
||
|
|
|
||
|
|
class ItemSlot(mcrfpy.Frame):
|
||
|
|
"""A frame that can hold a single item (for equipment slots)."""
|
||
|
|
|
||
|
|
def __init__(self, pos, size=(64, 64), slot_type=None,
|
||
|
|
empty_color=(60, 60, 70), valid_color=(60, 100, 60),
|
||
|
|
invalid_color=(100, 60, 60), filled_color=(80, 80, 90)):
|
||
|
|
"""
|
||
|
|
Args:
|
||
|
|
pos: Position tuple (x, y)
|
||
|
|
size: Size tuple (w, h)
|
||
|
|
slot_type: Type of items this slot accepts (e.g., 'weapon', 'shield')
|
||
|
|
empty_color: Color when empty and not hovered
|
||
|
|
valid_color: Color when valid item is hovering
|
||
|
|
invalid_color: Color when invalid item is hovering
|
||
|
|
filled_color: Color when containing an item
|
||
|
|
"""
|
||
|
|
super().__init__(pos, size, fill_color=empty_color, outline=2, outline_color=(100, 100, 120))
|
||
|
|
|
||
|
|
self.slot_type = slot_type
|
||
|
|
self.empty_color = empty_color
|
||
|
|
self.valid_color = valid_color
|
||
|
|
self.invalid_color = invalid_color
|
||
|
|
self.filled_color = filled_color
|
||
|
|
|
||
|
|
# Item stored in this slot
|
||
|
|
self.item = None
|
||
|
|
self.item_sprite = None
|
||
|
|
|
||
|
|
# Manager reference (set by manager.register_slot)
|
||
|
|
self.manager = None
|
||
|
|
self.slot_name = None
|
||
|
|
|
||
|
|
# Setup sprite for displaying item
|
||
|
|
sprite_scale = min(size[0], size[1]) / 16.0 * 0.8 # 80% of slot size
|
||
|
|
self.item_sprite = mcrfpy.Sprite(
|
||
|
|
pos=(size[0] * 0.1, size[1] * 0.1),
|
||
|
|
texture=mcrfpy.default_texture,
|
||
|
|
sprite_index=0
|
||
|
|
)
|
||
|
|
self.item_sprite.scale = sprite_scale
|
||
|
|
self.item_sprite.visible = False
|
||
|
|
self.children.append(self.item_sprite)
|
||
|
|
|
||
|
|
# Setup events
|
||
|
|
self.on_click = self._on_click
|
||
|
|
self.on_enter = self._on_enter
|
||
|
|
self.on_exit = self._on_exit
|
||
|
|
|
||
|
|
def set_item(self, item):
|
||
|
|
"""Set the item in this slot."""
|
||
|
|
self.item = item
|
||
|
|
if item:
|
||
|
|
self.item_sprite.sprite_index = item.sprite_index
|
||
|
|
self.item_sprite.visible = True
|
||
|
|
self.fill_color = self.filled_color
|
||
|
|
else:
|
||
|
|
self.item_sprite.visible = False
|
||
|
|
self.fill_color = self.empty_color
|
||
|
|
|
||
|
|
def clear(self):
|
||
|
|
"""Remove item from slot."""
|
||
|
|
self.set_item(None)
|
||
|
|
|
||
|
|
def can_accept(self, item):
|
||
|
|
"""Check if this slot can accept the given item."""
|
||
|
|
if self.slot_type is None:
|
||
|
|
return True # Accepts anything
|
||
|
|
if item is None:
|
||
|
|
return True
|
||
|
|
return item.slot_type == self.slot_type
|
||
|
|
|
||
|
|
def _on_click(self, pos, button, action):
|
||
|
|
if action != "start" or button != "left":
|
||
|
|
return
|
||
|
|
if self.manager:
|
||
|
|
self.manager.handle_slot_click(self.slot_name)
|
||
|
|
|
||
|
|
def _on_enter(self, pos, *args):
|
||
|
|
if self.manager and self.manager.held_item:
|
||
|
|
if self.can_accept(self.manager.held_item):
|
||
|
|
self.fill_color = self.valid_color
|
||
|
|
else:
|
||
|
|
self.fill_color = self.invalid_color
|
||
|
|
|
||
|
|
def _on_exit(self, pos, *args):
|
||
|
|
if self.item:
|
||
|
|
self.fill_color = self.filled_color
|
||
|
|
else:
|
||
|
|
self.fill_color = self.empty_color
|
||
|
|
|
||
|
|
|
||
|
|
class ItemManager:
|
||
|
|
"""Coordinates item pickup and placement across multiple widgets."""
|
||
|
|
|
||
|
|
def __init__(self, scene):
|
||
|
|
"""
|
||
|
|
Args:
|
||
|
|
scene: The mcrfpy.Scene to add cursor elements to
|
||
|
|
"""
|
||
|
|
self.scene = scene
|
||
|
|
self.grids = {} # name -> (grid, {(x,y): Item})
|
||
|
|
self.slots = {} # name -> ItemSlot
|
||
|
|
|
||
|
|
# Currently held item state
|
||
|
|
self.held_item = None
|
||
|
|
self.held_source = None # ('grid', name, pos) or ('slot', name)
|
||
|
|
self.held_entity = None # For grid sources, the original entity
|
||
|
|
|
||
|
|
# Cursor sprite setup
|
||
|
|
self.cursor_frame = mcrfpy.Frame(
|
||
|
|
pos=(0, 0),
|
||
|
|
size=(64, 64),
|
||
|
|
fill_color=(0, 0, 0, 0),
|
||
|
|
outline=0
|
||
|
|
)
|
||
|
|
self.cursor_sprite = mcrfpy.Sprite(
|
||
|
|
pos=(0, 0),
|
||
|
|
texture=mcrfpy.default_texture,
|
||
|
|
sprite_index=0
|
||
|
|
)
|
||
|
|
self.cursor_sprite.scale = 4.0
|
||
|
|
self.cursor_sprite.visible = False
|
||
|
|
self.cursor_frame.children.append(self.cursor_sprite)
|
||
|
|
scene.children.append(self.cursor_frame)
|
||
|
|
|
||
|
|
# Callbacks for UI updates
|
||
|
|
self.on_pickup = None # Called when item picked up
|
||
|
|
self.on_drop = None # Called when item dropped
|
||
|
|
self.on_cancel = None # Called when pickup cancelled
|
||
|
|
|
||
|
|
def register_grid(self, name, grid, items=None):
|
||
|
|
"""Register a grid for item management.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
name: Unique name for this grid
|
||
|
|
grid: mcrfpy.Grid instance
|
||
|
|
items: Optional dict of {(x, y): Item} for initial items
|
||
|
|
"""
|
||
|
|
item_map = items or {}
|
||
|
|
|
||
|
|
# Add a color layer for highlighting if not present
|
||
|
|
color_layer = grid.add_layer('color', z_index=-1)
|
||
|
|
|
||
|
|
self.grids[name] = (grid, item_map, color_layer)
|
||
|
|
|
||
|
|
# Setup grid event handlers
|
||
|
|
grid.on_click = lambda pos, btn, act: self._on_grid_click(name, pos, btn, act)
|
||
|
|
grid.on_cell_enter = lambda cell_pos: self._on_grid_cell_enter(name, cell_pos)
|
||
|
|
grid.on_move = self._on_move
|
||
|
|
|
||
|
|
def register_slot(self, name, slot):
|
||
|
|
"""Register an ItemSlot for item management.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
name: Unique name for this slot
|
||
|
|
slot: ItemSlot instance
|
||
|
|
"""
|
||
|
|
self.slots[name] = slot
|
||
|
|
slot.manager = self
|
||
|
|
slot.slot_name = name
|
||
|
|
|
||
|
|
def add_item_to_grid(self, grid_name, pos, item):
|
||
|
|
"""Add an item to a grid at the specified position.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
grid_name: Name of registered grid
|
||
|
|
pos: (x, y) cell position
|
||
|
|
item: Item instance
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
True if successful, False if cell occupied
|
||
|
|
"""
|
||
|
|
if grid_name not in self.grids:
|
||
|
|
return False
|
||
|
|
|
||
|
|
grid, item_map, color_layer = self.grids[grid_name]
|
||
|
|
|
||
|
|
if pos in item_map:
|
||
|
|
return False # Cell occupied
|
||
|
|
|
||
|
|
# Create entity
|
||
|
|
entity = ItemEntity()
|
||
|
|
grid.entities.append(entity)
|
||
|
|
entity.grid_pos = pos # Use grid_pos for tile coordinates
|
||
|
|
entity.sprite_index = item.sprite_index
|
||
|
|
entity.item = item # Store item reference on our subclass
|
||
|
|
item_map[pos] = item
|
||
|
|
|
||
|
|
return True
|
||
|
|
|
||
|
|
def get_item_at(self, grid_name, pos):
|
||
|
|
"""Get item at grid position, or None."""
|
||
|
|
if grid_name not in self.grids:
|
||
|
|
return None
|
||
|
|
grid, item_map, color_layer = self.grids[grid_name]
|
||
|
|
return item_map.get(pos)
|
||
|
|
|
||
|
|
def _get_entity_at(self, grid_name, pos):
|
||
|
|
"""Get entity at grid position."""
|
||
|
|
grid, _, _ = self.grids[grid_name]
|
||
|
|
for entity in grid.entities:
|
||
|
|
gp = entity.grid_pos
|
||
|
|
if (int(gp[0]), int(gp[1])) == pos:
|
||
|
|
return entity
|
||
|
|
return None
|
||
|
|
|
||
|
|
def _on_grid_click(self, grid_name, pos, button, action):
|
||
|
|
"""Handle click on a registered grid."""
|
||
|
|
if action != "start":
|
||
|
|
return
|
||
|
|
|
||
|
|
if button == "right":
|
||
|
|
self.cancel_pickup()
|
||
|
|
return
|
||
|
|
|
||
|
|
if button != "left":
|
||
|
|
return
|
||
|
|
|
||
|
|
grid, item_map, color_layer = self.grids[grid_name]
|
||
|
|
|
||
|
|
# Convert screen pos to cell
|
||
|
|
cell_size = 16 * grid.zoom
|
||
|
|
x = int((pos[0] - grid.x) / cell_size)
|
||
|
|
y = int((pos[1] - grid.y) / cell_size)
|
||
|
|
grid_w, grid_h = grid.grid_size
|
||
|
|
|
||
|
|
if not (0 <= x < grid_w and 0 <= y < grid_h):
|
||
|
|
return
|
||
|
|
|
||
|
|
cell_pos = (x, y)
|
||
|
|
|
||
|
|
if self.held_item is None:
|
||
|
|
# Try to pick up
|
||
|
|
if cell_pos in item_map:
|
||
|
|
self._pickup_from_grid(grid_name, cell_pos)
|
||
|
|
else:
|
||
|
|
# Try to drop
|
||
|
|
if cell_pos not in item_map:
|
||
|
|
self._drop_to_grid(grid_name, cell_pos)
|
||
|
|
|
||
|
|
def _pickup_from_grid(self, grid_name, pos):
|
||
|
|
"""Pick up item from grid cell."""
|
||
|
|
grid, item_map, color_layer = self.grids[grid_name]
|
||
|
|
item = item_map[pos]
|
||
|
|
entity = self._get_entity_at(grid_name, pos)
|
||
|
|
|
||
|
|
if entity:
|
||
|
|
entity.visible = False
|
||
|
|
|
||
|
|
self.held_item = item
|
||
|
|
self.held_source = ('grid', grid_name, pos)
|
||
|
|
self.held_entity = entity
|
||
|
|
|
||
|
|
# Setup cursor
|
||
|
|
self.cursor_sprite.sprite_index = item.sprite_index
|
||
|
|
self.cursor_sprite.visible = True
|
||
|
|
|
||
|
|
# Highlight source cell
|
||
|
|
color_layer.set(pos, (255, 255, 100, 200))
|
||
|
|
|
||
|
|
if self.on_pickup:
|
||
|
|
self.on_pickup(item, grid_name, pos)
|
||
|
|
|
||
|
|
def _drop_to_grid(self, grid_name, pos):
|
||
|
|
"""Drop held item to grid cell."""
|
||
|
|
grid, item_map, color_layer = self.grids[grid_name]
|
||
|
|
|
||
|
|
# Check if same grid and moving item
|
||
|
|
if self.held_source[0] == 'grid':
|
||
|
|
source_grid_name = self.held_source[1]
|
||
|
|
source_pos = self.held_source[2]
|
||
|
|
|
||
|
|
# Remove from source
|
||
|
|
source_grid, source_map, source_color_layer = self.grids[source_grid_name]
|
||
|
|
if source_pos in source_map:
|
||
|
|
del source_map[source_pos]
|
||
|
|
|
||
|
|
# Clear source highlight
|
||
|
|
source_color_layer.set(source_pos, (0, 0, 0, 0))
|
||
|
|
|
||
|
|
# Move or recreate entity
|
||
|
|
if grid_name == source_grid_name and self.held_entity:
|
||
|
|
# Same grid - just move entity
|
||
|
|
self.held_entity.grid_pos = pos
|
||
|
|
self.held_entity.visible = True
|
||
|
|
else:
|
||
|
|
# Different grid - remove old, create new
|
||
|
|
if self.held_entity:
|
||
|
|
# Remove from source grid
|
||
|
|
for i, e in enumerate(source_grid.entities):
|
||
|
|
if e is self.held_entity:
|
||
|
|
source_grid.entities.pop(i)
|
||
|
|
break
|
||
|
|
|
||
|
|
# Create in target grid
|
||
|
|
entity = ItemEntity()
|
||
|
|
grid.entities.append(entity)
|
||
|
|
entity.grid_pos = pos # Use grid_pos for tile coordinates
|
||
|
|
entity.sprite_index = self.held_item.sprite_index
|
||
|
|
entity.item = self.held_item
|
||
|
|
self.held_entity = None
|
||
|
|
|
||
|
|
elif self.held_source[0] == 'slot':
|
||
|
|
# Moving from slot to grid
|
||
|
|
slot_name = self.held_source[1]
|
||
|
|
slot = self.slots[slot_name]
|
||
|
|
slot.clear()
|
||
|
|
|
||
|
|
# Create entity in grid
|
||
|
|
entity = ItemEntity()
|
||
|
|
grid.entities.append(entity)
|
||
|
|
entity.grid_pos = pos # Use grid_pos for tile coordinates
|
||
|
|
entity.sprite_index = self.held_item.sprite_index
|
||
|
|
entity.item = self.held_item
|
||
|
|
|
||
|
|
# Add to target grid's item map
|
||
|
|
item_map[pos] = self.held_item
|
||
|
|
|
||
|
|
if self.on_drop:
|
||
|
|
self.on_drop(self.held_item, grid_name, pos)
|
||
|
|
|
||
|
|
# Clear held state
|
||
|
|
self.cursor_sprite.visible = False
|
||
|
|
self.held_item = None
|
||
|
|
self.held_source = None
|
||
|
|
self.held_entity = None
|
||
|
|
|
||
|
|
def handle_slot_click(self, slot_name):
|
||
|
|
"""Handle click on a registered slot."""
|
||
|
|
slot = self.slots[slot_name]
|
||
|
|
|
||
|
|
if self.held_item is None:
|
||
|
|
# Try to pick up from slot
|
||
|
|
if slot.item:
|
||
|
|
self._pickup_from_slot(slot_name)
|
||
|
|
else:
|
||
|
|
# Try to drop to slot
|
||
|
|
if slot.can_accept(self.held_item):
|
||
|
|
self._drop_to_slot(slot_name)
|
||
|
|
|
||
|
|
def _pickup_from_slot(self, slot_name):
|
||
|
|
"""Pick up item from slot."""
|
||
|
|
slot = self.slots[slot_name]
|
||
|
|
item = slot.item
|
||
|
|
|
||
|
|
self.held_item = item
|
||
|
|
self.held_source = ('slot', slot_name)
|
||
|
|
self.held_entity = None
|
||
|
|
|
||
|
|
slot.clear()
|
||
|
|
|
||
|
|
# Setup cursor
|
||
|
|
self.cursor_sprite.sprite_index = item.sprite_index
|
||
|
|
self.cursor_sprite.visible = True
|
||
|
|
|
||
|
|
if self.on_pickup:
|
||
|
|
self.on_pickup(item, slot_name, None)
|
||
|
|
|
||
|
|
def _drop_to_slot(self, slot_name):
|
||
|
|
"""Drop held item to slot."""
|
||
|
|
slot = self.slots[slot_name]
|
||
|
|
|
||
|
|
# If slot has item, swap
|
||
|
|
old_item = slot.item
|
||
|
|
slot.set_item(self.held_item)
|
||
|
|
|
||
|
|
# Clean up source
|
||
|
|
if self.held_source[0] == 'grid':
|
||
|
|
source_grid_name = self.held_source[1]
|
||
|
|
source_pos = self.held_source[2]
|
||
|
|
source_grid, source_map, source_color_layer = self.grids[source_grid_name]
|
||
|
|
|
||
|
|
# Remove from source grid
|
||
|
|
if source_pos in source_map:
|
||
|
|
del source_map[source_pos]
|
||
|
|
|
||
|
|
# Clear highlight
|
||
|
|
source_color_layer.set(source_pos, (0, 0, 0, 0))
|
||
|
|
|
||
|
|
# Remove entity
|
||
|
|
if self.held_entity:
|
||
|
|
for i, e in enumerate(source_grid.entities):
|
||
|
|
if e is self.held_entity:
|
||
|
|
source_grid.entities.pop(i)
|
||
|
|
break
|
||
|
|
|
||
|
|
# If swapping, put old item in source position
|
||
|
|
if old_item:
|
||
|
|
self.add_item_to_grid(source_grid_name, source_pos, old_item)
|
||
|
|
|
||
|
|
elif self.held_source[0] == 'slot':
|
||
|
|
# Slot to slot swap
|
||
|
|
source_slot_name = self.held_source[1]
|
||
|
|
source_slot = self.slots[source_slot_name]
|
||
|
|
if old_item:
|
||
|
|
source_slot.set_item(old_item)
|
||
|
|
|
||
|
|
if self.on_drop:
|
||
|
|
self.on_drop(self.held_item, slot_name, None)
|
||
|
|
|
||
|
|
# Clear held state
|
||
|
|
self.cursor_sprite.visible = False
|
||
|
|
self.held_item = None
|
||
|
|
self.held_source = None
|
||
|
|
self.held_entity = None
|
||
|
|
|
||
|
|
def cancel_pickup(self):
|
||
|
|
"""Cancel current pickup and return item to source."""
|
||
|
|
if not self.held_item:
|
||
|
|
return
|
||
|
|
|
||
|
|
if self.held_source[0] == 'grid':
|
||
|
|
grid_name = self.held_source[1]
|
||
|
|
pos = self.held_source[2]
|
||
|
|
grid, item_map, color_layer = self.grids[grid_name]
|
||
|
|
|
||
|
|
# Restore entity visibility
|
||
|
|
if self.held_entity:
|
||
|
|
self.held_entity.visible = True
|
||
|
|
|
||
|
|
# Restore item map
|
||
|
|
item_map[pos] = self.held_item
|
||
|
|
|
||
|
|
# Clear highlight
|
||
|
|
color_layer.set(pos, (0, 0, 0, 0))
|
||
|
|
|
||
|
|
elif self.held_source[0] == 'slot':
|
||
|
|
slot_name = self.held_source[1]
|
||
|
|
slot = self.slots[slot_name]
|
||
|
|
slot.set_item(self.held_item)
|
||
|
|
|
||
|
|
if self.on_cancel:
|
||
|
|
self.on_cancel(self.held_item)
|
||
|
|
|
||
|
|
# Clear held state
|
||
|
|
self.cursor_sprite.visible = False
|
||
|
|
self.held_item = None
|
||
|
|
self.held_source = None
|
||
|
|
self.held_entity = None
|
||
|
|
|
||
|
|
def _on_grid_cell_enter(self, grid_name, cell_pos):
|
||
|
|
"""Handle cell hover on registered grid."""
|
||
|
|
if not self.held_item:
|
||
|
|
return
|
||
|
|
|
||
|
|
grid, item_map, color_layer = self.grids[grid_name]
|
||
|
|
x, y = int(cell_pos[0]), int(cell_pos[1])
|
||
|
|
|
||
|
|
# Don't highlight source cell
|
||
|
|
if (self.held_source[0] == 'grid' and
|
||
|
|
self.held_source[1] == grid_name and
|
||
|
|
self.held_source[2] == (x, y)):
|
||
|
|
return
|
||
|
|
|
||
|
|
if (x, y) in item_map:
|
||
|
|
color_layer.set((x, y), (255, 100, 100, 200)) # Red - occupied
|
||
|
|
else:
|
||
|
|
color_layer.set((x, y), (100, 255, 100, 200)) # Green - available
|
||
|
|
|
||
|
|
def _on_move(self, pos, *args):
|
||
|
|
"""Update cursor position."""
|
||
|
|
if self.cursor_sprite.visible:
|
||
|
|
self.cursor_frame.x = pos[0] - 32
|
||
|
|
self.cursor_frame.y = pos[1] - 32
|
||
|
|
|
||
|
|
|
||
|
|
# Predefined items using the texture sprites
|
||
|
|
ITEM_DATABASE = {
|
||
|
|
'buckler': Item(101, "Buckler", def_=1, slot_type='shield', price=15),
|
||
|
|
'shield': Item(102, "Shield", def_=2, slot_type='shield', price=30),
|
||
|
|
'shortsword': Item(103, "Shortsword", atk=1, slot_type='weapon', price=20),
|
||
|
|
'longsword': Item(104, "Longsword", atk=2, slot_type='weapon', price=40),
|
||
|
|
'cleaver': Item(105, "Cleaver", atk=3, slot_type='weapon', two_handed=True, price=60),
|
||
|
|
'buster': Item(106, "Buster Sword", atk=4, slot_type='weapon', two_handed=True, price=100),
|
||
|
|
'training_sword': Item(107, "Training Sword", atk=2, slot_type='weapon', two_handed=True, price=25),
|
||
|
|
'hammer': Item(117, "Hammer", atk=2, slot_type='weapon', price=35),
|
||
|
|
'double_axe': Item(118, "Double Axe", atk=5, slot_type='weapon', two_handed=True, price=120),
|
||
|
|
'axe': Item(119, "Axe", atk=3, slot_type='weapon', price=50),
|
||
|
|
'wand': Item(129, "Wand", atk=1, int_=4, slot_type='weapon', price=45),
|
||
|
|
'staff': Item(130, "Staff", atk=1, int_=7, slot_type='weapon', two_handed=True, price=80),
|
||
|
|
'spear': Item(131, "Spear", atk=4, range_=1, slot_type='weapon', two_handed=True, price=55),
|
||
|
|
'cloudy_potion': Item(113, "Cloudy Potion", slot_type='consumable', price=5),
|
||
|
|
'str_potion': Item(114, "Strength Potion", slot_type='consumable', price=25),
|
||
|
|
'health_potion': Item(115, "Health Potion", slot_type='consumable', price=15),
|
||
|
|
'mana_potion': Item(116, "Mana Potion", slot_type='consumable', price=15),
|
||
|
|
'lesser_cloudy': Item(125, "Lesser Cloudy Potion", slot_type='consumable', price=3),
|
||
|
|
'lesser_str': Item(126, "Lesser Strength Potion", slot_type='consumable', price=12),
|
||
|
|
'lesser_health': Item(127, "Lesser Health Potion", slot_type='consumable', price=8),
|
||
|
|
'lesser_mana': Item(128, "Lesser Mana Potion", slot_type='consumable', price=8),
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def get_item(name):
|
||
|
|
"""Get an item from the database by name."""
|
||
|
|
return ITEM_DATABASE.get(name)
|