🎒 Item Collection System: - 16 unique items across 5 categories (healing, battle, rare, location, special) - Rarity tiers: Common, Uncommon, Rare, Epic, Legendary with symbols - 30% chance to find items during exploration - Location-specific items (shells, mushrooms, crystals, runes) - Inventory management with \!inventory and \!use commands - Web interface integration showing player inventories - Consumable items: healing potions, battle boosters, lucky charms 🔧 Technical Updates: - Added items and player_inventory database tables - New Inventory module for item management - Updated game engine with item discovery system - Enhanced web interface with inventory display - Item initialization from config/items.json 🆕 New Commands: - \!inventory / \!inv / \!items - View collected items by category - \!use <item name> - Use consumable items on active pets 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
145 lines
No EOL
6 KiB
Python
145 lines
No EOL
6 KiB
Python
#!/usr/bin/env python3
|
|
"""Inventory management module for PetBot"""
|
|
|
|
from .base_module import BaseModule
|
|
|
|
class Inventory(BaseModule):
|
|
"""Handles inventory, item usage, and item management commands"""
|
|
|
|
def get_commands(self):
|
|
return ["inventory", "inv", "items", "use", "item"]
|
|
|
|
async def handle_command(self, channel, nickname, command, args):
|
|
if command in ["inventory", "inv", "items"]:
|
|
await self.cmd_inventory(channel, nickname)
|
|
elif command in ["use", "item"]:
|
|
await self.cmd_use_item(channel, nickname, args)
|
|
|
|
async def cmd_inventory(self, channel, nickname):
|
|
"""Display player's inventory"""
|
|
player = await self.require_player(channel, nickname)
|
|
if not player:
|
|
return
|
|
|
|
inventory = await self.database.get_player_inventory(player["id"])
|
|
|
|
if not inventory:
|
|
self.send_message(channel, f"🎒 {nickname}: Your inventory is empty! Try exploring to find items.")
|
|
return
|
|
|
|
# Group items by category
|
|
categories = {}
|
|
for item in inventory:
|
|
category = item["category"]
|
|
if category not in categories:
|
|
categories[category] = []
|
|
categories[category].append(item)
|
|
|
|
# Send inventory summary first
|
|
total_items = sum(item["quantity"] for item in inventory)
|
|
self.send_message(channel, f"🎒 {nickname}'s Inventory ({total_items} items):")
|
|
|
|
# Display items by category
|
|
rarity_symbols = {
|
|
"common": "○",
|
|
"uncommon": "◇",
|
|
"rare": "◆",
|
|
"epic": "★",
|
|
"legendary": "✦"
|
|
}
|
|
|
|
for category, items in categories.items():
|
|
category_display = category.replace("_", " ").title()
|
|
self.send_message(channel, f"📦 {category_display}:")
|
|
|
|
for item in items[:5]: # Limit to 5 items per category to avoid spam
|
|
symbol = rarity_symbols.get(item["rarity"], "○")
|
|
quantity_str = f" x{item['quantity']}" if item["quantity"] > 1 else ""
|
|
self.send_message(channel, f" {symbol} {item['name']}{quantity_str} - {item['description']}")
|
|
|
|
if len(items) > 5:
|
|
self.send_message(channel, f" ... and {len(items) - 5} more items")
|
|
|
|
self.send_message(channel, f"💡 Use '!use <item name>' to use consumable items!")
|
|
|
|
async def cmd_use_item(self, channel, nickname, args):
|
|
"""Use an item from inventory"""
|
|
if not args:
|
|
self.send_message(channel, f"{nickname}: Specify an item to use! Example: !use Small Potion")
|
|
return
|
|
|
|
player = await self.require_player(channel, nickname)
|
|
if not player:
|
|
return
|
|
|
|
item_name = " ".join(args)
|
|
result = await self.database.use_item(player["id"], item_name)
|
|
|
|
if not result["success"]:
|
|
self.send_message(channel, f"❌ {nickname}: {result['error']}")
|
|
return
|
|
|
|
item = result["item"]
|
|
effect = result["effect"]
|
|
effect_value = result["effect_value"]
|
|
|
|
# Handle different item effects
|
|
if effect == "heal":
|
|
# Find active pet to heal
|
|
active_pets = await self.database.get_active_pets(player["id"])
|
|
if not active_pets:
|
|
self.send_message(channel, f"❌ {nickname}: You need an active pet to use healing items!")
|
|
return
|
|
|
|
# Heal the first active pet (can be expanded to choose specific pet)
|
|
pet = active_pets[0]
|
|
old_hp = pet["hp"]
|
|
new_hp = min(pet["max_hp"], pet["hp"] + effect_value)
|
|
healed_amount = new_hp - old_hp
|
|
|
|
# Update pet HP in database
|
|
await self.database.update_pet_hp(pet["id"], new_hp)
|
|
|
|
self.send_message(channel,
|
|
f"💊 {nickname}: Used {item['name']} on {pet['nickname'] or pet['species_name']}! "
|
|
f"Restored {healed_amount} HP ({old_hp} → {new_hp}/{pet['max_hp']})")
|
|
|
|
elif effect == "full_heal":
|
|
active_pets = await self.database.get_active_pets(player["id"])
|
|
if not active_pets:
|
|
self.send_message(channel, f"❌ {nickname}: You need an active pet to use healing items!")
|
|
return
|
|
|
|
pet = active_pets[0]
|
|
old_hp = pet["hp"]
|
|
healed_amount = pet["max_hp"] - old_hp
|
|
|
|
await self.database.update_pet_hp(pet["id"], pet["max_hp"])
|
|
|
|
self.send_message(channel,
|
|
f"✨ {nickname}: Used {item['name']} on {pet['nickname'] or pet['species_name']}! "
|
|
f"Fully restored HP! ({old_hp} → {pet['max_hp']}/{pet['max_hp']})")
|
|
|
|
elif effect == "attack_boost":
|
|
self.send_message(channel,
|
|
f"⚔️ {nickname}: Used {item['name']}! Your next battle will have +{effect_value}% attack damage!")
|
|
|
|
elif effect == "defense_boost":
|
|
self.send_message(channel,
|
|
f"🛡️ {nickname}: Used {item['name']}! Your next battle will have +{effect_value}% damage reduction!")
|
|
|
|
elif effect == "speed_boost":
|
|
self.send_message(channel,
|
|
f"💨 {nickname}: Used {item['name']}! You'll move first in your next battle!")
|
|
|
|
elif effect == "lucky_boost":
|
|
self.send_message(channel,
|
|
f"🍀 {nickname}: Used {item['name']}! Rare pet encounter rate increased by {effect_value}% for 1 hour!")
|
|
|
|
elif effect == "none":
|
|
self.send_message(channel,
|
|
f"📦 {nickname}: Used {item['name']}! This item has no immediate effect but may be useful later.")
|
|
|
|
else:
|
|
self.send_message(channel,
|
|
f"✅ {nickname}: Used {item['name']}! {item['description']}") |