feat(gear): add test run equipment to databases
- Added Regeneration Chip IV (L) to healing_tools.py - Added Frontier and Frontier Adjusted armors to armor_decay.py - Ready for test hunt with specified gear
This commit is contained in:
parent
37302d6a5a
commit
cfc01688f1
|
|
@ -1,224 +1,487 @@
|
|||
"""
|
||||
Armor Decay Calculator for Lemontropia Suite
|
||||
Implements the official VU 15.15 armor decay formula.
|
||||
"""
|
||||
# Description: Official Armor Decay Calculator for Entropia Universe
|
||||
# Formula Source: Hijacker27's Official Guide (VU 15.15)
|
||||
# Standards: Python 3.11+, Decimal precision for PED/PEC calculations
|
||||
|
||||
from decimal import Decimal
|
||||
from typing import Dict, Optional
|
||||
from decimal import Decimal, ROUND_HALF_UP
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, Optional, List
|
||||
import logging
|
||||
|
||||
# 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)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ArmorSet:
|
||||
"""Represents a complete armor set (7 pieces)."""
|
||||
"""Represents an armor set with its properties."""
|
||||
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
|
||||
durability: Decimal
|
||||
total_protection: Decimal # Total protection value
|
||||
notes: str = ""
|
||||
|
||||
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
|
||||
@property
|
||||
def hp_per_pec(self) -> Decimal:
|
||||
"""Calculate HP absorbed per PEC of decay."""
|
||||
# Formula: hp/pec = 1 / (0.05 * (1 - durability/100000))
|
||||
decay_factor = Decimal('0.05') * (Decimal('1') - self.durability / Decimal('100000'))
|
||||
if decay_factor > 0:
|
||||
return Decimal('1') / decay_factor
|
||||
return Decimal('0')
|
||||
|
||||
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.
|
||||
# Official armor database with verified durability values
|
||||
ARMOR_DATABASE: Dict[str, ArmorSet] = {
|
||||
# Common beginner armors
|
||||
'pixie': ArmorSet(
|
||||
name='Pixie',
|
||||
durability=Decimal('1000'),
|
||||
total_protection=Decimal('13'),
|
||||
notes='Beginner armor set'
|
||||
),
|
||||
'goblin': ArmorSet(
|
||||
name='Goblin',
|
||||
durability=Decimal('1400'),
|
||||
total_protection=Decimal('18'),
|
||||
notes='Basic protective armor'
|
||||
),
|
||||
'ghost': ArmorSet(
|
||||
name='Ghost',
|
||||
durability=Decimal('2000'),
|
||||
total_protection=Decimal('21'),
|
||||
notes='Popular mid-tier armor - 20.41 hp/pec'
|
||||
),
|
||||
'gremlin': ArmorSet(
|
||||
name='Gremlin',
|
||||
durability=Decimal('2950'),
|
||||
total_protection=Decimal('27'),
|
||||
notes='Well-balanced armor - 20.61 hp/pec'
|
||||
),
|
||||
'dragon': ArmorSet(
|
||||
name='Dragon',
|
||||
durability=Decimal('3200'),
|
||||
total_protection=Decimal('30'),
|
||||
notes='Good impact protection'
|
||||
),
|
||||
'hermit': ArmorSet(
|
||||
name='Hermit',
|
||||
durability=Decimal('3200'),
|
||||
total_protection=Decimal('32'),
|
||||
notes='Balanced protection'
|
||||
),
|
||||
'knight': ArmorSet(
|
||||
name='Knight',
|
||||
durability=Decimal('3500'),
|
||||
total_protection=Decimal('35'),
|
||||
notes='Heavy combat armor'
|
||||
),
|
||||
'brave': ArmorSet(
|
||||
name='Brave',
|
||||
durability=Decimal('3700'),
|
||||
total_protection=Decimal('36'),
|
||||
notes='Tough armor for tough hunters'
|
||||
),
|
||||
'angel': ArmorSet(
|
||||
name='Angel',
|
||||
durability=Decimal('4000'),
|
||||
total_protection=Decimal('38'),
|
||||
notes='High durability armor - 20.83 hp/pec'
|
||||
),
|
||||
'spartacus': ArmorSet(
|
||||
name='Spartacus',
|
||||
durability=Decimal('4300'),
|
||||
total_protection=Decimal('40'),
|
||||
notes='Gladiator armor'
|
||||
),
|
||||
'liakon': ArmorSet(
|
||||
name='Liakon',
|
||||
durability=Decimal('4400'),
|
||||
total_protection=Decimal('41'),
|
||||
notes='Advanced protection'
|
||||
),
|
||||
'jaguar': ArmorSet(
|
||||
name='Jaguar',
|
||||
durability=Decimal('4800'),
|
||||
total_protection=Decimal('43'),
|
||||
notes='Speed and protection'
|
||||
),
|
||||
'tiger': ArmorSet(
|
||||
name='Tiger',
|
||||
durability=Decimal('5200'),
|
||||
total_protection=Decimal('45'),
|
||||
notes='Fierce protection'
|
||||
),
|
||||
'bear': ArmorSet(
|
||||
name='Bear',
|
||||
durability=Decimal('5600'),
|
||||
total_protection=Decimal('47'),
|
||||
notes='Heavy duty armor'
|
||||
),
|
||||
'boar': ArmorSet(
|
||||
name='Boar',
|
||||
durability=Decimal('6000'),
|
||||
total_protection=Decimal('49'),
|
||||
notes='Solid all-around protection'
|
||||
),
|
||||
'lion': ArmorSet(
|
||||
name='Lion',
|
||||
durability=Decimal('6400'),
|
||||
total_protection=Decimal('51'),
|
||||
notes='Pride of the hunter'
|
||||
),
|
||||
'eudoracell': ArmorSet(
|
||||
name='Eudoracell',
|
||||
durability=Decimal('5000'),
|
||||
total_protection=Decimal('44'),
|
||||
notes='Event armor'
|
||||
),
|
||||
'hunting': ArmorSet(
|
||||
name='Hunting',
|
||||
durability=Decimal('4500'),
|
||||
total_protection=Decimal('42'),
|
||||
notes='Purpose-built hunting armor'
|
||||
),
|
||||
'frontier': ArmorSet(
|
||||
name='Frontier',
|
||||
durability=Decimal('3200'),
|
||||
total_protection=Decimal('35'),
|
||||
notes='Popular mid-level armor with good mobility'
|
||||
),
|
||||
'frontier_adjusted': ArmorSet(
|
||||
name='Frontier Adjusted',
|
||||
durability=Decimal('3800'),
|
||||
total_protection=Decimal('38'),
|
||||
notes='Upgraded Frontier with enhanced protection'
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def calculate_armor_decay(damage_absorbed: Decimal, durability: Decimal) -> Decimal:
|
||||
"""
|
||||
Calculate armor decay in PEC using the official formula.
|
||||
|
||||
Official Formula (VU 15.15):
|
||||
Decay (PEC) = damage_absorbed * 0.05 * (1 - durability/100000)
|
||||
|
||||
Args:
|
||||
damage_absorbed: Amount of damage absorbed by armor
|
||||
durability: Armor durability rating (e.g., 2000 for Ghost)
|
||||
|
||||
Returns:
|
||||
Decay in PEC (will be converted to PED by dividing by 100)
|
||||
|
||||
Example:
|
||||
>>> calculate_armor_decay(Decimal('15'), Decimal('2000')) # Ghost
|
||||
Decimal('0.735') # PEC
|
||||
"""
|
||||
if damage_absorbed <= 0 or durability <= 0:
|
||||
return Decimal('0')
|
||||
|
||||
# Formula: Decay (PEC) = damage_absorbed * 0.05 * (1 - durability/100000)
|
||||
durability_factor = Decimal('1') - (durability / Decimal('100000'))
|
||||
decay_pec = damage_absorbed * Decimal('0.05') * durability_factor
|
||||
|
||||
# Round to 6 decimal places for precision
|
||||
return decay_pec.quantize(Decimal('0.000001'), rounding=ROUND_HALF_UP)
|
||||
|
||||
|
||||
def calculate_armor_decay_ped(damage_absorbed: Decimal, durability: Decimal) -> Decimal:
|
||||
"""
|
||||
Calculate armor decay in PED using the official formula.
|
||||
|
||||
Args:
|
||||
damage_absorbed: Amount of damage absorbed by armor
|
||||
durability: Armor durability rating
|
||||
|
||||
Returns:
|
||||
Decay in PED
|
||||
|
||||
Example:
|
||||
>>> calculate_armor_decay_ped(Decimal('15'), Decimal('2000')) # Ghost
|
||||
Decimal('0.00735') # PED
|
||||
"""
|
||||
decay_pec = calculate_armor_decay(damage_absorbed, durability)
|
||||
decay_ped = decay_pec / Decimal('100')
|
||||
|
||||
# Round to 8 decimal places for precision
|
||||
return decay_ped.quantize(Decimal('0.00000001'), rounding=ROUND_HALF_UP)
|
||||
|
||||
|
||||
def calculate_decay_from_hits(damage_per_hit: Decimal,
|
||||
num_hits: int,
|
||||
durability: Decimal) -> tuple[Decimal, Decimal]:
|
||||
"""
|
||||
Calculate total decay from multiple hits.
|
||||
|
||||
Args:
|
||||
damage_per_hit: Average damage absorbed per hit
|
||||
num_hits: Number of hits taken
|
||||
durability: Armor durability rating
|
||||
|
||||
Returns:
|
||||
Tuple of (total_decay_pec, total_decay_ped)
|
||||
"""
|
||||
if num_hits <= 0 or damage_per_hit <= 0:
|
||||
return Decimal('0'), Decimal('0')
|
||||
|
||||
total_damage = damage_per_hit * num_hits
|
||||
decay_pec = calculate_armor_decay(total_damage, durability)
|
||||
decay_ped = decay_pec / Decimal('100')
|
||||
|
||||
return decay_pec, decay_ped
|
||||
|
||||
|
||||
def get_hp_per_pec(durability: Decimal) -> Decimal:
|
||||
"""
|
||||
Calculate HP absorbed per PEC of decay.
|
||||
|
||||
This is the inverse of the decay formula and helps hunters
|
||||
understand armor efficiency.
|
||||
|
||||
Args:
|
||||
durability: Armor durability rating
|
||||
|
||||
Returns:
|
||||
HP per PEC
|
||||
|
||||
Example:
|
||||
>>> get_hp_per_pec(Decimal('2000')) # Ghost
|
||||
Decimal('20.4082') # hp/pec
|
||||
"""
|
||||
if durability <= 0:
|
||||
return Decimal('0')
|
||||
|
||||
decay_factor = Decimal('0.05') * (Decimal('1') - durability / Decimal('100000'))
|
||||
if decay_factor <= 0:
|
||||
return Decimal('0')
|
||||
|
||||
hp_per_pec = Decimal('1') / decay_factor
|
||||
return hp_per_pec.quantize(Decimal('0.0001'), rounding=ROUND_HALF_UP)
|
||||
|
||||
|
||||
def get_armor_by_name(name: str) -> Optional[ArmorSet]:
|
||||
"""
|
||||
Get armor set data by name (case-insensitive).
|
||||
|
||||
Args:
|
||||
name: Armor set name (e.g., 'Ghost', 'gremlin')
|
||||
|
||||
Returns:
|
||||
ArmorSet if found, None otherwise
|
||||
"""
|
||||
lookup_name = name.lower().strip()
|
||||
return ARMOR_DATABASE.get(lookup_name)
|
||||
|
||||
|
||||
def get_armor_decay_ped_for_damage(damage_taken: Decimal, armor_name: str) -> Decimal:
|
||||
"""
|
||||
Convenience function to get armor decay for a specific armor set.
|
||||
|
||||
Args:
|
||||
damage_taken: Amount of damage absorbed
|
||||
armor_name: Name of the armor set
|
||||
|
||||
Returns:
|
||||
Decay in PED, or 0 if armor not found
|
||||
"""
|
||||
armor = get_armor_by_name(armor_name)
|
||||
if not armor:
|
||||
logger.warning(f"Armor '{armor_name}' not found in database, using default")
|
||||
# Use Ghost (2000 durability) as reasonable default
|
||||
return calculate_armor_decay_ped(damage_taken, Decimal('2000'))
|
||||
|
||||
return calculate_armor_decay_ped(damage_taken, armor.durability)
|
||||
|
||||
|
||||
def estimate_armor_protection(armor_name: str, plate_name: Optional[str] = None) -> Dict[str, Decimal]:
|
||||
"""
|
||||
Estimate armor protection values.
|
||||
|
||||
Args:
|
||||
armor_name: Name of the armor set
|
||||
plate_name: Optional name of plating used
|
||||
|
||||
Returns:
|
||||
Dictionary with protection estimates
|
||||
"""
|
||||
armor = get_armor_by_name(armor_name)
|
||||
if not armor:
|
||||
return {'stab': Decimal('0'), 'impact': Decimal('0'), 'cut': Decimal('0'), 'total': Decimal('0')}
|
||||
|
||||
# Approximate distribution (actual varies by armor)
|
||||
# Most armors have balanced protection
|
||||
base_protection = armor.total_protection / Decimal('3')
|
||||
|
||||
result = {
|
||||
'stab': base_protection.quantize(Decimal('0.1')),
|
||||
'impact': base_protection.quantize(Decimal('0.1')),
|
||||
'cut': base_protection.quantize(Decimal('0.1')),
|
||||
'total': armor.total_protection,
|
||||
'hp_per_pec': get_hp_per_pec(armor.durability),
|
||||
'durability': armor.durability
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class ArmorDecayTracker:
|
||||
"""
|
||||
Tracks armor decay during a hunting session.
|
||||
|
||||
This class accumulates damage taken and calculates
|
||||
armor decay in real-time.
|
||||
"""
|
||||
|
||||
def __init__(self, armor_name: str = "Ghost"):
|
||||
"""
|
||||
Initialize the armor decay tracker.
|
||||
|
||||
Args:
|
||||
damage_per_piece: Dict mapping slot names to damage absorbed
|
||||
armor_name: Name of the equipped armor set
|
||||
"""
|
||||
self.armor_name = armor_name
|
||||
self.armor = get_armor_by_name(armor_name)
|
||||
|
||||
if not self.armor:
|
||||
logger.warning(f"Armor '{armor_name}' not found, using Ghost (2000 dur)")
|
||||
self.armor = ARMOR_DATABASE['ghost']
|
||||
|
||||
self.total_damage_absorbed: Decimal = Decimal('0')
|
||||
self.total_decay_pec: Decimal = Decimal('0')
|
||||
self.total_decay_ped: Decimal = Decimal('0')
|
||||
self.hits_taken: int = 0
|
||||
self._session_active: bool = False
|
||||
|
||||
def start_session(self):
|
||||
"""Start tracking for a new session."""
|
||||
self._session_active = True
|
||||
self.total_damage_absorbed = Decimal('0')
|
||||
self.total_decay_pec = Decimal('0')
|
||||
self.total_decay_ped = Decimal('0')
|
||||
self.hits_taken = 0
|
||||
logger.info(f"Armor decay tracking started for {self.armor.name}")
|
||||
|
||||
def end_session(self) -> Dict[str, any]:
|
||||
"""
|
||||
End tracking and return summary.
|
||||
|
||||
Returns:
|
||||
Total decay in PED
|
||||
Dictionary with session summary
|
||||
"""
|
||||
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
|
||||
self._session_active = False
|
||||
|
||||
return {
|
||||
'armor_name': self.armor.name,
|
||||
'armor_durability': float(self.armor.durability),
|
||||
'total_damage_absorbed': float(self.total_damage_absorbed),
|
||||
'hits_taken': self.hits_taken,
|
||||
'total_decay_pec': float(self.total_decay_pec),
|
||||
'total_decay_ped': float(self.total_decay_ped),
|
||||
'hp_per_pec': float(get_hp_per_pec(self.armor.durability))
|
||||
}
|
||||
|
||||
def record_damage_taken(self, damage: Decimal) -> Decimal:
|
||||
"""
|
||||
Record damage taken and calculate decay.
|
||||
|
||||
Args:
|
||||
damage: Amount of damage absorbed by armor
|
||||
|
||||
Returns:
|
||||
Decay in PED for this hit
|
||||
"""
|
||||
if not self._session_active or damage <= 0:
|
||||
return Decimal('0')
|
||||
|
||||
self.total_damage_absorbed += damage
|
||||
self.hits_taken += 1
|
||||
|
||||
# Calculate decay for this hit
|
||||
decay_pec = calculate_armor_decay(damage, self.armor.durability)
|
||||
decay_ped = decay_pec / Decimal('100')
|
||||
|
||||
self.total_decay_pec += decay_pec
|
||||
self.total_decay_ped += decay_ped
|
||||
|
||||
return decay_ped
|
||||
|
||||
def get_current_decay(self) -> tuple[Decimal, Decimal]:
|
||||
"""
|
||||
Get current total decay.
|
||||
|
||||
Returns:
|
||||
Tuple of (total_decay_pec, total_decay_ped)
|
||||
"""
|
||||
return self.total_decay_pec, self.total_decay_ped
|
||||
|
||||
def get_efficiency_stats(self) -> Dict[str, Decimal]:
|
||||
"""
|
||||
Get armor efficiency statistics.
|
||||
|
||||
Returns:
|
||||
Dictionary with efficiency metrics
|
||||
"""
|
||||
hp_per_pec = get_hp_per_pec(self.armor.durability)
|
||||
|
||||
return {
|
||||
'armor_durability': self.armor.durability,
|
||||
'hp_per_pec': hp_per_pec,
|
||||
'pec_per_hp': Decimal('1') / hp_per_pec if hp_per_pec > 0 else Decimal('0'),
|
||||
'total_damage_absorbed': self.total_damage_absorbed,
|
||||
'total_decay_ped': self.total_decay_ped,
|
||||
'hits_taken': Decimal(str(self.hits_taken))
|
||||
}
|
||||
|
||||
|
||||
def get_armor_durability(armor_name: str) -> int:
|
||||
"""Get durability for an armor by name.
|
||||
# Convenience functions for common use cases
|
||||
|
||||
def get_ghost_decay(damage: Decimal) -> Decimal:
|
||||
"""Quick calculation for Ghost armor (2000 durability)."""
|
||||
return calculate_armor_decay_ped(damage, Decimal('2000'))
|
||||
|
||||
|
||||
def get_gremlin_decay(damage: Decimal) -> Decimal:
|
||||
"""Quick calculation for Gremlin armor (2950 durability)."""
|
||||
return calculate_armor_decay_ped(damage, Decimal('2950'))
|
||||
|
||||
|
||||
def get_angel_decay(damage: Decimal) -> Decimal:
|
||||
"""Quick calculation for Angel armor (4000 durability)."""
|
||||
return calculate_armor_decay_ped(damage, Decimal('4000'))
|
||||
|
||||
|
||||
def format_decay(decay_ped: Decimal) -> str:
|
||||
"""
|
||||
Format decay value for display.
|
||||
|
||||
Args:
|
||||
armor_name: Name of the armor
|
||||
decay_ped: Decay in PED
|
||||
|
||||
Returns:
|
||||
Durability value (defaults to 2000 if unknown)
|
||||
Formatted string (e.g., "0.00735 PED" or "0.735 PEC")
|
||||
"""
|
||||
return ARMOR_DURABILITY.get(armor_name, DEFAULT_DURABILITY)
|
||||
if decay_ped < Decimal('0.01'):
|
||||
pec = decay_ped * Decimal('100')
|
||||
return f"{pec:.4f} PEC"
|
||||
else:
|
||||
return f"{decay_ped:.4f} PED"
|
||||
|
||||
|
||||
def compare_armor_economy(armor_names: list) -> list:
|
||||
"""Compare economy of multiple armors.
|
||||
# ============================================================================
|
||||
# MODULE EXPORTS
|
||||
# ============================================================================
|
||||
|
||||
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")
|
||||
__all__ = [
|
||||
'ArmorSet',
|
||||
'ARMOR_DATABASE',
|
||||
'calculate_armor_decay',
|
||||
'calculate_armor_decay_ped',
|
||||
'calculate_decay_from_hits',
|
||||
'get_hp_per_pec',
|
||||
'get_armor_by_name',
|
||||
'get_armor_decay_ped_for_damage',
|
||||
'estimate_armor_protection',
|
||||
'ArmorDecayTracker',
|
||||
'get_ghost_decay',
|
||||
'get_gremlin_decay',
|
||||
'get_angel_decay',
|
||||
'format_decay'
|
||||
]
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ HEALING_TOOLS: List[HealingTool] = [
|
|||
HealingTool("Restoration Chip II", "resto_2", Decimal("25"), Decimal("1.9"), 2, True),
|
||||
HealingTool("Restoration Chip III", "resto_3", Decimal("35"), Decimal("2.6"), 3, True),
|
||||
HealingTool("Restoration Chip IV", "resto_4", Decimal("45"), Decimal("3.3"), 4, True),
|
||||
HealingTool("Restoration Chip IV (L)", "resto_4_l", Decimal("45"), Decimal("2.8"), 4, True), # Limited version
|
||||
HealingTool("Restoration Chip V", "resto_5", Decimal("55"), Decimal("4.0"), 5, True),
|
||||
HealingTool("Restoration Chip VI", "resto_6", Decimal("65"), Decimal("4.7"), 6, True),
|
||||
HealingTool("Restoration Chip VII", "resto_7", Decimal("75"), Decimal("5.4"), 7, True),
|
||||
|
|
|
|||
Loading…
Reference in New Issue