"""
Profile and character stat management handlers.
"""
import logging
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from . import keyboards
from data.world_loader import game_world
logger = logging.getLogger(__name__)
async def handle_profile(query, user_id: int, player: dict, data: list = None):
"""Display player profile with stats and level info."""
from .utils import format_stat_bar
await query.answer()
from bot import combat
from .utils import format_stat_bar, create_progress_bar
# Calculate stats
xp_current = player['xp']
xp_needed = combat.xp_for_level(player['level'] + 1)
xp_for_current_level = combat.xp_for_level(player['level'])
xp_progress = max(0, xp_current - xp_for_current_level)
xp_level_requirement = xp_needed - xp_for_current_level
progress_percent = int((xp_progress / xp_level_requirement) * 100) if xp_level_requirement > 0 else 0
unspent = player.get('unspent_points', 0)
# Build profile with visual bars
profile_text = f"👤 {player['name']}\n"
profile_text += f"━━━━━━━━━━━━━━━━━━━━\n\n"
profile_text += f"Level: {player['level']}\n"
# XP bar
xp_bar = create_progress_bar(xp_progress, xp_level_requirement, length=10)
profile_text += f"⭐ XP: {xp_bar} {progress_percent}% ({xp_current}/{xp_needed})\n"
if unspent > 0:
profile_text += f"💎 Unspent Points: {unspent}\n"
profile_text += f"\n{format_stat_bar('HP', '❤️', player['hp'], player['max_hp'])}\n"
profile_text += f"{format_stat_bar('Stamina', '⚡', player['stamina'], player['max_stamina'])}\n\n"
profile_text += f"Stats:\n"
profile_text += f"💪 Strength: {player['strength']}\n"
profile_text += f"🏃 Agility: {player['agility']}\n"
profile_text += f"💚 Endurance: {player['endurance']}\n"
profile_text += f"🧠 Intellect: {player['intellect']}\n\n"
profile_text += f"Combat:\n"
profile_text += f"⚔️ Base Damage: {5 + player['strength'] // 2 + player['level']}\n"
profile_text += f"🛡️ Flee Chance: {int((0.5 + player['agility'] / 100) * 100)}%\n"
profile_text += f"💚 Stamina Regen: {1 + player['endurance'] // 10}/cycle\n\n"
# Show status effects if any
try:
from .api_client import api_client
status_effects = await api_client.get_player_status_effects(user_id)
if status_effects:
from bot.status_utils import get_status_details
from .api_client import api_client
# Check if player is in combat
combat_state = await api_client.get_combat(user_id)
in_combat = combat_state is not None
profile_text += f"Status Effects:\n"
profile_text += get_status_details(status_effects, in_combat=in_combat) + "\n\n"
except:
pass # Status effects not critical, skip if error
location = game_world.get_location(player['location_id'])
location_image = location.image_path if location else None
# Add spend points button if player has unspent points
keyboard_buttons = []
if unspent > 0:
keyboard_buttons.append([
InlineKeyboardButton("⭐ Spend Stat Points", callback_data="spend_points_menu")
])
keyboard_buttons.append([InlineKeyboardButton("⬅️ Back", callback_data="main_menu")])
back_keyboard = InlineKeyboardMarkup(keyboard_buttons)
from .handlers import send_or_edit_with_image
await send_or_edit_with_image(
query,
text=profile_text,
reply_markup=back_keyboard,
image_path=location_image
)
async def handle_spend_points_menu(query, user_id: int, player: dict, data: list = None):
"""Show menu for spending attribute points."""
await query.answer()
unspent = player.get('unspent_points', 0)
if unspent <= 0:
await query.answer("You have no points to spend!", show_alert=False)
return
text = f"⭐ Spend Stat Points\n\n"
text += f"Available Points: {unspent}\n\n"
text += f"Current Stats:\n"
text += f"❤️ Max HP: {player['max_hp']} (+10 per point)\n"
text += f"⚡ Max Stamina: {player['max_stamina']} (+5 per point)\n"
text += f"💪 Strength: {player['strength']} (+1 per point)\n"
text += f"🏃 Agility: {player['agility']} (+1 per point)\n"
text += f"💚 Endurance: {player['endurance']} (+1 per point)\n"
text += f"🧠 Intellect: {player['intellect']} (+1 per point)\n\n"
text += f"💡 Choose wisely! Each point matters."
keyboard = keyboards.spend_points_keyboard()
from .handlers import send_or_edit_with_image
await send_or_edit_with_image(query, text=text, reply_markup=keyboard)
async def handle_spend_point(query, user_id: int, player: dict, data: list):
"""Spend a stat point on a specific attribute."""
stat_name = data[1]
unspent = player.get('unspent_points', 0)
if unspent <= 0:
await query.answer("You have no points to spend!", show_alert=False)
return
# Map stat names to updates
stat_mapping = {
'max_hp': ('max_hp', 10, '❤️ Max HP'),
'max_stamina': ('max_stamina', 5, '⚡ Max Stamina'),
'strength': ('strength', 1, '💪 Strength'),
'agility': ('agility', 1, '🏃 Agility'),
'endurance': ('endurance', 1, '💚 Endurance'),
'intellect': ('intellect', 1, '🧠 Intellect'),
}
if stat_name not in stat_mapping:
await query.answer("Invalid stat!", show_alert=False)
return
db_field, increase, display_name = stat_mapping[stat_name]
new_value = player[db_field] + increase
new_unspent = unspent - 1
from .api_client import api_client
await api_client.update_player(user_id, {
db_field: new_value,
'unspent_points': new_unspent
})
# Update local player data
player[db_field] = new_value
player['unspent_points'] = new_unspent
await query.answer(f"+{increase} {display_name}!", show_alert=False)
# Refresh the spend points menu
text = f"⭐ Spend Stat Points\n\n"
text += f"Available Points: {new_unspent}\n\n"
text += f"Current Stats:\n"
text += f"❤️ Max HP: {player['max_hp']} (+10 per point)\n"
text += f"⚡ Max Stamina: {player['max_stamina']} (+5 per point)\n"
text += f"💪 Strength: {player['strength']} (+1 per point)\n"
text += f"🏃 Agility: {player['agility']} (+1 per point)\n"
text += f"💚 Endurance: {player['endurance']} (+1 per point)\n"
text += f"🧠 Intellect: {player['intellect']} (+1 per point)\n\n"
text += f"💡 Choose wisely! Each point matters."
keyboard = keyboards.spend_points_keyboard()
from .handlers import send_or_edit_with_image
await send_or_edit_with_image(query, text=text, reply_markup=keyboard)