From 2c2249f45e10bb4082e763a9ccc7d05c2ee701f5 Mon Sep 17 00:00:00 2001 From: LemonNexus Date: Mon, 9 Feb 2026 20:30:00 +0000 Subject: [PATCH] fix: loadout selection dialog now reads from both database and JSON files - Added support for loading JSON-saved loadouts - Dialog now scans ~/.lemontropia/loadouts/ directory - Displays both database and file-based loadouts - Calculates costs from JSON data for preview --- ui/loadout_selection_dialog.py | 135 +++++++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 33 deletions(-) diff --git a/ui/loadout_selection_dialog.py b/ui/loadout_selection_dialog.py index d87ebad..dd88f2c 100644 --- a/ui/loadout_selection_dialog.py +++ b/ui/loadout_selection_dialog.py @@ -2,6 +2,8 @@ # Allows choosing a loadout when starting a new session # Standards: Python 3.11+, PyQt6, type hints +import json +from pathlib import Path from decimal import Decimal from PyQt6.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, @@ -39,6 +41,10 @@ class LoadoutSelectionDialog(QDialog): self.db = db_manager or DatabaseManager() self.loadout_db = LoadoutDatabase(self.db) + # Also check JSON files + self.config_dir = Path.home() / ".lemontropia" / "loadouts" + self.config_dir.mkdir(parents=True, exist_ok=True) + self.selected_loadout_id: Optional[int] = None self.selected_loadout_name: Optional[str] = None @@ -114,10 +120,40 @@ class LoadoutSelectionDialog(QDialog): layout.addLayout(btn_layout) def _load_loadouts(self): - """Load saved loadouts from database.""" - loadouts = self.loadout_db.list_loadouts() + """Load saved loadouts from database and JSON files.""" + self.all_loadouts = [] # Store all loadouts for lookup - if not loadouts: + # First try database + db_loadouts = self.loadout_db.list_loadouts() + for loadout in db_loadouts: + self.all_loadouts.append({ + 'id': loadout['id'], + 'name': loadout['name'], + 'source': 'db', + 'data': loadout + }) + + # Also check JSON files + try: + for filepath in sorted(self.config_dir.glob("*.json")): + try: + with open(filepath, 'r') as f: + data = json.load(f) + # Generate a unique ID based on filename + loadout_id = abs(hash(filepath.stem)) % (10 ** 9) + self.all_loadouts.append({ + 'id': loadout_id, + 'name': data.get('name', filepath.stem), + 'source': 'json', + 'filepath': str(filepath), + 'data': data + }) + except Exception as e: + print(f"Error loading {filepath}: {e}") + except Exception as e: + print(f"Error scanning config dir: {e}") + + if not self.all_loadouts: # No loadouts saved item = QListWidgetItem("No loadouts saved yet") item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsSelectable) @@ -125,28 +161,33 @@ class LoadoutSelectionDialog(QDialog): self.loadout_list.addItem(item) return - for loadout in loadouts: + # Sort by name + self.all_loadouts.sort(key=lambda x: x['name'].lower()) + + for loadout_info in self.all_loadouts: item = QListWidgetItem() - item.setText(loadout['name']) + item.setText(loadout_info['name']) + + data = loadout_info['data'] # Build tooltip with gear info - tooltip = f"Weapon: {loadout['weapon_name'] or 'None'}\n" - tooltip += f"Armor: {loadout['armor_name'] or 'None'}\n" - tooltip += f"Healing: {loadout['healing_tool_name'] or 'None'}\n" - tooltip += f"Cost/Shot: {loadout['cost_per_shot_ped']:.4f} PED\n" - tooltip += f"Cost/Hit: {loadout['cost_per_hit_ped']:.4f} PED\n" - tooltip += f"Cost/Heal: {loadout['cost_per_heal_ped']:.4f} PED" + if loadout_info['source'] == 'db': + tooltip = f"Weapon: {data.get('weapon_name') or 'None'}\n" + tooltip += f"Armor: {data.get('armor_name') or 'None'}\n" + tooltip += f"Healing: {data.get('healing_tool_name') or 'None'}\n" + tooltip += f"Cost/Shot: {data.get('cost_per_shot_ped', 0):.4f} PED\n" + tooltip += f"Cost/Hit: {data.get('cost_per_hit_ped', 0):.4f} PED\n" + tooltip += f"Cost/Heal: {data.get('cost_per_heal_ped', 0):.4f} PED" + else: + # JSON format + tooltip = f"Weapon: {data.get('weapon_name', 'None')}\n" + tooltip += f"Armor: {data.get('armor_set_name', 'None')}\n" + tooltip += f"Healing: {data.get('heal_name', 'None')}" + item.setToolTip(tooltip) - # Store loadout ID - item.setData(Qt.ItemDataRole.UserRole, loadout['id']) - - # Highlight active loadout - if loadout.get('is_active'): - item.setText(f"⭐ {loadout['name']} (Active)") - font = item.font() - font.setBold(True) - item.setFont(font) + # Store loadout info + item.setData(Qt.ItemDataRole.UserRole, loadout_info['id']) self.loadout_list.addItem(item) @@ -165,25 +206,53 @@ class LoadoutSelectionDialog(QDialog): self.ok_button.setEnabled(False) return + # Find the loadout info + loadout_info = None + for lo in self.all_loadouts: + if lo['id'] == loadout_id: + loadout_info = lo + break + + if not loadout_info: + self.ok_button.setEnabled(False) + return + self.selected_loadout_id = loadout_id - self.selected_loadout_name = item.text().replace("⭐ ", "").replace(" (Active)", "") + self.selected_loadout_name = loadout_info['name'] # Load and display preview - loadout = self.loadout_db.get_loadout(self.selected_loadout_name) - if loadout: - self._update_preview(loadout) - self.ok_button.setEnabled(True) + self._update_preview(loadout_info) + self.ok_button.setEnabled(True) - def _update_preview(self, loadout: Dict[str, Any]): + def _update_preview(self, loadout_info: Dict[str, Any]): """Update preview panel with loadout details.""" - self.preview_weapon.setText(loadout.get('weapon_name') or "None") - self.preview_armor.setText(loadout.get('armor_name') or "None") - self.preview_healing.setText(loadout.get('healing_tool_name') or "None") + data = loadout_info['data'] - # Format costs - cost_shot = Decimal(str(loadout.get('cost_per_shot_ped', 0))) - cost_hit = Decimal(str(loadout.get('cost_per_hit_ped', 0))) - cost_heal = Decimal(str(loadout.get('cost_per_heal_ped', 0))) + if loadout_info['source'] == 'db': + self.preview_weapon.setText(data.get('weapon_name') or "None") + self.preview_armor.setText(data.get('armor_name') or "None") + self.preview_healing.setText(data.get('healing_tool_name') or "None") + + # Format costs + cost_shot = Decimal(str(data.get('cost_per_shot_ped', 0))) + cost_hit = Decimal(str(data.get('cost_per_hit_ped', 0))) + cost_heal = Decimal(str(data.get('cost_per_heal_ped', 0))) + else: + # JSON format + self.preview_weapon.setText(data.get('weapon_name', "None")) + self.preview_armor.setText(data.get('armor_set_name', "None")) + self.preview_healing.setText(data.get('heal_name', "None")) + + # Try to calculate costs from JSON data + weapon_decay = Decimal(str(data.get('weapon_decay_pec', 0))) + weapon_ammo = Decimal(str(data.get('weapon_ammo_pec', 0))) + cost_shot = (weapon_decay + weapon_ammo) / Decimal("100") + + armor_decay = Decimal(str(data.get('armor_decay_pec', 0))) + cost_hit = armor_decay / Decimal("100") + + heal_cost = Decimal(str(data.get('heal_cost_pec', 0))) + cost_heal = heal_cost / Decimal("100") self.preview_cost_shot.setText(f"{cost_shot:.4f} PED") self.preview_cost_hit.setText(f"{cost_hit:.4f} PED")