314 lines
12 KiB
Python
314 lines
12 KiB
Python
"""
|
|
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()
|