""" Armor Decay Calculator for Lemontropia Suite Implements the official VU 15.15 armor decay formula. """ from decimal import Decimal from typing import Dict, Optional from dataclasses import dataclass # Armor durability database (from official guide) ARMOR_DURABILITY: Dict[str, int] = { # Unlimited Armors "Ghost": 2000, "Gremlin": 2950, "Adjusted Nemesis": 3400, "Angel": 4000, "Hero": 3500, "Dragon": 3000, "Gorgon": 4500, "Shogun": 2800, "Viking": 3200, "Titan": 3800, "Demon": 4200, "Shadow": 3600, "Warrior": 3100, "Guardian": 3300, "Sentinel": 3900, "Pirate": 2700, "Swamp": 2600, "Desert": 2900, "Arctic": 3400, "Jungle": 2500, "Mountain": 3700, "Forest": 2400, "Urban": 3500, "Combat": 4100, "Assault": 4300, "Recon": 2300, "Spec Ops": 4400, # Limited Armors "Martial (L)": 13000, "Mayhem (L)": 13300, "Angel (L)": 14000, "Perseus (L)": 15000, "Moonshine (L)": 15400, "Eon (L)": 12000, "Hermes (L)": 12500, "Tiger (L)": 11000, "Spartacus (L)": 11500, "Vain (L)": 11800, } # Default durability for unknown armors DEFAULT_DURABILITY = 2000 # Same as Ghost def calculate_armor_decay(damage_absorbed: Decimal, durability: int) -> Decimal: """Calculate armor decay in PED. Formula: Decay = damage * 0.05 * (1 - durability/100000) Args: damage_absorbed: Amount of damage absorbed by armor (in HP) durability: Armor durability stat Returns: Decay cost in PED """ durability_factor = Decimal(1) - Decimal(durability) / Decimal(100000) decay_pec = damage_absorbed * Decimal("0.05") * durability_factor return decay_pec / Decimal(100) # Convert PEC to PED def calculate_hp_per_pec(durability: int) -> Decimal: """Calculate armor economy in hp/pec. Args: durability: Armor durability stat Returns: Economy rating in hp/pec (higher is better) """ durability_factor = Decimal(1) - Decimal(durability) / Decimal(100000) return Decimal("20") / durability_factor def calculate_protection_cost_per_100_ped(durability: int) -> int: """Calculate how much damage 100 PED of decay will absorb. Args: durability: Armor durability stat Returns: Damage absorbed per 100 PED decay """ hp_per_pec = calculate_hp_per_pec(durability) return int(hp_per_pec * 10000) # 100 PED = 10,000 PEC @dataclass class ArmorPiece: """Represents a single armor piece.""" name: str slot: str # 'head', 'chest', 'arms', 'hands', 'legs', 'feet' durability: int protection_impact: Decimal = Decimal("0") protection_cut: Decimal = Decimal("0") protection_stab: Decimal = Decimal("0") protection_burn: Decimal = Decimal("0") protection_cold: Decimal = Decimal("0") protection_acid: Decimal = Decimal("0") protection_electric: Decimal = Decimal("0") def calculate_decay(self, damage_absorbed: Decimal) -> Decimal: """Calculate decay for this piece.""" return calculate_armor_decay(damage_absorbed, self.durability) def get_economy(self) -> Decimal: """Get hp/pec economy rating.""" return calculate_hp_per_pec(self.durability) @dataclass class ArmorSet: """Represents a complete armor set (7 pieces).""" name: str head: Optional[ArmorPiece] = None chest: Optional[ArmorPiece] = None left_arm: Optional[ArmorPiece] = None right_arm: Optional[ArmorPiece] = None left_hand: Optional[ArmorPiece] = None right_hand: Optional[ArmorPiece] = None legs: Optional[ArmorPiece] = None feet: Optional[ArmorPiece] = None def get_all_pieces(self) -> list: """Get list of all equipped pieces.""" pieces = [] for piece in [self.head, self.chest, self.left_arm, self.right_arm, self.left_hand, self.right_hand, self.legs, self.feet]: if piece: pieces.append(piece) return pieces def get_total_protection(self, damage_type: str = "impact") -> Decimal: """Get total protection for a damage type.""" total = Decimal("0") for piece in self.get_all_pieces(): protection = getattr(piece, f"protection_{damage_type}", Decimal("0")) total += protection return total def calculate_total_decay(self, damage_per_piece: Dict[str, Decimal]) -> Decimal: """Calculate total decay for all pieces. Args: damage_per_piece: Dict mapping slot names to damage absorbed Returns: Total decay in PED """ total_decay = Decimal("0") for piece in self.get_all_pieces(): if piece.slot in damage_per_piece: damage = damage_per_piece[piece.slot] total_decay += piece.calculate_decay(damage) return total_decay def get_armor_durability(armor_name: str) -> int: """Get durability for an armor by name. Args: armor_name: Name of the armor Returns: Durability value (defaults to 2000 if unknown) """ return ARMOR_DURABILITY.get(armor_name, DEFAULT_DURABILITY) def compare_armor_economy(armor_names: list) -> list: """Compare economy of multiple armors. Args: armor_names: List of armor names to compare Returns: List of tuples (name, durability, hp_per_pec, dmg_per_100ped) """ results = [] for name in armor_names: durability = get_armor_durability(name) hp_per_pec = calculate_hp_per_pec(durability) dmg_per_100 = calculate_protection_cost_per_100_ped(durability) results.append((name, durability, hp_per_pec, dmg_per_100)) # Sort by economy (hp/pec) descending results.sort(key=lambda x: x[2], reverse=True) return results # Example usage if __name__ == "__main__": # Compare popular armors armors = ["Ghost", "Gremlin", "Adjusted Nemesis", "Angel", "Martial (L)", "Angel (L)", "Perseus (L)"] print("Armor Economy Comparison:") print("-" * 70) print(f"{'Armor':<25} {'Dur':<8} {'hp/pec':<12} {'dmg/100PED':<12}") print("-" * 70) for name, durability, hp_per_pec, dmg_per_100 in compare_armor_economy(armors): print(f"{name:<25} {durability:<8} {hp_per_pec:<12.2f} {dmg_per_100:<12,}") # Example decay calculation print("\n\nDecay Example (15 damage absorbed):") print("-" * 50) for armor in ["Ghost", "Angel", "Martial (L)"]: durability = get_armor_durability(armor) decay = calculate_armor_decay(Decimal("15"), durability) print(f"{armor:<20} {decay:.5f} PED")