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 @@
|
||||||
"""
|
# Description: Official Armor Decay Calculator for Entropia Universe
|
||||||
Armor Decay Calculator for Lemontropia Suite
|
# Formula Source: Hijacker27's Official Guide (VU 15.15)
|
||||||
Implements the official VU 15.15 armor decay formula.
|
# Standards: Python 3.11+, Decimal precision for PED/PEC calculations
|
||||||
"""
|
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal, ROUND_HALF_UP
|
||||||
from typing import Dict, Optional
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from typing import Dict, Optional, List
|
||||||
|
import logging
|
||||||
|
|
||||||
# Armor durability database (from official guide)
|
logger = logging.getLogger(__name__)
|
||||||
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
|
@dataclass
|
||||||
class ArmorSet:
|
class ArmorSet:
|
||||||
"""Represents a complete armor set (7 pieces)."""
|
"""Represents an armor set with its properties."""
|
||||||
name: str
|
name: str
|
||||||
head: Optional[ArmorPiece] = None
|
durability: Decimal
|
||||||
chest: Optional[ArmorPiece] = None
|
total_protection: Decimal # Total protection value
|
||||||
left_arm: Optional[ArmorPiece] = None
|
notes: str = ""
|
||||||
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:
|
@property
|
||||||
"""Get list of all equipped pieces."""
|
def hp_per_pec(self) -> Decimal:
|
||||||
pieces = []
|
"""Calculate HP absorbed per PEC of decay."""
|
||||||
for piece in [self.head, self.chest, self.left_arm, self.right_arm,
|
# Formula: hp/pec = 1 / (0.05 * (1 - durability/100000))
|
||||||
self.left_hand, self.right_hand, self.legs, self.feet]:
|
decay_factor = Decimal('0.05') * (Decimal('1') - self.durability / Decimal('100000'))
|
||||||
if piece:
|
if decay_factor > 0:
|
||||||
pieces.append(piece)
|
return Decimal('1') / decay_factor
|
||||||
return pieces
|
return Decimal('0')
|
||||||
|
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
def get_total_protection(self, damage_type: str = "impact") -> Decimal:
|
Official Formula (VU 15.15):
|
||||||
"""Get total protection for a damage type."""
|
Decay (PEC) = damage_absorbed * 0.05 * (1 - durability/100000)
|
||||||
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:
|
Args:
|
||||||
"""Calculate total decay for all pieces.
|
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:
|
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:
|
Returns:
|
||||||
Total decay in PED
|
Dictionary with session summary
|
||||||
"""
|
"""
|
||||||
total_decay = Decimal("0")
|
self._session_active = False
|
||||||
for piece in self.get_all_pieces():
|
|
||||||
if piece.slot in damage_per_piece:
|
return {
|
||||||
damage = damage_per_piece[piece.slot]
|
'armor_name': self.armor.name,
|
||||||
total_decay += piece.calculate_decay(damage)
|
'armor_durability': float(self.armor.durability),
|
||||||
return total_decay
|
'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:
|
# Convenience functions for common use cases
|
||||||
"""Get durability for an armor by name.
|
|
||||||
|
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:
|
Args:
|
||||||
armor_name: Name of the armor
|
decay_ped: Decay in PED
|
||||||
|
|
||||||
Returns:
|
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
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
# Example usage
|
'ArmorSet',
|
||||||
if __name__ == "__main__":
|
'ARMOR_DATABASE',
|
||||||
# Compare popular armors
|
'calculate_armor_decay',
|
||||||
armors = ["Ghost", "Gremlin", "Adjusted Nemesis", "Angel",
|
'calculate_armor_decay_ped',
|
||||||
"Martial (L)", "Angel (L)", "Perseus (L)"]
|
'calculate_decay_from_hits',
|
||||||
|
'get_hp_per_pec',
|
||||||
print("Armor Economy Comparison:")
|
'get_armor_by_name',
|
||||||
print("-" * 70)
|
'get_armor_decay_ped_for_damage',
|
||||||
print(f"{'Armor':<25} {'Dur':<8} {'hp/pec':<12} {'dmg/100PED':<12}")
|
'estimate_armor_protection',
|
||||||
print("-" * 70)
|
'ArmorDecayTracker',
|
||||||
|
'get_ghost_decay',
|
||||||
for name, durability, hp_per_pec, dmg_per_100 in compare_armor_economy(armors):
|
'get_gremlin_decay',
|
||||||
print(f"{name:<25} {durability:<8} {hp_per_pec:<12.2f} {dmg_per_100:<12,}")
|
'get_angel_decay',
|
||||||
|
'format_decay'
|
||||||
# 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")
|
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ HEALING_TOOLS: List[HealingTool] = [
|
||||||
HealingTool("Restoration Chip II", "resto_2", Decimal("25"), Decimal("1.9"), 2, True),
|
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 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", "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 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 VI", "resto_6", Decimal("65"), Decimal("4.7"), 6, True),
|
||||||
HealingTool("Restoration Chip VII", "resto_7", Decimal("75"), Decimal("5.4"), 7, True),
|
HealingTool("Restoration Chip VII", "resto_7", Decimal("75"), Decimal("5.4"), 7, True),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue