diff --git a/ui/loadout_manager_simple.py b/ui/loadout_manager_simple.py index 30c92ee..eb55cb7 100644 --- a/ui/loadout_manager_simple.py +++ b/ui/loadout_manager_simple.py @@ -389,9 +389,9 @@ class LoadoutManagerDialog(QDialog): def _select_armor(self): """Open simplified armor selector.""" - from ui.armor_selection_dialog import ArmorSelectionDialog + from ui.armor_selector import ArmorSelectorDialog - dialog = ArmorSelectionDialog(self) + dialog = ArmorSelectorDialog(self) if dialog.exec() == QDialog.DialogCode.Accepted: result = dialog.get_selected_armor() if result: diff --git a/ui/weapon_selector.py b/ui/weapon_selector.py index acc59c0..84037e6 100644 --- a/ui/weapon_selector.py +++ b/ui/weapon_selector.py @@ -4,7 +4,7 @@ Quick weapon selection for cost configuration. """ import logging -from decimal import Decimal +from decimal import Decimal, InvalidOperation from PyQt6.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QLabel, @@ -105,7 +105,22 @@ class WeaponSelectorDialog(QDialog): """Load weapons from API.""" try: nexus = get_nexus_api() - self._weapons = nexus.get_all_weapons() + all_weapons = nexus.get_all_weapons() + + # Filter out weapons with invalid/null decay or ammo + self._weapons = [] + for w in all_weapons: + try: + # Validate that decay and ammo are valid numbers + decay_val = w.decay if w.decay is not None else 0 + ammo_val = w.ammo if w.ammo is not None else 0 + # Try to convert to Decimal to validate + Decimal(str(decay_val)) + Decimal(str(ammo_val)) + self._weapons.append(w) + except (InvalidOperation, ValueError, TypeError): + # Skip weapons with invalid data + continue # Sort by name self._weapons.sort(key=lambda w: w.name.lower()) @@ -120,25 +135,34 @@ class WeaponSelectorDialog(QDialog): self.weapon_list.clear() for weapon in weapons: - # Calculate cost per shot - decay_pec = Decimal(str(weapon.decay)) - ammo = Decimal(str(weapon.ammo)) - cost_per_shot = (decay_pec / Decimal("100")) + (ammo * Decimal("0.0001")) - - item = QListWidgetItem(f"{weapon.name} (💰 {cost_per_shot:.4f} PED)") - item.setData(Qt.ItemDataRole.UserRole, weapon) - - # Tooltip - tooltip = ( - f"Damage: {weapon.damage}\n" - f"Decay: {weapon.decay} PEC\n" - f"Ammo: {weapon.ammo}\n" - f"Range: {weapon.range}\n" - f"DPP: {weapon.dpp:.2f}" - ) - item.setToolTip(tooltip) - - self.weapon_list.addItem(item) + try: + # Get values with safe defaults + decay_raw = weapon.decay if weapon.decay is not None else 0 + ammo_raw = weapon.ammo if weapon.ammo is not None else 0 + + # Calculate cost per shot + decay_pec = Decimal(str(decay_raw)) + ammo = Decimal(str(ammo_raw)) + cost_per_shot = (decay_pec / Decimal("100")) + (ammo * Decimal("0.0001")) + + item = QListWidgetItem(f"{weapon.name} (💰 {cost_per_shot:.4f} PED)") + item.setData(Qt.ItemDataRole.UserRole, weapon) + + # Tooltip + tooltip = ( + f"Damage: {weapon.damage}\n" + f"Decay: {decay_raw} PEC\n" + f"Ammo: {ammo_raw}\n" + f"Range: {weapon.range}\n" + f"DPP: {weapon.dpp:.2f}" if weapon.dpp else "DPP: -" + ) + item.setToolTip(tooltip) + + self.weapon_list.addItem(item) + except Exception as e: + # Skip weapons that fail to process + logger.debug(f"Skipping weapon {getattr(weapon, 'name', 'unknown')}: {e}") + continue def _on_search(self, text): """Filter weapons by search text.""" @@ -158,6 +182,24 @@ class WeaponSelectorDialog(QDialog): self.selected_weapon = weapon + # Get values with safe defaults + decay_raw = weapon.decay if weapon.decay is not None else 0 + ammo_raw = weapon.ammo if weapon.ammo is not None else 0 + + # Calculate cost per shot + decay_pec = Decimal(str(decay_raw)) + ammo = Decimal(str(ammo_raw)) + cost_per_shot = (decay_pec / Decimal("100")) + (ammo * Decimal("0.0001")) + + # Update preview + self.preview_name.setText(weapon.name) + self.preview_damage.setText(str(weapon.damage) if weapon.damage is not None else "-") + self.preview_decay.setText(f"{decay_raw} PEC") + self.preview_ammo.setText(str(ammo_raw)) + self.preview_cost.setText(f"{cost_per_shot:.4f} PED") + + self.ok_btn.setEnabled(True) + # Calculate cost per shot decay_pec = Decimal(str(weapon.decay)) ammo = Decimal(str(weapon.ammo))