- Add safe_decimal() and safe_int() helper functions at module level
- Update NexusWeapon.from_api to use safe_decimal for all fields
- Update NexusArmor.from_api to use safe_decimal/safe_int
- Update NexusPlate.from_api to use safe_decimal
- Update NexusEnhancer.from_api to use safe_decimal/safe_int
- Remove duplicate safe_decimal definition
- This fixes decimal.ConversionSyntax errors from null/invalid API values
- weapon_selector: use ammo_burn (not ammo), range_val (not range)
- armor_selector: use id (not set_id)
- healing_selector: use get_all_healing_tools/get_all_healing_chips
- Add safe null handling for all API values
- loadout_manager_simple: use ArmorSelectorDialog (not ArmorSelectionDialog)
- weapon_selector: handle null/invalid decay/ammo values from API
- Add safe Decimal conversion with InvalidOperation handling
- Filter out weapons with invalid data before populating list
- weapon_selector.py: Simple weapon selection with cost preview
- armor_selector.py: Armor set selection with decay estimation
- healing_selector.py: Healing tool selection with economy info
- All selectors calculate cost per use in real-time
- Search/filter functionality for quick finding
- New LoadoutManagerSimple with clean cost-focused design
- LoadoutConfig now stores only: cost_per_shot/hit/heal + display names
- Legacy format support for backward compatibility
- Simplified LoadoutSelectionDialog with clear cost preview
- Updated MainWindow to use new simplified structure
- Removed 3 overlapping armor systems, replaced with single decay value
- JSON serialization is now simple and reliable
Key principle: Only store what's needed for cost tracking.
- _get_current_config now includes new armor fields
- to_dict properly serializes current_armor_decay as string
- from_dict properly deserializes new armor fields
- _set_config restores new armor fields when loading
- Armor decay now flows from LoadoutManager to session
- Added current_armor_set_name, current_armor_pieces, current_armor_protection, current_armor_decay to LoadoutConfig
- Fixed armor_set_label reference to use armor_summary_label
- Added hasattr checks for backward compatibility with old save files
- Created new ArmorSelectionDialog with two tabs:
1. Full Armor Sets: Browse and select complete sets from API
2. Custom Set: Build custom sets from individual pieces
- Armor sets show proper protection and decay per hit
- Decay calculated using official formula: 0.05 * (1 - durability/100000)
- New armor data flows correctly to session cost tracking
- Removed old hardcoded armor set methods
- Updated loadout_selected signal to emit dict with full loadout info
- _on_loadout_selected_for_session now extracts weapon/armor/healing names
- HUD now shows gear names from selected loadout
- Cost tracker skipped for JSON-based loadouts (need DB save first)
- start_session now uses _session_loadout_name for HUD display
- Added _setup_session_cost_tracker to initialize SessionCostTracker
- Added _on_cost_update callback to update HUD with live costs
- Loadout name now appears in HUD instead of 'Default'
- weapon_decay_pec is in PEC (divide by 100 to get PED)
- weapon_ammo_pec is ammo count (multiply by 0.0001 to get PED)
- armor_decay_pec is in PEC (divide by 100 to get PED)
- heal_cost_pec is in PEC (divide by 100 to get PED)
- 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
- Modified on_start_session to show LoadoutSelectionDialog first
- Added _on_loadout_selected_for_session callback
- User can now select a loadout or skip before session starts
- Selected loadout info is logged and stored for session
- AttachmentConfig.from_dict now uses safe_decimal() for all decimal fields
- Added traceback logging to _load_saved_loadouts to see exact error location
- Handles int/float/Decimal/string values for all numeric fields
- Check if pieces is a list (NexusArmorSet) or dict (ArmorSet)
- Route to API method for NexusArmorSet
- Keep hardcoded logic for ArmorSet from combo box
- Shows set protection values (Impact, Cut, Stab, etc.)
- Shows each piece's assigned total protection
- Shows first equipped piece's actual protection value
- Helps trace where protection is getting lost
- NexusArmorSet.pieces is List[str], not Dict
- Removed code that tried to call .items() on the list
- Now simply clears current_armor_set when pieces are modified
- Added debug logging to _get_current_config to see pieces found
- Added debug logging to _update_calculations to see equipped armor state
- This will help diagnose why armor shows 0 protection
- API returns 0 protection for individual armor pieces
- Protection values are only at the armor set level (Defense field)
- Now each piece gets the full set protection values assigned
- Removed equip_full_set call with wrong type (NexusArmorSet vs ArmorSet)
- Individual pieces now have correct protection for calculations
- Fixed set_piece() to use protection_label instead of non-existent piece_name_label
- Now updates protection display when piece is set
- Adds piece to combo if not already present
- Properly stores current_piece and calls _update_total()
- Added name-based slot detection as fallback when Type field doesn't match
- Added more slot mapping variations (chest, armguards, thighguards, etc.)
- Added _get_slot_from_name() helper for name-based detection
- Now correctly equips all 7 pieces of armor sets like Frontier Adjusted
- Fixed field name: API uses 'Armors' not 'Pieces'
- Fixed protection location: API uses 'Defense' not per-piece protection
- Armors is array of arrays, now properly flattened
- Added set bonus parsing from EffectsOnSetEquip
- Absorbers don't have Decay in Economy, only Absorption
- Updated parser to set decay=0 and absorption from Economy.Absorption for absorbers
- Updated UI to show absorption % in Decay column for absorbers
- Updated preview panel to display absorption for absorbers
- Removed code that was overwriting attachment_type for all items
- Type is now correctly parsed from API (scope vs sight)
- Sights tab now correctly shows items with Type='Sight'
- Fixed NexusAttachment.from_api() to parse correct API structure:
- Amplifiers: Damage values from Properties.Damage
- Scopes: Skill bonuses from Properties.SkillModification/SkillBonus, zoom from Properties.Zoom
- Absorbers: Absorption from Economy.Absorption
- Added zoom and absorption fields to NexusAttachment
- Updated attachment selector UI to show type-specific columns
- Added zoom and absorption to preview panel
- Updated from_api() to check multiple possible field names
- Added fallback checks for Damage, Range, Decay, Efficiency fields
- Type detection from both API Type field and item name
- Improved display formatting in attachment selector
- Added tabs to ArmorSelectorDialog: Individual Pieces and Full Sets
- Armor sets show total protection across all 7 pieces
- Selecting a full set auto-populates all 7 armor slots in loadout manager
- Added armor_set_selected signal for full set selection
- Shows summary of equipped pieces and any missing ones
- Added LoadoutSelectionDialog for choosing loadout when starting session
- Added set_cost_tracker() method to HUDOverlay for SessionCostTracker integration
- Added new display row for loadout metrics: $/shot, $/hit, $/heal, hits, heals
- Added mindforce cost support
- Updated start_session() to accept loadout_id and per-action costs
- Updated _refresh_display() to show new cost metrics
- Added loadouts table to schema with full gear configuration
- Created LoadoutDatabase for CRUD operations on loadouts
- Created SessionCostTracker for real-time cost tracking based on loadout
- Added cost per shot/hit/heal tracking to HUDStats
- Added mindforce cost support throughout
- Database schema updated with loadout_id foreign key in hunting_sessions
- Added mindforce_implant and mindforce_decay_pec fields
- Changed enhancers from list to Dict[int, NexusEnhancer] for tier-based system
- Updated get_total_decay_per_shot() to include enhancer and mindforce decay
- Max 10 tiers, 1 enhancer per tier
- Created ArmorSetSelectorDialog for browsing full armor sets
- Created MindforceImplantSelectorDialog for MF chips/implants
- Both dialogs integrate with Entropia Nexus API
- Filter by type, search, and preview functionality included
- Added NexusArmorSet dataclass with pieces list and total protection
- Added NexusMindforceImplant dataclass for MF chips/implants
- Added get_all_armor_sets() method using /armorsets endpoint
- Added get_all_mindforce_implants() method using /mindforceimplants endpoint
- Added cache variables for both new endpoints
- Updated AttachmentLoaderThread to fetch from separate endpoints:
- /weaponamplifiers for amplifiers
- /weaponvisionattachments for scopes
- /absorbers for absorbers
- Fixed get_all_attachments() AttributeError
- Added protection_acid and protection_electric to NexusPlate dataclass
- Updated hardcoded plates to use individual protection fields
- Fixed plate selector crash when sorting by protection
- Plates: /plates → /armorplatings
- Absorbers: Now using /absorbers (was /attachments)
- Amplifiers: Now using /weaponamplifiers (was /attachments)
- Scopes: Now using /weaponvisionattachments (was /attachments)
- Healing: Now fetches both /medicaltools AND /medicalchips
Added separate cache variables and methods for:
- _absorbers_cache, get_all_absorbers()
- _amplifiers_cache, get_all_amplifiers()
- _scopes_cache, get_all_scopes()
- _healing_chips_cache, get_all_healing_chips()
API uses MaxHeal and MinHeal directly in Properties (not nested Heal object).
Parser now correctly reads heal amounts and calculates economy.
Also added type detection for chips vs FAPs based on item name.