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
This commit is contained in:
LemonNexus 2026-02-09 20:30:00 +00:00
parent c71f6a8647
commit 2c2249f45e
1 changed files with 102 additions and 33 deletions

View File

@ -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._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']
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(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)))
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")