""" Enhancer Selector for Lemontropia Suite Browse and search weapon/armor enhancers """ from decimal import Decimal from PyQt6.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QTreeWidget, QTreeWidgetItem, QHeaderView, QLabel, QDialogButtonBox, QProgressBar, QGroupBox, QFormLayout, QComboBox, QCheckBox ) from PyQt6.QtCore import Qt, QThread, pyqtSignal from PyQt6.QtGui import QColor from typing import Optional, List from core.nexus_full_api import get_nexus_api, NexusEnhancer class EnhancerLoaderThread(QThread): """Background thread for loading enhancers from API.""" enhancers_loaded = pyqtSignal(list) error_occurred = pyqtSignal(str) def run(self): try: api = get_nexus_api() enhancers = api.get_all_enhancers() self.enhancers_loaded.emit(enhancers) except Exception as e: self.error_occurred.emit(str(e)) class EnhancerSelectorDialog(QDialog): """Dialog for selecting enhancers from Entropia Nexus API.""" enhancer_selected = pyqtSignal(NexusEnhancer) def __init__(self, parent=None, enhancer_type: str = "", target_tier: int = 1): super().__init__(parent) self.preferred_type = enhancer_type.lower() self.target_tier = target_tier type_names = { "damage": "Damage Enhancer", "economy": "Economy Enhancer", "range": "Range Enhancer", "accuracy": "Accuracy Enhancer", "skillmod": "Skill Mod Enhancer" } title_type = type_names.get(self.preferred_type, "Enhancer") self.setWindowTitle(f"Select {title_type} - Entropia Nexus") self.setMinimumSize(900, 600) self.all_enhancers: List[NexusEnhancer] = [] self.selected_enhancer: Optional[NexusEnhancer] = None self._setup_ui() self._load_data() def _setup_ui(self): layout = QVBoxLayout(self) layout.setSpacing(10) # Warning about enhancer breakage warning = QLabel("⚠️ Warning: Enhancers have a chance to break on each use!") warning.setStyleSheet("color: #ff9800; font-weight: bold; padding: 5px;") layout.addWidget(warning) # Status self.status_label = QLabel("Loading enhancers from Entropia Nexus...") layout.addWidget(self.status_label) self.progress = QProgressBar() self.progress.setRange(0, 0) layout.addWidget(self.progress) # Filters filter_layout = QHBoxLayout() filter_layout.addWidget(QLabel("Type:")) self.type_combo = QComboBox() self.type_combo.addItems([ "All Types", "Damage", "Economy", "Range", "Accuracy", "Skill Mod", "Defense", "Durability" ]) if self.preferred_type: # Map type names type_map = { "damage": "Damage", "economy": "Economy", "range": "Range", "accuracy": "Accuracy", "skillmod": "Skill Mod" } preferred = type_map.get(self.preferred_type, "") index = self.type_combo.findText(preferred) if index >= 0: self.type_combo.setCurrentIndex(index) self.type_combo.currentTextChanged.connect(self._apply_filters) filter_layout.addWidget(self.type_combo) filter_layout.addWidget(QLabel("Tier:")) self.tier_combo = QComboBox() self.tier_combo.addItems(["All Tiers", "Tier 1", "Tier 2", "Tier 3", "Tier 4", "Tier 5+"]) if self.target_tier > 0 and self.target_tier <= 5: self.tier_combo.setCurrentIndex(self.target_tier) self.tier_combo.currentTextChanged.connect(self._apply_filters) filter_layout.addWidget(self.tier_combo) # Show breakable only self.breakable_check = QCheckBox("Show breakable only") self.breakable_check.setChecked(False) self.breakable_check.stateChanged.connect(self._apply_filters) filter_layout.addWidget(self.breakable_check) layout.addLayout(filter_layout) # Search search_layout = QHBoxLayout() search_layout.addWidget(QLabel("Search:")) self.search_input = QLineEdit() self.search_input.setPlaceholderText("Search enhancers...") self.search_input.textChanged.connect(self._apply_filters) search_layout.addWidget(self.search_input) self.clear_btn = QPushButton("Clear") self.clear_btn.clicked.connect(self._clear_search) search_layout.addWidget(self.clear_btn) layout.addLayout(search_layout) # Results tree self.results_tree = QTreeWidget() self.results_tree.setHeaderLabels([ "Name", "Type", "Tier", "Effect", "Break Chance", "Risk Level" ]) header = self.results_tree.header() header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) header.setStretchLastSection(False) self.results_tree.itemSelectionChanged.connect(self._on_selection_changed) self.results_tree.itemDoubleClicked.connect(self._on_double_click) layout.addWidget(self.results_tree) # Preview panel self.preview_group = QGroupBox("Enhancer Preview") preview_layout = QFormLayout(self.preview_group) self.preview_name = QLabel("-") self.preview_type = QLabel("-") self.preview_tier = QLabel("-") self.preview_effect = QLabel("-") self.preview_break = QLabel("-") preview_layout.addRow("Name:", self.preview_name) preview_layout.addRow("Type:", self.preview_type) preview_layout.addRow("Tier:", self.preview_tier) preview_layout.addRow("Effect:", self.preview_effect) preview_layout.addRow("Break Chance:", self.preview_break) layout.addWidget(self.preview_group) # Buttons buttons = QDialogButtonBox( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel ) buttons.accepted.connect(self._on_accept) buttons.rejected.connect(self.reject) self.ok_button = buttons.button(QDialogButtonBox.StandardButton.Ok) self.ok_button.setEnabled(False) layout.addWidget(buttons) def _load_data(self): """Load enhancers in background thread.""" self.loader = EnhancerLoaderThread() self.loader.enhancers_loaded.connect(self._on_enhancers_loaded) self.loader.error_occurred.connect(self._on_load_error) self.loader.start() def _on_enhancers_loaded(self, enhancers: List[NexusEnhancer]): """Handle loaded enhancers.""" self.all_enhancers = enhancers self.status_label.setText(f"Loaded {len(enhancers)} enhancers from Entropia Nexus") self.progress.setRange(0, 100) self.progress.setValue(100) self._apply_filters() def _on_load_error(self, error: str): """Handle load error.""" self.status_label.setText(f"Error loading enhancers: {error}") self.progress.setRange(0, 100) self.progress.setValue(0) def _apply_filters(self): """Apply all filters and search.""" enhancers = self.all_enhancers.copy() # Type filter type_filter = self.type_combo.currentText() if type_filter != "All Types": type_lower = type_filter.lower().replace(" ", "") enhancers = [e for e in enhancers if type_lower in e.enhancer_type.lower()] # Tier filter tier_filter = self.tier_combo.currentText() if tier_filter != "All Tiers": if tier_filter == "Tier 5+": enhancers = [e for e in enhancers if e.tier >= 5] else: tier_num = int(tier_filter.replace("Tier ", "")) enhancers = [e for e in enhancers if e.tier == tier_num] # Breakable filter if self.breakable_check.isChecked(): enhancers = [e for e in enhancers if e.break_chance > 0] # Search filter search_text = self.search_input.text() if search_text: query = search_text.lower() enhancers = [e for e in enhancers if query in e.name.lower()] self._populate_results(enhancers) # Update status if search_text: self.status_label.setText(f"Found {len(enhancers)} enhancers matching '{search_text}'") else: self.status_label.setText(f"Showing {len(enhancers)} of {len(self.all_enhancers)} enhancers") def _populate_results(self, enhancers: List[NexusEnhancer]): """Populate results tree.""" self.results_tree.clear() # Sort by tier (lowest first - safer) then effect value enhancers = sorted(enhancers, key=lambda e: (e.tier, -e.effect_value)) for enhancer in enhancers: item = QTreeWidgetItem() item.setText(0, enhancer.name) item.setText(1, enhancer.enhancer_type.title()) item.setText(2, str(enhancer.tier)) item.setText(3, f"+{enhancer.effect_value}%") item.setText(4, f"{enhancer.break_chance * 100:.1f}%") # Risk level if enhancer.break_chance <= 0.01: risk = "Low" color = QColor("#4caf50") # Green elif enhancer.break_chance <= 0.05: risk = "Medium" color = QColor("#ff9800") # Orange else: risk = "High" color = QColor("#f44336") # Red item.setText(5, risk) item.setForeground(5, color) # Color code tier tier_colors = { 1: QColor("#4caf50"), # Green 2: QColor("#8bc34a"), # Light green 3: QColor("#ff9800"), # Orange 4: QColor("#ff5722"), # Deep orange 5: QColor("#f44336"), # Red } if enhancer.tier in tier_colors: item.setForeground(2, tier_colors[enhancer.tier]) item.setData(0, Qt.ItemDataRole.UserRole, enhancer) self.results_tree.addTopLevelItem(item) def _clear_search(self): """Clear search and filters.""" self.search_input.clear() self.type_combo.setCurrentIndex(0) self.tier_combo.setCurrentIndex(0) self.breakable_check.setChecked(False) self._apply_filters() def _on_selection_changed(self): """Handle selection change.""" items = self.results_tree.selectedItems() if items: self.selected_enhancer = items[0].data(0, Qt.ItemDataRole.UserRole) self.ok_button.setEnabled(True) self._update_preview(self.selected_enhancer) else: self.selected_enhancer = None self.ok_button.setEnabled(False) def _update_preview(self, enhancer: NexusEnhancer): """Update preview panel.""" self.preview_name.setText(enhancer.name) self.preview_type.setText(enhancer.enhancer_type.title()) self.preview_tier.setText(str(enhancer.tier)) self.preview_effect.setText(f"+{enhancer.effect_value}%") self.preview_break.setText(f"{enhancer.break_chance * 100:.1f}%") # Color code break chance if enhancer.break_chance <= 0.01: self.preview_break.setStyleSheet("color: #4caf50;") # Green elif enhancer.break_chance <= 0.05: self.preview_break.setStyleSheet("color: #ff9800;") # Orange else: self.preview_break.setStyleSheet("color: #f44336;") # Red def _on_double_click(self, item, column): """Handle double click.""" self._on_accept() def _on_accept(self): """Handle OK button.""" if self.selected_enhancer: self.enhancer_selected.emit(self.selected_enhancer) self.accept()