From dc7b26676d3b24249c5a54b8b829e2be2142462c Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Mar 2026 07:54:56 +0100 Subject: [PATCH] fix: tighten mana panel layout and icon sizing Adjust the inventory mana panel to fit beside the backpack column without overlap, prevent the panel from scrolling, shrink composite icons correctly, and refine mana-state derivation using existing item spell data. --- inventory-service/main.py | 81 +++++++++++++++++++++++++++++++++++++++ static/script.js | 7 +++- static/style.css | 81 ++++++++++++++++++++++++++++----------- 3 files changed, 146 insertions(+), 23 deletions(-) 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,