diff --git a/css/analysis.css b/css/analysis.css index 6985894..7ad6076 100644 --- a/css/analysis.css +++ b/css/analysis.css @@ -252,6 +252,12 @@ border-radius: 2px; } +.aoe-buff-ref-unique { + border: 2px solid #3dff6e; + border-radius: 3px; + box-shadow: 0 0 4px #3dff6e; +} + /* ── Target buffs ────────────────────────────────────────────────────────── */ .aoe-target-buffs { display: flex; diff --git a/js/analysis.js b/js/analysis.js index d5244f1..9a5ba35 100644 --- a/js/analysis.js +++ b/js/analysis.js @@ -201,16 +201,27 @@ renderTimeline(lastEvents, lastFightStart); }); - function onFightsLoaded(fights) { + let allSameReportFights = []; + + function populateRefFightSelect() { + const currentName = (window.App.fights ?? []).find(f => f.id === window.App.fightId)?.name; + const visible = allSameReportFights.filter(f => + f.id !== window.App.fightId && (!currentName || f.name === currentName) + ); refFightSelect.innerHTML = ''; - fights.forEach(f => { + visible.forEach(f => { const hp = f.kill ? 'Kill' : (f.fightPercentage != null ? f.fightPercentage.toFixed(2) + '%' : '?'); const opt = document.createElement('option'); opt.value = f.id; opt.textContent = `${f.name} — ${fmtDur(f.endTime - f.startTime)} — ${hp}`; refFightSelect.appendChild(opt); }); - refFightSelect.style.display = ''; + refFightSelect.style.display = visible.length ? '' : 'none'; + } + + function onFightsLoaded(fights) { + allSameReportFights = fights; + populateRefFightSelect(); } // ── External report comparison ──────────────────────────────────────────── @@ -221,6 +232,11 @@ const refReportLoad = document.getElementById('ref-report-load'); const refExtFightSelect = document.getElementById('ref-ext-fight-select'); + refReportInput.addEventListener('input', () => { + const match = refReportInput.value.match(/fflogs\.com\/reports\/([A-Za-z0-9]+)/); + if (match) refReportInput.value = match[1]; + }); + refExtToggle.addEventListener('click', () => { const hidden = refExtPanel.style.display === 'none'; refExtPanel.style.display = hidden ? '' : 'none'; @@ -246,15 +262,17 @@ extFights = fights; extReportCode = code; + const currentName = (window.App.fights ?? []).find(f => f.id === window.App.fightId)?.name; + const visibleExt = currentName ? fights.filter(f => f.name === currentName) : fights; refExtFightSelect.innerHTML = ''; - fights.forEach(f => { + visibleExt.forEach(f => { const hp = f.kill ? 'Kill' : (f.fightPercentage != null ? f.fightPercentage.toFixed(2) + '%' : '?'); const opt = document.createElement('option'); opt.value = f.id; opt.textContent = `${f.name} — ${fmtDur(f.endTime - f.startTime)} — ${hp}`; refExtFightSelect.appendChild(opt); }); - refExtFightSelect.style.display = fights.length ? '' : 'none'; + refExtFightSelect.style.display = visibleExt.length ? '' : 'none'; } catch { } refReportLoad.disabled = false; @@ -389,12 +407,6 @@ return `${m.name}`; }).join(''); - const missingIcons = missingMitigs.map(m => { - const iconSrc = MITIG_ICONS[m.name]; - if (!iconSrc) return ''; - return `${m.name}`; - }).join(''); - // Shield tooltip on absorbed value const activeShields = (t.mitigations ?? []).filter(m => m.buffType === 'shield'); const missingShields = refTarget @@ -423,7 +435,7 @@ ${hpBar} - ${(mitigIcons || missingIcons) ? `
${mitigIcons}${missingIcons}
` : ''} + ${mitigIcons ? `
${mitigIcons}
` : ''} `; }).join(''); @@ -457,13 +469,23 @@ ? `${diff > 0 ? '+' : '-'}${fmtDmg(Math.abs(diff))}` : ''; + const currMitigNames = new Set((curr?.mitigations ?? []).map(m => m.name)); + const refMitigIcons = (t.mitigations ?? []).filter(m => m.buffType === 'buff').map(m => { const iconSrc = MITIG_ICONS[m.name]; if (!iconSrc) return ''; - const dr = m.dr > 0 ? ` −${m.dr}%` : ''; - return `${m.name}`; + const dr = m.dr > 0 ? ` −${m.dr}%` : ''; + const missing = !currMitigNames.has(m.name); + const cls = missing ? ' aoe-buff-ref-unique' : ''; + const titleSufx = missing ? ' (fehlt im aktuellen Pull)' : ''; + return `${m.name}`; }).join(''); + const refShields = (t.mitigations ?? []).filter(m => m.buffType === 'shield'); + const refShieldTitle = refShields.length + ? refShields.map(s => currMitigNames.has(s.name) ? s.name : `${s.name} [fehlt im aktuellen Pull]`).join('\n') + : null; + return `
@@ -472,7 +494,7 @@ ${deltaHtml}
${t.name} - ${fmtDmg(t.amount)}${t.absorbed > 0 ? ` +${fmtDmg(t.absorbed)}` : ''} + ${fmtDmg(t.amount)}${t.absorbed > 0 ? ` +${fmtDmg(t.absorbed)}` : ''}
${refMitigIcons ? `
${refMitigIcons}
` : ''} `; @@ -545,6 +567,7 @@ if (json.error) { setEmpty('Fehler: ' + json.error); return; } lastFightId = fightId; + populateRefFightSelect(); setupPhases(window.App?.phases ?? []); renderPlayers(json.players ?? []); renderTimeline(json.aoe_events ?? [], json.fight_start ?? fightStart);