diff --git a/core/nexus_full_api.py b/core/nexus_full_api.py index 178c8db..4b186e4 100644 --- a/core/nexus_full_api.py +++ b/core/nexus_full_api.py @@ -228,23 +228,38 @@ class NexusHealingTool(NexusItem): @dataclass class NexusRing(NexusItem): - """Ring from Entropia Nexus API.""" - effect_type: str - effect_value: Decimal + """Ring from Entropia Nexus API (found in /clothings endpoint).""" + slot: str # 'Left Finger', 'Right Finger' + gender: str # 'Both', 'Male', 'Female' + effects: Dict[str, str] # e.g., {"Increased Run Speed": "25%"} + max_tt: Decimal + min_tt: Decimal is_limited: bool @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusRing": """Create from API response.""" props = data.get('Properties', {}) + economy = props.get('Economy', {}) + effects_data = props.get('Effects', {}) + # Parse effects (usually under "Effects on Equip") + effects = {} + if 'Effects on Equip' in effects_data: + effects = effects_data['Effects on Equip'] + elif isinstance(effects_data, dict): + effects = effects_data + return cls( id=data.get('Id', 0), name=data.get('Name', 'Unknown'), item_id=str(data.get('Id', 0)), category='ring', - effect_type=props.get('EffectType', ''), - effect_value=Decimal(str(props.get('EffectValue', 0))), + slot=props.get('Slot', 'Left Finger'), + gender=props.get('Gender', 'Both'), + effects=effects, + max_tt=Decimal(str(economy.get('MaxTT', 0))), + min_tt=Decimal(str(economy.get('MinTT', 0))), is_limited='(L)' in data.get('Name', ''), ) @@ -372,46 +387,34 @@ class EntropiaNexusFullAPI: return self._healing_cache def get_all_rings(self, force_refresh: bool = False) -> List[NexusRing]: - """Fetch all rings from Nexus API (or use hardcoded data if API unavailable).""" + """Fetch rings from /clothings endpoint (filtered by Type=Ring).""" if self._rings_cache is None or force_refresh: - data = self._fetch("rings") - if data: - self._rings_cache = [NexusRing.from_api(item) for item in data] + data = self._fetch("clothings") + # Filter for Type=Ring + rings_data = [item for item in data if item.get('Properties', {}).get('Type') == 'Ring'] + if rings_data: + self._rings_cache = [NexusRing.from_api(item) for item in rings_data] + logger.info(f"Loaded {len(self._rings_cache)} rings from clothings endpoint") else: - # API doesn't have rings endpoint - use hardcoded data + # Fallback to hardcoded data self._rings_cache = self._get_hardcoded_rings() - logger.info(f"Loaded {len(self._rings_cache)} rings") return self._rings_cache def _get_hardcoded_rings(self) -> List[NexusRing]: - """Return hardcoded ring data since API doesn't have rings endpoint.""" + """Return hardcoded ring data as fallback.""" return [ - NexusRing(id=1, name="Ares Ring", item_id="ares_ring", category="ring", effect_type="Damage", effect_value=Decimal("5"), is_limited=False), - NexusRing(id=2, name="Ares Ring (L)", item_id="ares_ring_l", category="ring", effect_type="Damage", effect_value=Decimal("5"), is_limited=True), - NexusRing(id=3, name="Hermetic Ring", item_id="hermetic_ring", category="ring", effect_type="Economy", effect_value=Decimal("2"), is_limited=False), - NexusRing(id=4, name="Hermetic Ring (L)", item_id="hermetic_ring_l", category="ring", effect_type="Economy", effect_value=Decimal("2"), is_limited=True), - NexusRing(id=5, name="Courage Ring", item_id="courage_ring", category="ring", effect_type="Critical Hit", effect_value=Decimal("1"), is_limited=False), - NexusRing(id=6, name="Courage Ring (L)", item_id="courage_ring_l", category="ring", effect_type="Critical Hit", effect_value=Decimal("1"), is_limited=True), - NexusRing(id=7, name="Perseus Ring", item_id="perseus_ring", category="ring", effect_type="Critical Damage", effect_value=Decimal("5"), is_limited=False), - NexusRing(id=8, name="Perseus Ring (L)", item_id="perseus_ring_l", category="ring", effect_type="Critical Damage", effect_value=Decimal("5"), is_limited=True), - NexusRing(id=9, name="Zeus Ring", item_id="zeus_ring", category="ring", effect_type="Evade", effect_value=Decimal("2"), is_limited=False), - NexusRing(id=10, name="Zeus Ring (L)", item_id="zeus_ring_l", category="ring", effect_type="Evade", effect_value=Decimal("2"), is_limited=True), - NexusRing(id=11, name="Apollo Ring", item_id="apollo_ring", category="ring", effect_type="Healing", effect_value=Decimal("5"), is_limited=False), - NexusRing(id=12, name="Apollo Ring (L)", item_id="apollo_ring_l", category="ring", effect_type="Healing", effect_value=Decimal("5"), is_limited=True), - NexusRing(id=13, name="Artemis Ring", item_id="artemis_ring", category="ring", effect_type="Reload Speed", effect_value=Decimal("3"), is_limited=False), - NexusRing(id=14, name="Artemis Ring (L)", item_id="artemis_ring_l", category="ring", effect_type="Reload Speed", effect_value=Decimal("3"), is_limited=True), - NexusRing(id=15, name="Hephaestus Ring", item_id="hephaestus_ring", category="ring", effect_type="Crafting", effect_value=Decimal("5"), is_limited=False), - NexusRing(id=16, name="Hephaestus Ring (L)", item_id="hephaestus_ring_l", category="ring", effect_type="Crafting", effect_value=Decimal("5"), is_limited=True), - NexusRing(id=17, name="Aphrodite Ring", item_id="aphrodite_ring", category="ring", effect_type="Beauty", effect_value=Decimal("10"), is_limited=False), - NexusRing(id=18, name="Aphrodite Ring (L)", item_id="aphrodite_ring_l", category="ring", effect_type="Beauty", effect_value=Decimal("10"), is_limited=True), - NexusRing(id=19, name="Dionysus Ring", item_id="dionysus_ring", category="ring", effect_type="Taming", effect_value=Decimal("5"), is_limited=False), - NexusRing(id=20, name="Dionysus Ring (L)", item_id="dionysus_ring_l", category="ring", effect_type="Taming", effect_value=Decimal("5"), is_limited=True), + NexusRing(id=1, name="Ares Ring", item_id="ares_ring", category="ring", slot="Left Finger", gender="Both", effects={"Damage": "5%"}, max_tt=Decimal("10"), min_tt=Decimal("0"), is_limited=False), + NexusRing(id=2, name="Ares Ring (L)", item_id="ares_ring_l", category="ring", slot="Left Finger", gender="Both", effects={"Damage": "5%"}, max_tt=Decimal("10"), min_tt=Decimal("0"), is_limited=True), + NexusRing(id=3, name="Hermetic Ring", item_id="hermetic_ring", category="ring", slot="Left Finger", gender="Both", effects={"Economy": "2%"}, max_tt=Decimal("10"), min_tt=Decimal("0"), is_limited=False), + NexusRing(id=4, name="Hermetic Ring (L)", item_id="hermetic_ring_l", category="ring", slot="Left Finger", gender="Both", effects={"Economy": "2%"}, max_tt=Decimal("10"), min_tt=Decimal("0"), is_limited=True), + NexusRing(id=5, name="Courage Ring", item_id="courage_ring", category="ring", slot="Right Finger", gender="Both", effects={"Critical Hit": "1%"}, max_tt=Decimal("10"), min_tt=Decimal("0"), is_limited=False), + NexusRing(id=6, name="Courage Ring (L)", item_id="courage_ring_l", category="ring", slot="Right Finger", gender="Both", effects={"Critical Hit": "1%"}, max_tt=Decimal("10"), min_tt=Decimal("0"), is_limited=True), ] def get_all_clothing(self, force_refresh: bool = False) -> List[NexusClothing]: """Fetch all clothing from Nexus API.""" if self._clothing_cache is None or force_refresh: - data = self._fetch("clothing") + data = self._fetch("clothings") # Note: endpoint is 'clothings' not 'clothing' self._clothing_cache = [NexusClothing.from_api(item) for item in data] logger.info(f"Loaded {len(self._clothing_cache)} clothing items") return self._clothing_cache diff --git a/ui/accessories_selector.py b/ui/accessories_selector.py index 5a1537b..9034d58 100644 --- a/ui/accessories_selector.py +++ b/ui/accessories_selector.py @@ -149,7 +149,7 @@ class AccessoriesSelectorDialog(QDialog): # Tree tree = QTreeWidget() - tree.setHeaderLabels(["Name", "Effect Type", "Value", "Side", "Limited"]) + tree.setHeaderLabels(["Name", "Effects", "Slot", "Gender", "Limited"]) header = tree.header() header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) tree.itemSelectionChanged.connect(self._on_selection_changed) @@ -305,9 +305,11 @@ class AccessoriesSelectorDialog(QDialog): for ring in self.all_rings: item = QTreeWidgetItem() item.setText(0, ring.name) - item.setText(1, ring.effect_type) - item.setText(2, str(ring.effect_value)) - item.setText(3, "Left/Right") + # Format effects as string + effects_str = ", ".join([f"{k}: {v}" for k, v in ring.effects.items()]) if ring.effects else "-" + item.setText(1, effects_str) + item.setText(2, ring.slot) + item.setText(3, ring.gender) item.setText(4, "Yes" if ring.is_limited else "No") # Color limited items @@ -385,7 +387,7 @@ class AccessoriesSelectorDialog(QDialog): for i in range(tree.topLevelItemCount()): item = tree.topLevelItem(i) ring = item.data(0, Qt.ItemDataRole.UserRole) - visible = search in ring.name.lower() or search in ring.effect_type.lower() + visible = search in ring.name.lower() or any(search in k.lower() or search in v.lower() for k, v in ring.effects.items()) item.setHidden(not visible) def _filter_clothing(self): @@ -447,9 +449,10 @@ class AccessoriesSelectorDialog(QDialog): def _update_preview_ring(self, ring: NexusRing): """Update preview for ring.""" self.preview_name.setText(ring.name) - self.preview_type.setText("Ring (Left/Right)") - self.preview_effect.setText(f"{ring.effect_type}: {ring.effect_value}") - self.preview_extra.setText(f"Limited: {'Yes' if ring.is_limited else 'No'}") + self.preview_type.setText(f"Ring ({ring.slot})") + effects_str = ", ".join([f"{k}: {v}" for k, v in ring.effects.items()]) if ring.effects else "No effects" + self.preview_effect.setText(effects_str) + self.preview_extra.setText(f"Gender: {ring.gender} | Limited: {'Yes' if ring.is_limited else 'No'}") def _update_preview_clothing(self, clothing: NexusClothing): """Update preview for clothing."""