225 lines
7.1 KiB
Python
225 lines
7.1 KiB
Python
"""
|
|
EU-Utility - Loot Tracker Plugin
|
|
|
|
Track and analyze hunting loot with statistics and ROI.
|
|
"""
|
|
|
|
import re
|
|
from datetime import datetime
|
|
from collections import defaultdict
|
|
from pathlib import Path
|
|
import json
|
|
|
|
from PyQt6.QtWidgets import (
|
|
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
|
QPushButton, QTableWidget, QTableWidgetItem,
|
|
QComboBox, QLineEdit, QTabWidget, QFrame
|
|
)
|
|
from PyQt6.QtCore import Qt
|
|
|
|
from plugins.base_plugin import BasePlugin
|
|
|
|
|
|
class LootTrackerPlugin(BasePlugin):
|
|
"""Track hunting loot and calculate ROI."""
|
|
|
|
name = "Loot Tracker"
|
|
version = "1.0.0"
|
|
author = "ImpulsiveFPS"
|
|
description = "Track hunting loot with stats and ROI analysis"
|
|
hotkey = "ctrl+shift+l" # L for Loot
|
|
|
|
def initialize(self):
|
|
"""Setup loot tracker."""
|
|
self.data_file = Path("data/loot_tracker.json")
|
|
self.data_file.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
self.sessions = []
|
|
self.current_session = {
|
|
'start_time': None,
|
|
'kills': 0,
|
|
'loot_items': [],
|
|
'total_tt': 0.0,
|
|
'ammo_cost': 0.0,
|
|
'weapon_decay': 0.0,
|
|
}
|
|
|
|
self._load_data()
|
|
|
|
def _load_data(self):
|
|
"""Load historical data."""
|
|
if self.data_file.exists():
|
|
try:
|
|
with open(self.data_file, 'r') as f:
|
|
self.sessions = json.load(f)
|
|
except:
|
|
self.sessions = []
|
|
|
|
def _save_data(self):
|
|
"""Save data to file."""
|
|
with open(self.data_file, 'w') as f:
|
|
json.dump(self.sessions, f, indent=2)
|
|
|
|
def get_ui(self):
|
|
"""Create plugin UI."""
|
|
widget = QWidget()
|
|
widget.setStyleSheet("background: transparent;")
|
|
layout = QVBoxLayout(widget)
|
|
layout.setSpacing(15)
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
# Title
|
|
title = QLabel("Loot Tracker")
|
|
title.setStyleSheet("color: white; font-size: 16px; font-weight: bold;")
|
|
layout.addWidget(title)
|
|
|
|
# Stats summary
|
|
stats_frame = QFrame()
|
|
stats_frame.setStyleSheet("""
|
|
QFrame {
|
|
background-color: rgba(0, 0, 0, 50);
|
|
border-radius: 10px;
|
|
border: 1px solid rgba(255, 255, 255, 20);
|
|
}
|
|
""")
|
|
stats_layout = QHBoxLayout(stats_frame)
|
|
|
|
self.kills_label = QLabel("Kills: 0")
|
|
self.kills_label.setStyleSheet("color: #4caf50; font-size: 14px; font-weight: bold;")
|
|
stats_layout.addWidget(self.kills_label)
|
|
|
|
self.tt_label = QLabel("TT: 0.00 PED")
|
|
self.tt_label.setStyleSheet("color: #ffc107; font-size: 14px; font-weight: bold;")
|
|
stats_layout.addWidget(self.tt_label)
|
|
|
|
self.roi_label = QLabel("ROI: 0%")
|
|
self.roi_label.setStyleSheet("color: #4a9eff; font-size: 14px; font-weight: bold;")
|
|
stats_layout.addWidget(self.roi_label)
|
|
|
|
layout.addWidget(stats_frame)
|
|
|
|
# Session controls
|
|
controls = QHBoxLayout()
|
|
|
|
self.start_btn = QPushButton("▶ Start Session")
|
|
self.start_btn.setStyleSheet("""
|
|
QPushButton {
|
|
background-color: #4caf50;
|
|
color: white;
|
|
padding: 10px 20px;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-weight: bold;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: #5cbf60;
|
|
}
|
|
""")
|
|
self.start_btn.clicked.connect(self._start_session)
|
|
controls.addWidget(self.start_btn)
|
|
|
|
self.stop_btn = QPushButton("⏹ Stop Session")
|
|
self.stop_btn.setStyleSheet("""
|
|
QPushButton {
|
|
background-color: #f44336;
|
|
color: white;
|
|
padding: 10px 20px;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-weight: bold;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: #f55a4e;
|
|
}
|
|
""")
|
|
self.stop_btn.clicked.connect(self._stop_session)
|
|
self.stop_btn.setEnabled(False)
|
|
controls.addWidget(self.stop_btn)
|
|
|
|
layout.addLayout(controls)
|
|
|
|
# Loot table
|
|
self.loot_table = QTableWidget()
|
|
self.loot_table.setColumnCount(4)
|
|
self.loot_table.setHorizontalHeaderLabels(["Item", "Qty", "TT Value", "Time"])
|
|
self.loot_table.setStyleSheet("""
|
|
QTableWidget {
|
|
background-color: rgba(30, 30, 30, 100);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 6px;
|
|
}
|
|
QHeaderView::section {
|
|
background-color: rgba(74, 158, 255, 100);
|
|
color: white;
|
|
padding: 6px;
|
|
}
|
|
""")
|
|
self.loot_table.horizontalHeader().setStretchLastSection(True)
|
|
layout.addWidget(self.loot_table)
|
|
|
|
layout.addStretch()
|
|
return widget
|
|
|
|
def _start_session(self):
|
|
"""Start new hunting session."""
|
|
self.current_session = {
|
|
'start_time': datetime.now().isoformat(),
|
|
'kills': 0,
|
|
'loot_items': [],
|
|
'total_tt': 0.0,
|
|
'ammo_cost': 0.0,
|
|
'weapon_decay': 0.0,
|
|
}
|
|
self.start_btn.setEnabled(False)
|
|
self.stop_btn.setEnabled(True)
|
|
|
|
def _stop_session(self):
|
|
"""Stop current session and save."""
|
|
self.current_session['end_time'] = datetime.now().isoformat()
|
|
self.sessions.append(self.current_session)
|
|
self._save_data()
|
|
|
|
self.start_btn.setEnabled(True)
|
|
self.stop_btn.setEnabled(False)
|
|
self._update_stats()
|
|
|
|
def _update_stats(self):
|
|
"""Update statistics display."""
|
|
kills = self.current_session.get('kills', 0)
|
|
tt = self.current_session.get('total_tt', 0.0)
|
|
|
|
self.kills_label.setText(f"Kills: {kills}")
|
|
self.tt_label.setText(f"TT: {tt:.2f} PED")
|
|
|
|
def parse_chat_message(self, message):
|
|
"""Parse loot from chat."""
|
|
# Look for loot patterns
|
|
# Example: "You received Animal Hide (0.03 PED)"
|
|
loot_pattern = r'You received (.+?) \(([\d.]+) PED\)'
|
|
match = re.search(loot_pattern, message)
|
|
|
|
if match:
|
|
item_name = match.group(1)
|
|
tt_value = float(match.group(2))
|
|
|
|
self.current_session['loot_items'].append({
|
|
'item': item_name,
|
|
'tt': tt_value,
|
|
'time': datetime.now().isoformat()
|
|
})
|
|
self.current_session['total_tt'] += tt_value
|
|
self._update_stats()
|
|
|
|
# Check for new kill
|
|
# Multiple items in quick succession = one kill
|
|
# Longer gap = new kill
|
|
self.current_session['kills'] += 1
|
|
|
|
def on_hotkey(self):
|
|
"""Toggle session on hotkey."""
|
|
if self.start_btn.isEnabled():
|
|
self._start_session()
|
|
else:
|
|
self._stop_session()
|