""" EU-Utility - Mission Tracker Plugin Track active missions and progress. """ import json from datetime import datetime from pathlib import Path from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QProgressBar, QFrame, QScrollArea ) from PyQt6.QtCore import Qt from plugins.base_plugin import BasePlugin from core.icon_manager import get_icon_manager class MissionTrackerPlugin(BasePlugin): """Track active missions and daily challenges.""" name = "Mission Tracker" version = "1.0.0" author = "ImpulsiveFPS" description = "Track missions, challenges, and objectives" hotkey = "ctrl+shift+m" def initialize(self): """Setup mission tracker.""" self.data_file = Path("data/missions.json") self.data_file.parent.mkdir(parents=True, exist_ok=True) self.missions = [] self.daily_challenges = [] self._load_data() def _load_data(self): """Load mission data.""" if self.data_file.exists(): try: with open(self.data_file, 'r') as f: data = json.load(f) self.missions = data.get('missions', []) self.daily_challenges = data.get('daily', []) except: pass def _save_data(self): """Save mission data.""" with open(self.data_file, 'w') as f: json.dump({ 'missions': self.missions, 'daily': self.daily_challenges }, f, indent=2) def get_ui(self): """Create mission tracker UI.""" widget = QWidget() widget.setStyleSheet("background: transparent;") layout = QVBoxLayout(widget) layout.setSpacing(15) layout.setContentsMargins(0, 0, 0, 0) # Title title = QLabel("📜 Mission Tracker") title.setStyleSheet(""" color: white; font-size: 16px; font-weight: bold; """) layout.addWidget(title) # Active missions section active_label = QLabel("Active Missions") active_label.setStyleSheet("color: rgba(255,255,255,200); font-size: 12px;") layout.addWidget(active_label) # Mission cards self.missions_container = QWidget() self.missions_layout = QVBoxLayout(self.missions_container) self.missions_layout.setSpacing(10) self.missions_layout.setContentsMargins(0, 0, 0, 0) self._refresh_missions() layout.addWidget(self.missions_container) # Daily challenges daily_label = QLabel("Daily Challenges") daily_label.setStyleSheet("color: rgba(255,255,255,200); font-size: 12px; margin-top: 10px;") layout.addWidget(daily_label) self.daily_container = QWidget() self.daily_layout = QVBoxLayout(self.daily_container) self.daily_layout.setSpacing(8) self.daily_layout.setContentsMargins(0, 0, 0, 0) self._refresh_daily() layout.addWidget(self.daily_container) # Add mission button add_btn = QPushButton("+ Add Mission") add_btn.setStyleSheet(""" QPushButton { background-color: rgba(255, 140, 66, 200); color: white; padding: 10px; border: none; border-radius: 4px; font-weight: bold; } QPushButton:hover { background-color: rgba(255, 160, 80, 230); } """) add_btn.clicked.connect(self._add_mission) layout.addWidget(add_btn) layout.addStretch() return widget def _create_mission_card(self, mission): """Create a mission card widget.""" card = QFrame() card.setStyleSheet(""" QFrame { background-color: rgba(30, 35, 45, 200); border: 1px solid rgba(100, 110, 130, 80); border-radius: 6px; } """) layout = QVBoxLayout(card) layout.setContentsMargins(12, 10, 12, 10) layout.setSpacing(8) # Header header = QHBoxLayout() name = QLabel(mission.get('name', 'Unknown Mission')) name.setStyleSheet("color: #ff8c42; font-weight: bold; font-size: 12px;") header.addWidget(name) header.addStretch() # Complete button complete_btn = QPushButton("✓") complete_btn.setFixedSize(24, 24) complete_btn.setStyleSheet(""" QPushButton { background-color: rgba(76, 175, 80, 150); color: white; border: none; border-radius: 3px; font-weight: bold; } QPushButton:hover { background-color: rgba(76, 175, 80, 200); } """) complete_btn.clicked.connect(lambda: self._complete_mission(mission)) header.addWidget(complete_btn) layout.addLayout(header) # Progress current = mission.get('current', 0) total = mission.get('total', 1) pct = min(100, int(current / total * 100)) progress_layout = QHBoxLayout() progress = QProgressBar() progress.setValue(pct) progress.setTextVisible(False) progress.setFixedHeight(6) progress.setStyleSheet(""" QProgressBar { background-color: rgba(60, 70, 90, 150); border: none; border-radius: 3px; } QProgressBar::chunk { background-color: #ff8c42; border-radius: 3px; } """) progress_layout.addWidget(progress, 1) progress_text = QLabel(f"{current}/{total}") progress_text.setStyleSheet("color: rgba(255,255,255,150); font-size: 10px;") progress_layout.addWidget(progress_text) layout.addLayout(progress_layout) return card def _create_challenge_card(self, challenge): """Create a daily challenge card.""" card = QFrame() card.setStyleSheet(""" QFrame { background-color: rgba(25, 30, 40, 180); border: 1px solid rgba(80, 90, 110, 60); border-radius: 4px; } """) layout = QHBoxLayout(card) layout.setContentsMargins(10, 8, 10, 8) layout.setSpacing(10) # Icon based on type icon_mgr = get_icon_manager() icon_label = QLabel() icon_pixmap = icon_mgr.get_pixmap('sword', size=16) icon_label.setPixmap(icon_pixmap) icon_label.setFixedSize(16, 16) layout.addWidget(icon_label) # Name name = QLabel(challenge.get('name', 'Challenge')) name.setStyleSheet("color: white; font-size: 11px;") layout.addWidget(name) layout.addStretch() # Progress current = challenge.get('current', 0) total = challenge.get('total', 1) pct = min(100, int(current / total * 100)) progress = QProgressBar() progress.setValue(pct) progress.setTextVisible(False) progress.setFixedSize(60, 4) progress.setStyleSheet(""" QProgressBar { background-color: rgba(60, 70, 90, 150); border: none; border-radius: 2px; } QProgressBar::chunk { background-color: #ffc107; border-radius: 2px; } """) layout.addWidget(progress) text = QLabel(f"{current}/{total}") text.setStyleSheet("color: rgba(255,255,255,120); font-size: 10px;") layout.addWidget(text) return card def _refresh_missions(self): """Refresh mission display.""" # Clear existing while self.missions_layout.count(): item = self.missions_layout.takeAt(0) if item.widget(): item.widget().deleteLater() # Add missions for mission in self.missions: card = self._create_mission_card(mission) self.missions_layout.addWidget(card) def _refresh_daily(self): """Refresh daily challenges.""" while self.daily_layout.count(): item = self.daily_layout.takeAt(0) if item.widget(): item.widget().deleteLater() for challenge in self.daily_challenges: card = self._create_challenge_card(challenge) self.daily_layout.addWidget(card) def _add_mission(self): """Add a new mission.""" # Add sample mission self.missions.append({ 'name': 'Oratan Payback Mission III', 'current': 0, 'total': 100, 'type': 'kill', 'target': 'Oratan Prospector Bandits', 'added': datetime.now().isoformat() }) self._save_data() self._refresh_missions() def _complete_mission(self, mission): """Mark mission as complete.""" if mission in self.missions: self.missions.remove(mission) self._save_data() self._refresh_missions() def parse_chat_message(self, message): """Parse mission progress from chat.""" # Look for mission progress # Example: "Mission updated: 12/100 Oratan Prospector Bandits" for mission in self.missions: target = mission.get('target', '') if target and target in message: # Extract progress import re match = re.search(r'(\d+)/(\d+)', message) if match: mission['current'] = int(match.group(1)) mission['total'] = int(match.group(2)) self._save_data() self._refresh_missions()