""" NPC Events Module Handles player commands for NPC events system """ from modules.base_module import BaseModule from src.npc_events import NPCEventsManager from datetime import datetime class NPCEventsModule(BaseModule): """Module for NPC events system commands""" def __init__(self, bot, database, game_engine): super().__init__(bot, database, game_engine) self.events_manager = NPCEventsManager(database) def get_commands(self): return ['events', 'event', 'help', 'contribute', 'eventhelp'] async def handle_command(self, command, channel, nickname, args): """Handle NPC events commands""" # Normalize command command = self.normalize_input(command) if command == 'events': await self.cmd_events(channel, nickname) elif command == 'event': await self.cmd_event(channel, nickname, args) elif command == 'help' and len(args) > 0 and args[0].lower() == 'events': await self.cmd_event_help(channel, nickname) elif command == 'contribute': await self.cmd_contribute(channel, nickname, args) elif command == 'eventhelp': await self.cmd_event_help(channel, nickname) async def cmd_events(self, channel, nickname): """Show all active NPC events""" try: active_events = await self.events_manager.get_active_events() if not active_events: self.send_message(channel, "šŸ“… No active community events at the moment. Check back later!") return message = "šŸŽÆ **Active Community Events:**\n" for event in active_events: progress = self.events_manager.get_progress_bar( event['current_contributions'], event['target_contributions'] ) # Calculate time remaining expires_at = datetime.fromisoformat(event['expires_at']) time_left = expires_at - datetime.now() if time_left.total_seconds() > 0: hours_left = int(time_left.total_seconds() / 3600) minutes_left = int((time_left.total_seconds() % 3600) / 60) time_str = f"{hours_left}h {minutes_left}m" else: time_str = "Expired" difficulty_stars = "⭐" * event['difficulty'] message += f"\n**#{event['id']} - {event['title']}** {difficulty_stars}\n" message += f"šŸ“ {event['description']}\n" message += f"šŸ“Š Progress: {progress}\n" message += f"ā° Time left: {time_str}\n" message += f"šŸ’° Reward: {event['reward_experience']} XP, ${event['reward_money']}\n" message += f"šŸ¤ Use `!contribute {event['id']}` to help!\n" self.send_message(channel, message) except Exception as e: print(f"Error in cmd_events: {e}") self.send_message(channel, f"āŒ Error fetching events: {str(e)}") async def cmd_event(self, channel, nickname, args): """Show details for a specific event""" if not args: self.send_message(channel, "āŒ Usage: !event ") return try: event_id = int(args[0]) event = await self.events_manager.get_event_details(event_id) if not event: self.send_message(channel, f"āŒ Event #{event_id} not found or expired.") return # Calculate time remaining expires_at = datetime.fromisoformat(event['expires_at']) time_left = expires_at - datetime.now() if time_left.total_seconds() > 0: hours_left = int(time_left.total_seconds() / 3600) minutes_left = int((time_left.total_seconds() % 3600) / 60) time_str = f"{hours_left}h {minutes_left}m" else: time_str = "Expired" progress = self.events_manager.get_progress_bar( event['current_contributions'], event['target_contributions'] ) difficulty_stars = "⭐" * event['difficulty'] status_emoji = "šŸ”„" if event['status'] == 'active' else "āœ…" if event['status'] == 'completed' else "āŒ" message = f"{status_emoji} **Event #{event['id']}: {event['title']}** {difficulty_stars}\n" message += f"šŸ“ {event['description']}\n" message += f"šŸ“Š Progress: {progress}\n" message += f"ā° Time left: {time_str}\n" message += f"šŸ’° Reward: {event['reward_experience']} XP, ${event['reward_money']}\n" message += f"šŸ† Status: {event['status'].title()}\n" # Show leaderboard if there are contributors if event['leaderboard']: message += "\nšŸ… **Top Contributors:**\n" for i, contributor in enumerate(event['leaderboard'][:5]): # Top 5 rank_emoji = ["šŸ„‡", "🄈", "šŸ„‰", "4ļøāƒ£", "5ļøāƒ£"][i] message += f"{rank_emoji} {contributor['nickname']}: {contributor['contributions']} contributions\n" if event['status'] == 'active': message += f"\nšŸ¤ Use `!contribute {event['id']}` to help!" self.send_message(channel, message) except ValueError: self.send_message(channel, "āŒ Invalid event ID. Please use a number.") except Exception as e: print(f"Error in cmd_event: {e}") self.send_message(channel, f"āŒ Error fetching event details: {str(e)}") async def cmd_contribute(self, channel, nickname, args): """Allow player to contribute to an event""" if not args: self.send_message(channel, "āŒ Usage: !contribute ") return player = await self.require_player(channel, nickname) if not player: return try: event_id = int(args[0]) # Check if event exists and is active event = await self.events_manager.get_event_details(event_id) if not event: self.send_message(channel, f"āŒ Event #{event_id} not found or expired.") return if event['status'] != 'active': self.send_message(channel, f"āŒ Event #{event_id} is not active.") return # Check if event has expired expires_at = datetime.fromisoformat(event['expires_at']) if datetime.now() >= expires_at: self.send_message(channel, f"āŒ Event #{event_id} has expired.") return # Add contribution result = await self.events_manager.contribute_to_event(event_id, player['id']) if not result['success']: self.send_message(channel, f"āŒ Failed to contribute: {result.get('error', 'Unknown error')}") return # Get updated event details updated_event = await self.events_manager.get_event_details(event_id) player_contributions = await self.events_manager.get_player_contributions(player['id'], event_id) progress = self.events_manager.get_progress_bar( updated_event['current_contributions'], updated_event['target_contributions'] ) if result['event_completed']: self.send_message(channel, f"šŸŽ‰ **EVENT COMPLETED!** {updated_event['completion_message']}") self.send_message(channel, f"šŸ† Thanks to everyone who participated! Rewards will be distributed shortly.") else: self.send_message(channel, f"āœ… {nickname} contributed to '{updated_event['title']}'!") self.send_message(channel, f"šŸ“Š Progress: {progress}") self.send_message(channel, f"šŸ¤ Your total contributions: {player_contributions}") # Show encouragement based on progress progress_percent = (updated_event['current_contributions'] / updated_event['target_contributions']) * 100 if progress_percent >= 75: self.send_message(channel, "šŸ”„ Almost there! Keep it up!") elif progress_percent >= 50: self.send_message(channel, "šŸ’Ŗ Great progress! We're halfway there!") elif progress_percent >= 25: self.send_message(channel, "🌟 Good start! Keep contributing!") except ValueError: self.send_message(channel, "āŒ Invalid event ID. Please use a number.") except Exception as e: print(f"Error in cmd_contribute: {e}") self.send_message(channel, f"āŒ Error contributing to event: {str(e)}") async def cmd_event_help(self, channel, nickname): """Show help for NPC events system""" message = """šŸŽÆ **Community Events System Help** **Available Commands:** • `!events` - Show all active community events • `!event ` - Show details for a specific event • `!contribute ` - Contribute to an event • `!eventhelp` - Show this help message **How Events Work:** 🌟 Random community events spawn regularly šŸ¤ All players can contribute to the same events šŸ“Š Events have progress bars and time limits šŸ† Everyone who contributes gets rewards when completed ⭐ Events have different difficulty levels (1-3 stars) **Event Types:** • šŸŖ Resource Gathering - Help collect supplies • 🐾 Pet Rescue - Search for missing pets • šŸŽŖ Community Projects - Work together on town projects • 🚨 Emergency Response - Help during crises • šŸ”¬ Research - Assist with scientific discoveries **Tips:** • Check `!events` regularly for new opportunities • Higher difficulty events give better rewards • Contributing more increases your reward multiplier • Events expire after their time limit""" self.send_message(channel, message)