feat(loadout): complete data model for all gear types

- LoadoutConfig now includes:
  - weapon_enhancers: List of up to 10 enhancer configs
  - armor_plates: Dict of plate configs per slot
  - left_ring, right_ring: Ring selections
  - clothing_items: List of clothing
  - pet: Selected pet

- Cost calculations updated:
  - get_total_decay_per_shot() includes enhancer decay
  - calculate_armor_cost_per_hour() includes plate decay

- Serialization updated:
  - to_dict() handles enhancers and plates
  - from_dict() handles all new fields with defaults
This commit is contained in:
LemonNexus 2026-02-09 12:05:16 +00:00
parent cf7c4ab5de
commit 78234da448
1 changed files with 56 additions and 5 deletions

View File

@ -102,10 +102,16 @@ class LoadoutConfig:
weapon_scope: Optional[AttachmentConfig] = None
weapon_absorber: Optional[AttachmentConfig] = None
# Weapon Enhancers (up to 10 slots)
weapon_enhancers: List[AttachmentConfig] = field(default_factory=list)
# Armor System
equipped_armor: Optional[EquippedArmor] = None
armor_set_name: str = "-- None --"
# Armor Plates (per slot)
armor_plates: Dict[str, AttachmentConfig] = field(default_factory=dict)
# Legacy armor fields for backward compatibility
armor_name: str = "-- None --"
armor_id: int = 0
@ -125,6 +131,12 @@ class LoadoutConfig:
heal_cost_pec: Decimal = Decimal("2.0")
heal_amount: Decimal = Decimal("20")
# Accessories
left_ring: Optional[str] = None
right_ring: Optional[str] = None
clothing_items: List[str] = field(default_factory=list)
pet: Optional[str] = None
# Settings
shots_per_hour: int = 3600
hits_per_hour: int = 720
@ -138,7 +150,7 @@ class LoadoutConfig:
return base
def get_total_decay_per_shot(self) -> Decimal:
"""Calculate total decay per shot including attachments."""
"""Calculate total decay per shot including attachments and enhancers."""
total = self.weapon_decay_pec
if self.weapon_amplifier:
total += self.weapon_amplifier.decay_pec
@ -146,6 +158,9 @@ class LoadoutConfig:
total += self.weapon_scope.decay_pec
if self.weapon_absorber:
total += self.weapon_absorber.decay_pec
# Add enhancer decay (assuming 1 use per shot)
for enhancer in self.weapon_enhancers:
total += enhancer.decay_pec
return total
def get_total_ammo_per_shot(self) -> Decimal:
@ -169,11 +184,19 @@ class LoadoutConfig:
return cost_per_shot * Decimal(self.shots_per_hour)
def calculate_armor_cost_per_hour(self) -> Decimal:
"""Calculate armor cost per hour using the equipped armor system."""
"""Calculate armor cost per hour including plates."""
base_cost = Decimal("0")
if self.equipped_armor:
return self.equipped_armor.get_total_decay_per_hit() * Decimal(self.hits_per_hour)
# Legacy fallback
return self.armor_decay_pec * Decimal(self.hits_per_hour)
base_cost = self.equipped_armor.get_total_decay_per_hit() * Decimal(self.hits_per_hour)
else:
# Legacy fallback
base_cost = self.armor_decay_pec * Decimal(self.hits_per_hour)
# Add plate decay costs
for slot, plate_config in self.armor_plates.items():
base_cost += plate_config.decay_pec * Decimal(self.hits_per_hour)
return base_cost
def calculate_heal_cost_per_hour(self) -> Decimal:
"""Calculate healing cost per hour."""
@ -229,6 +252,12 @@ class LoadoutConfig:
data['weapon_scope'] = self.weapon_scope.to_dict()
if self.weapon_absorber:
data['weapon_absorber'] = self.weapon_absorber.to_dict()
# Handle weapon enhancers
if self.weapon_enhancers:
data['weapon_enhancers'] = [e.to_dict() for e in self.weapon_enhancers]
# Handle armor plates
if self.armor_plates:
data['armor_plates'] = {k: v.to_dict() for k, v in self.armor_plates.items()}
# Handle equipped armor
if self.equipped_armor:
data['equipped_armor'] = self.equipped_armor.to_dict()
@ -271,6 +300,28 @@ class LoadoutConfig:
else:
data['weapon_absorber'] = None
# Handle weapon enhancers
if 'weapon_enhancers' in data and data['weapon_enhancers']:
data['weapon_enhancers'] = [AttachmentConfig.from_dict(e) for e in data['weapon_enhancers']]
else:
data['weapon_enhancers'] = []
# Handle armor plates
if 'armor_plates' in data and data['armor_plates']:
data['armor_plates'] = {k: AttachmentConfig.from_dict(v) for k, v in data['armor_plates'].items()}
else:
data['armor_plates'] = {}
# Handle accessories
if 'clothing_items' not in data:
data['clothing_items'] = []
if 'left_ring' not in data:
data['left_ring'] = None
if 'right_ring' not in data:
data['right_ring'] = None
if 'pet' not in data:
data['pet'] = None
# Handle equipped armor
if 'equipped_armor' in data and data['equipped_armor']:
data['equipped_armor'] = EquippedArmor.from_dict(data['equipped_armor'])