diff --git a/inventory-service/main.py b/inventory-service/main.py index 24dc3a55..19335639 100644 --- a/inventory-service/main.py +++ b/inventory-service/main.py @@ -1137,6 +1137,8 @@ def get_mana_tracker_info(item_data: Dict[str, Any]) -> Dict[str, Any]: max_mana = mana_info.get("max_mana") has_id_data = bool(item_data.get("HasIdData", False)) spell_ids = item_data.get("Spells", []) or [] + active_spells = item_data.get("ActiveSpells", []) or [] + active_item_enchantments = item_data.get("ActiveItemEnchantments", []) or [] mana_rate_of_change = None if "5" in double_values: @@ -1144,6 +1146,78 @@ def get_mana_tracker_info(item_data: Dict[str, Any]) -> Dict[str, Any]: elif 5 in double_values: mana_rate_of_change = double_values[5] + def is_spell_active(spell_data: Dict[str, Any]) -> bool: + if not spell_data: + return False + + spell_id = spell_data.get("id") + if spell_id in active_spells: + return True + + spell_family = spell_data.get("family") + spell_difficulty = spell_data.get("difficulty") + if spell_family in (None, "", 0): + return False + + for active_spell in active_item_enchantments: + if not active_spell: + continue + if active_spell.get("family") != spell_family: + continue + + active_difficulty = active_spell.get("difficulty") + if active_difficulty in (None, "") or spell_difficulty in (None, ""): + return True + + try: + if int(active_difficulty) >= int(spell_difficulty): + return True + except (TypeError, ValueError): + return True + + return False + + translated_spells = [translate_spell(spell_id) for spell_id in spell_ids] + actionable_spells = [] + for spell in translated_spells: + if not spell: + continue + if spell.get("id") == int_values.get("94") or spell.get("id") == int_values.get( + 94 + ): + continue + spell_name = (spell.get("name") or "").lower() + if spell_name.startswith("unknown_spell_"): + continue + if spell_name.startswith(("cantrip portal send", "cantrip portal recall")): + continue + if spell_name.startswith(("incantation of ", "aura of incantation ")): + actionable_spells.append(spell) + continue + if spell_name.startswith( + ( + "feeble ", + "minor ", + "lesser ", + "moderate ", + "inner ", + "major ", + "epic ", + "legendary ", + "prodigal ", + ) + ): + actionable_spells.append(spell) + continue + duration = spell.get("duration") + try: + if duration is not None and int(duration) <= 0: + actionable_spells.append(spell) + except (TypeError, ValueError): + pass + + has_inactive_spell = any(not is_spell_active(spell) for spell in actionable_spells) + if not has_id_data: mana_state = "unknown" elif not spell_ids or max_mana is None or max_mana <= 0: @@ -1152,6 +1226,8 @@ def get_mana_tracker_info(item_data: Dict[str, Any]) -> Dict[str, Any]: mana_state = "unknown" elif current_mana <= 0: mana_state = "not_active" + elif has_inactive_spell: + mana_state = "not_active" else: mana_state = "active" @@ -2206,6 +2282,11 @@ def enrich_db_item(item) -> dict: original_json = {} if original_json: + if processed_item.get("active_item_enchantments"): + original_json["ActiveItemEnchantments"] = processed_item[ + "active_item_enchantments" + ] + # Extract properties and get translations properties = extract_item_properties(original_json) diff --git a/static/script.js b/static/script.js index 9b81558b..517078fe 100644 --- a/static/script.js +++ b/static/script.js @@ -1554,7 +1554,9 @@ function renderInventoryManaPanel(state) { const iconWrap = document.createElement('div'); iconWrap.className = 'inv-mana-icon'; - iconWrap.appendChild(createInventorySlot(item)); + const iconSlot = createInventorySlot(item); + iconSlot.classList.add('mana-slot'); + iconWrap.appendChild(iconSlot); const nameEl = document.createElement('div'); nameEl.className = 'inv-mana-name'; @@ -1609,6 +1611,9 @@ function showInventoryWindow(name) { loading.textContent = 'Loading inventory...'; content.appendChild(loading); + win.style.width = '540px'; + win.style.height = '520px'; + const invContent = document.createElement('div'); invContent.className = 'inventory-content'; invContent.style.display = 'none'; diff --git a/static/style.css b/static/style.css index 4b2d5efc..dbd6d346 100644 --- a/static/style.css +++ b/static/style.css @@ -735,7 +735,7 @@ body.noselect, body.noselect * { position: fixed; top: 100px; left: 400px; - width: 540px; + width: 548px; height: 520px; background: rgba(20, 20, 20, 0.92); backdrop-filter: blur(2px); @@ -762,7 +762,7 @@ body.noselect, body.noselect * { display: flex; justify-content: flex-start; height: 264px; - gap: 8px; + gap: 10px; } .inv-equipment-grid { @@ -808,13 +808,14 @@ body.noselect, body.noselect * { } .inv-sidebar { - width: 60px; + width: 54px; display: flex; flex-direction: column; align-items: center; gap: 2px; overflow: visible; flex-shrink: 0; + margin-right: 2px; } .inv-burden-bar { @@ -868,6 +869,7 @@ body.noselect, body.noselect * { justify-content: center; background: #000; flex-shrink: 0; + margin-right: 0; } .inv-pack-icon.active { @@ -911,7 +913,7 @@ body.noselect, body.noselect * { flex: 1; display: flex; flex-direction: column; - margin-top: 10px; + margin-top: 8px; margin-right: 0; overflow: hidden; min-height: 0; @@ -930,6 +932,7 @@ body.noselect, body.noselect * { display: flex; flex-direction: column; min-width: 0; + flex: 1; } .inv-item-grid { @@ -941,23 +944,24 @@ body.noselect, body.noselect * { padding: 4px; border: 1px solid var(--ac-border-light); flex: 1; - overflow-y: auto; + overflow-y: hidden; min-height: 0; align-content: start; justify-content: start; } .inv-mana-panel { - width: 150px; - min-width: 150px; + width: 162px; + min-width: 162px; display: flex; flex-direction: column; background: rgba(6, 10, 18, 0.92); border: 1px solid var(--ac-border-light); - padding: 4px; + padding: 3px; min-height: 0; - height: 100%; + height: 260px; flex-shrink: 0; + overflow: hidden; } .inv-mana-header { @@ -970,20 +974,20 @@ body.noselect, body.noselect * { .inv-mana-summary { color: var(--ac-text-dim); - font-size: 10px; + font-size: 9px; line-height: 1.2; - padding: 4px 0; + padding: 2px 0; border-bottom: 1px solid rgba(255,255,255,0.08); - margin-bottom: 4px; + margin-bottom: 3px; } .inv-mana-list { flex: 1; min-height: 0; - overflow-y: auto; + overflow: hidden; display: flex; flex-direction: column; - gap: 4px; + gap: 2px; } .inv-mana-row { @@ -994,7 +998,8 @@ body.noselect, body.noselect * { align-items: center; background: rgba(18, 24, 34, 0.9); border: 1px solid rgba(255,255,255,0.08); - padding: 2px 3px; + padding: 1px 2px; + min-height: 20px; } .inv-mana-icon { @@ -1008,11 +1013,30 @@ body.noselect, body.noselect * { height: 16px; } +.inv-mana-icon .inventory-slot.mana-slot { + width: 16px; + height: 16px; +} + +.inv-mana-icon .inventory-slot.mana-slot .item-icon-composite { + width: 14px; + height: 14px; +} + +.inv-mana-icon .inventory-slot.mana-slot .icon-underlay, +.inv-mana-icon .inventory-slot.mana-slot .icon-base, +.inv-mana-icon .inventory-slot.mana-slot .icon-overlay { + width: 14px; + height: 14px; +} + .inv-mana-name { color: #f2e6c9; font-size: 9px; line-height: 1.05; - word-break: break-word; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; grid-column: 2; grid-row: 1; } @@ -1034,6 +1058,7 @@ body.noselect, body.noselect * { grid-column: 3; grid-row: 2; text-align: right; + min-width: 34px; } .inv-mana-state-dot { @@ -2407,12 +2432,12 @@ table.ts-allegiance td:first-child { border: 2px solid #8a7a44 !important; background: #0e0c08 !important; resize: none !important; - width: 540px !important; + width: 548px !important; } .inv-top-section { justify-content: flex-start !important; - gap: 8px !important; + gap: 10px !important; } .inv-bottom-section { @@ -2421,11 +2446,12 @@ table.ts-allegiance td:first-child { } .inv-mana-panel { - width: 150px !important; - min-width: 150px !important; - height: 100% !important; + width: 162px !important; + min-width: 162px !important; + height: 260px !important; background: #111014 !important; border: 1px solid #5a4a24 !important; + overflow: hidden !important; } .inv-mana-header { @@ -2444,7 +2470,7 @@ table.ts-allegiance td:first-child { grid-template-columns: 18px 1fr 14px !important; grid-template-rows: auto auto !important; gap: 1px 4px !important; - padding: 2px 3px !important; + padding: 1px 2px !important; background: #1a1208 !important; border: 1px solid #3a2818 !important; } @@ -2460,9 +2486,20 @@ table.ts-allegiance td:first-child { height: 16px !important; } +.inv-mana-icon .inventory-slot.mana-slot .item-icon-composite, +.inv-mana-icon .inventory-slot.mana-slot .icon-underlay, +.inv-mana-icon .inventory-slot.mana-slot .icon-base, +.inv-mana-icon .inventory-slot.mana-slot .icon-overlay { + width: 14px !important; + height: 14px !important; +} + .inv-mana-name { font-size: 9px !important; line-height: 1.05 !important; + white-space: nowrap !important; + overflow: hidden !important; + text-overflow: ellipsis !important; } .inv-mana-value,