Lemontropia-Suite/core/attachments.py

197 lines
6.7 KiB
Python

"""
Attachment System for Lemontropia Suite
Defines all attachment types and their compatibility with gear.
"""
from dataclasses import dataclass
from decimal import Decimal
from typing import Optional, List
@dataclass
class Attachment:
"""Base class for all attachments."""
name: str
item_id: str
decay_pec: Decimal
attachment_type: str # e.g., 'amplifier', 'scope', 'absorber'
# Effects
damage_bonus: Decimal = Decimal('0')
range_bonus: Decimal = Decimal('0')
efficiency_bonus: Decimal = Decimal('0')
def calculate_cost_per_use(self) -> Decimal:
"""Calculate cost per use in PED."""
return self.decay_pec / Decimal('100')
@dataclass
class WeaponAmplifier(Attachment):
"""Weapon amplifier attachment."""
damage_increase: Decimal = Decimal('0')
ammo_increase: int = 0
def __post_init__(self):
self.attachment_type = 'amplifier'
@dataclass
class WeaponScope(Attachment):
"""Weapon scope attachment."""
range_increase: Decimal = Decimal('0')
accuracy_bonus: Decimal = Decimal('0')
def __post_init__(self):
self.attachment_type = 'scope'
@dataclass
class WeaponAbsorber(Attachment):
"""Weapon absorber (reduces damage taken)."""
damage_reduction: Decimal = Decimal('0')
def __post_init__(self):
self.attachment_type = 'absorber'
@dataclass
class FinderAmplifier(Attachment):
"""Mining finder amplifier."""
depth_increase: Decimal = Decimal('0')
radius_increase: Decimal = Decimal('0')
def __post_init__(self):
self.attachment_type = 'finder_amp'
@dataclass
class ArmorPlating(Attachment):
"""Armor plating for increased protection."""
protection_stab: Decimal = Decimal('0')
protection_cut: Decimal = Decimal('0')
protection_impact: Decimal = Decimal('0')
protection_penetration: Decimal = Decimal('0')
protection_shrapnel: Decimal = Decimal('0')
protection_burn: Decimal = Decimal('0')
protection_cold: Decimal = Decimal('0')
protection_acid: Decimal = Decimal('0')
protection_electric: Decimal = Decimal('0')
def __post_init__(self):
self.attachment_type = 'plating'
def get_total_protection(self) -> Decimal:
"""Get total protection value."""
return (
self.protection_stab + self.protection_cut + self.protection_impact +
self.protection_penetration + self.protection_shrapnel +
self.protection_burn + self.protection_cold +
self.protection_acid + self.protection_electric
)
@dataclass
class Enhancer(Attachment):
"""Gear enhancer (adds special effects)."""
tier: int = 1
effect_name: str = ""
effect_value: Decimal = Decimal('0')
def __post_init__(self):
self.attachment_type = 'enhancer'
@dataclass
class MindforceImplant(Attachment):
"""Mindforce implant for mindforce chips."""
mindforce_bonus: Decimal = Decimal('0')
def __post_init__(self):
self.attachment_type = 'implant'
# ============================================================================
# Attachment Compatibility Rules
# ============================================================================
ATTACHMENT_COMPATIBILITY = {
'weapon': ['amplifier', 'scope', 'absorber', 'enhancer'],
'armor': ['plating', 'enhancer'],
'finder': ['finder_amp', 'enhancer'],
'mindforce': ['implant', 'enhancer'],
'tool': ['enhancer'],
}
def can_attach(gear_type: str, attachment_type: str) -> bool:
"""Check if attachment is compatible with gear type."""
compatible = ATTACHMENT_COMPATIBILITY.get(gear_type, [])
return attachment_type in compatible
def get_compatible_attachments(gear_type: str) -> List[str]:
"""Get list of compatible attachment types for gear."""
return ATTACHMENT_COMPATIBILITY.get(gear_type, [])
# ============================================================================
# Mock Attachment Data (until API is available)
# ============================================================================
MOCK_AMPLIFIERS = [
WeaponAmplifier("A101", "amp_a101", Decimal("0.05"), damage_increase=Decimal("4"), ammo_increase=10),
WeaponAmplifier("A102", "amp_a102", Decimal("0.08"), damage_increase=Decimal("6"), ammo_increase=15),
WeaponAmplifier("A103", "amp_a103", Decimal("0.12"), damage_increase=Decimal("8"), ammo_increase=20),
WeaponAmplifier("A104", "amp_a104", Decimal("0.18"), damage_increase=Decimal("12"), ammo_increase=30),
WeaponAmplifier("A105", "amp_a105", Decimal("0.25"), damage_increase=Decimal("16"), ammo_increase=40),
WeaponAmplifier("A106", "amp_a106", Decimal("0.35"), damage_increase=Decimal("20"), ammo_increase=50),
]
MOCK_SCOPES = [
WeaponScope("Longreach 4", "scope_lr4", Decimal("0.02"), range_increase=Decimal("10")),
WeaponScope("Longreach 6", "scope_lr6", Decimal("0.04"), range_increase=Decimal("15")),
WeaponScope("Longreach 8", "scope_lr8", Decimal("0.06"), range_increase=Decimal("20")),
]
MOCK_ABSORBERS = [
WeaponAbsorber("Damage II", "abs_dmg2", Decimal("0.03"), damage_reduction=Decimal("2")),
WeaponAbsorber("Damage IV", "abs_dmg4", Decimal("0.05"), damage_reduction=Decimal("4")),
]
MOCK_FINDER_AMPS = [
FinderAmplifier("DSEC L-10", "fa_dsec10", Decimal("0.10"), depth_increase=Decimal("50"), radius_increase=Decimal("5")),
FinderAmplifier("DSEC L-30", "fa_dsec30", Decimal("0.25"), depth_increase=Decimal("100"), radius_increase=Decimal("10")),
]
MOCK_PLATINGS = [
ArmorPlating("Impact Plating", "plt_impact", Decimal("0.03"), protection_impact=Decimal("3")),
ArmorPlating("Cut Plating", "plt_cut", Decimal("0.03"), protection_cut=Decimal("3")),
ArmorPlating("Burn Plating", "plt_burn", Decimal("0.03"), protection_burn=Decimal("3")),
]
MOCK_ENHANCERS = [
Enhancer("Damage Enhancer 1", "enh_dmg1", Decimal("0.10"), tier=1, effect_name="damage", effect_value=Decimal("2")),
Enhancer("Damage Enhancer 2", "enh_dmg2", Decimal("0.15"), tier=2, effect_name="damage", effect_value=Decimal("4")),
Enhancer("Economy Enhancer 1", "enh_eco1", Decimal("0.08"), tier=1, effect_name="economy", effect_value=Decimal("5")),
]
MOCK_IMPLANTS = [
MindforceImplant("NeoPsion 10", "impl_np10", Decimal("0.05"), mindforce_bonus=Decimal("10")),
MindforceImplant("NeoPsion 20", "impl_np20", Decimal("0.10"), mindforce_bonus=Decimal("20")),
]
def get_mock_attachments(attachment_type: str) -> List[Attachment]:
"""Get mock attachments by type."""
mock_data = {
'amplifier': MOCK_AMPLIFIERS,
'scope': MOCK_SCOPES,
'absorber': MOCK_ABSORBERS,
'finder_amp': MOCK_FINDER_AMPS,
'plating': MOCK_PLATINGS,
'enhancer': MOCK_ENHANCERS,
'implant': MOCK_IMPLANTS,
}
return mock_data.get(attachment_type, [])