diff --git a/ui/loadout_manager.py b/ui/loadout_manager.py index edcfc68..845d8d1 100644 --- a/ui/loadout_manager.py +++ b/ui/loadout_manager.py @@ -181,6 +181,41 @@ class LoadoutConfig: return Decimal("0") return total_damage / total_cost + def calculate_dps(self) -> Decimal: + """Calculate Damage Per Second (DPS) with all attachments.""" + # Standard EU fire rate is typically 1 shot per second without attachments + # A scope may increase this, but we'll use a base of 1.0 for simplicity + shots_per_second = Decimal("1.0") + if self.weapon_scope: + # Scopes can increase fire rate, but let's be conservative + shots_per_second = Decimal("1.2") + return self.get_total_damage() * shots_per_second + + def get_armor_decay_per_hit(self) -> Decimal: + """Calculate armor decay cost per hit taken (in PED).""" + decay_per_hit = Decimal("0") + if self.equipped_armor: + decay_per_hit = self.equipped_armor.get_total_decay_per_hit() + else: + # Legacy fallback + decay_per_hit = self.armor_decay_pec + + # Add plate decay costs + for slot, plate_config in self.armor_plates.items(): + decay_per_hit += plate_config.decay_pec + + return decay_per_hit / Decimal("100") # Convert PEC to PED + + def get_heal_cost_per_use(self) -> Decimal: + """Calculate healing cost per use (in PED).""" + return self.heal_cost_pec / Decimal("100") + + def get_hp_per_pec(self) -> Decimal: + """Calculate HP healed per PEC spent.""" + if self.heal_cost_pec == 0: + return Decimal("0") + return self.heal_amount / self.heal_cost_pec + def calculate_weapon_cost_per_hour(self) -> Decimal: """Calculate weapon cost per hour.""" cost_per_shot = self.get_total_decay_per_shot() + self.get_total_ammo_per_shot() @@ -1114,22 +1149,6 @@ class LoadoutManagerDialog(QDialog): self.loadout_name_edit = QLineEdit() self.loadout_name_edit.setPlaceholderText("Enter loadout name...") - # Activity settings - self.shots_per_hour_spin = QSpinBox() - self.shots_per_hour_spin.setRange(1, 20000) - self.shots_per_hour_spin.setValue(3600) - self.shots_per_hour_spin.setSuffix(" /hr") - - self.hits_per_hour_spin = QSpinBox() - self.hits_per_hour_spin.setRange(0, 5000) - self.hits_per_hour_spin.setValue(720) - self.hits_per_hour_spin.setSuffix(" /hr") - - self.heals_per_hour_spin = QSpinBox() - self.heals_per_hour_spin.setRange(0, 500) - self.heals_per_hour_spin.setValue(60) - self.heals_per_hour_spin.setSuffix(" /hr") - # Weapon section self.weapon_group = DarkGroupBox("🔫 Weapon Configuration") self.select_weapon_btn = QPushButton("🔍 Select from Entropia Nexus") @@ -1185,19 +1204,28 @@ class LoadoutManagerDialog(QDialog): self.heal_cost_edit = DecimalLineEdit() self.heal_amount_edit = DecimalLineEdit() - # Cost summary - self.summary_group = DarkGroupBox("📊 Cost Summary") - self.weapon_cost_label = QLabel("0.00 PEC/hr") - self.armor_cost_label = QLabel("0.00 PEC/hr") - self.heal_cost_label = QLabel("0.00 PEC/hr") - self.total_cost_label = QLabel("0.00 PED/hr") - self.total_cost_label.setStyleSheet("color: #ff9800; font-weight: bold; font-size: 18px;") - self.total_dpp_label = QLabel("0.0000") - self.total_dpp_label.setStyleSheet("color: #4caf50; font-weight: bold; font-size: 18px;") + # Cost summary - refined metrics (cost per action, not per hour) + self.summary_group = DarkGroupBox("📊 Cost Analysis") - # Protection summary + # Weapon metrics + self.cost_per_shot_label = QLabel("0.0000 PED") + self.dps_label = QLabel("0.00 DPS") + self.dpp_label = QLabel("0.0000 DPP") + self.dpp_label.setStyleSheet("color: #4caf50; font-weight: bold;") + + # Armor metrics + self.cost_per_hit_label = QLabel("0.0000 PED") self.protection_summary_label = QLabel("No protection") - self.protection_summary_label.setStyleSheet("color: #4a90d9; font-size: 12px;") + self.protection_summary_label.setStyleSheet("color: #4a90d9;") + + # Healing metrics + self.cost_per_heal_label = QLabel("0.0000 PED") + self.hp_per_pec_label = QLabel("0.00 HP/PEC") + self.hp_per_pec_label.setStyleSheet("color: #4caf50;") + + # Total cost display + self.total_cost_label = QLabel("0.0000 PED") + self.total_cost_label.setStyleSheet("color: #ff9800; font-weight: bold; font-size: 16px;") # Break-even calculator self.mob_health_edit = DecimalLineEdit() @@ -1263,17 +1291,6 @@ class LoadoutManagerDialog(QDialog): name_layout.addWidget(self.loadout_name_edit, stretch=1) right_layout.addLayout(name_layout) - # Activity settings - activity_group = DarkGroupBox("⚙️ Activity Settings") - activity_layout = QGridLayout(activity_group) - activity_layout.addWidget(QLabel("Shots/Hour:"), 0, 0) - activity_layout.addWidget(self.shots_per_hour_spin, 0, 1) - activity_layout.addWidget(QLabel("Hits Taken/Hour:"), 0, 2) - activity_layout.addWidget(self.hits_per_hour_spin, 0, 3) - activity_layout.addWidget(QLabel("Heals/Hour:"), 0, 4) - activity_layout.addWidget(self.heals_per_hour_spin, 0, 5) - right_layout.addWidget(activity_group) - # Weapon configuration weapon_layout = QFormLayout(self.weapon_group) @@ -1421,23 +1438,41 @@ class LoadoutManagerDialog(QDialog): right_layout.addWidget(self.accessories_group) - # Cost summary + # Cost summary - refined layout with better metrics summary_layout = QFormLayout(self.summary_group) - summary_layout.addRow("Weapon Cost:", self.weapon_cost_label) - summary_layout.addRow("Armor Cost:", self.armor_cost_label) - summary_layout.addRow("Healing Cost:", self.heal_cost_label) - summary_layout.addRow("Total DPP:", self.total_dpp_label) - summary_layout.addRow("Total Cost:", self.total_cost_label) - # Protection summary - summary_layout.addRow("Protection:", self.protection_summary_label) + # Weapon section + weapon_group = QLabel("⚔️ Weapon") + weapon_group.setStyleSheet("color: #e0e0e0; margin-top: 5px;") + summary_layout.addRow(weapon_group) + summary_layout.addRow(" Cost/Shot:", self.cost_per_shot_label) + summary_layout.addRow(" DPS:", self.dps_label) + summary_layout.addRow(" DPP:", self.dpp_label) + # Armor section + armor_group = QLabel("🛡️ Armor") + armor_group.setStyleSheet("color: #e0e0e0; margin-top: 5px;") + summary_layout.addRow(armor_group) + summary_layout.addRow(" Cost/Hit:", self.cost_per_hit_label) + summary_layout.addRow(" Protection:", self.protection_summary_label) + + # Healing section + heal_group = QLabel("💚 Healing") + heal_group.setStyleSheet("color: #e0e0e0; margin-top: 5px;") + summary_layout.addRow(heal_group) + summary_layout.addRow(" Cost/Heal:", self.cost_per_heal_label) + summary_layout.addRow(" HP/PEC:", self.hp_per_pec_label) + + # Break-even calculator + break_even_group = QLabel("📈 Break-Even") + break_even_group.setStyleSheet("color: #e0e0e0; margin-top: 10px;") + summary_layout.addRow(break_even_group) break_even_layout = QHBoxLayout() - break_even_layout.addWidget(QLabel("Mob Health:")) + break_even_layout.addWidget(QLabel("Mob HP:")) break_even_layout.addWidget(self.mob_health_edit) break_even_layout.addWidget(self.calc_break_even_btn) - summary_layout.addRow("Break-Even:", break_even_layout) - summary_layout.addRow("", self.break_even_label) + summary_layout.addRow(" Calculate:", break_even_layout) + summary_layout.addRow(" Break-even:", self.break_even_label) right_layout.addWidget(self.summary_group) @@ -1478,11 +1513,6 @@ class LoadoutManagerDialog(QDialog): # Healing self.heal_combo.currentTextChanged.connect(self._on_heal_changed) - # Activity settings - self.shots_per_hour_spin.valueChanged.connect(self._update_calculations) - self.hits_per_hour_spin.valueChanged.connect(self._update_calculations) - self.heals_per_hour_spin.valueChanged.connect(self._update_calculations) - # Buttons self.save_btn.clicked.connect(self._save_loadout) self.load_btn.clicked.connect(self._load_selected) @@ -1855,33 +1885,40 @@ class LoadoutManagerDialog(QDialog): self._update_calculations() def _update_calculations(self): - """Update all cost and DPP calculations.""" + """Update all cost and performance calculations.""" try: config = self._get_current_config() - # Update DPP + # Weapon metrics (per shot, not per hour) + cost_per_shot = config.get_total_decay_per_shot() + config.get_total_ammo_per_shot() + self.cost_per_shot_label.setText(f"{cost_per_shot:.4f} PED") + + # DPS calculation + dps = config.calculate_dps() + self.dps_label.setText(f"{dps:.2f}") + + # DPP (Damage Per Pec) dpp = config.calculate_dpp() self.dpp_label.setText(f"{dpp:.4f}") - self.total_dpp_label.setText(f"{dpp:.4f}") - # Update cost breakdown - weapon_cost = config.calculate_weapon_cost_per_hour() - armor_cost = config.calculate_armor_cost_per_hour() - heal_cost = config.calculate_heal_cost_per_hour() - total_cost = config.calculate_total_cost_per_hour() + # Armor metrics (cost per hit) + cost_per_hit = config.get_armor_decay_per_hit() + self.cost_per_hit_label.setText(f"{cost_per_hit:.4f} PED") - self.weapon_cost_label.setText(f"{weapon_cost:.0f} PEC/hr") - self.armor_cost_label.setText(f"{armor_cost:.0f} PEC/hr") - self.heal_cost_label.setText(f"{heal_cost:.0f} PEC/hr") - self.total_cost_label.setText(f"{total_cost:.2f} PED/hr") - - # Update protection summary + # Protection summary protection = config.get_total_protection() prot_text = format_protection(protection) if prot_text == "None": self.protection_summary_label.setText("No protection") else: - self.protection_summary_label.setText(f"Total: {protection.get_total()} | {prot_text}") + self.protection_summary_label.setText(f"Total: {protection.get_total():.1f} | {prot_text}") + + # Healing metrics + cost_per_heal = config.get_heal_cost_per_use() + self.cost_per_heal_label.setText(f"{cost_per_heal:.4f} PED") + + hp_per_pec = config.get_hp_per_pec() + self.hp_per_pec_label.setText(f"{hp_per_pec:.2f}") except Exception as e: logger.error(f"Calculation error: {e}") @@ -1972,17 +2009,14 @@ class LoadoutManagerDialog(QDialog): heal_name=self.heal_combo.currentText(), heal_cost_pec=self.heal_cost_edit.get_decimal(), heal_amount=self.heal_amount_edit.get_decimal(), - shots_per_hour=self.shots_per_hour_spin.value(), - hits_per_hour=self.hits_per_hour_spin.value(), - heals_per_hour=self.heals_per_hour_spin.value(), + shots_per_hour=3600, # Default, no longer in UI + hits_per_hour=720, # Default, no longer in UI + heals_per_hour=60, # Default, no longer in UI ) def _set_config(self, config: LoadoutConfig): """Set UI fields from configuration.""" self.loadout_name_edit.setText(config.name) - self.shots_per_hour_spin.setValue(config.shots_per_hour) - self.hits_per_hour_spin.setValue(config.hits_per_hour) - self.heals_per_hour_spin.setValue(config.heals_per_hour) # Weapon self.weapon_name_label.setText(config.weapon_name) @@ -2166,9 +2200,6 @@ class LoadoutManagerDialog(QDialog): self.heal_amount_edit.clear() # Reset values - self.shots_per_hour_spin.setValue(3600) - self.hits_per_hour_spin.setValue(720) - self.heals_per_hour_spin.setValue(60) self.mob_health_edit.set_decimal(Decimal("100")) # Reset combos