diff --git a/css/planner.css b/css/planner.css index b5a10df..8236c3f 100644 --- a/css/planner.css +++ b/css/planner.css @@ -290,6 +290,11 @@ color: var(--t3); margin-left: 6px; } +.mechanic-mitig-row { margin-top: -2px; display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; } +.mechanic-mitig-shield { font-size: 12px; color: var(--t3); } +.mechanic-mitig-val { font-weight: 500; } +.mechanic-mitig--ok { color: var(--green); } +.mechanic-mitig--risk { color: var(--red); } .mechanic-assignments { display: flex; @@ -573,6 +578,38 @@ .info-warning--job { color: var(--t2); } .info-warning--missing { color: var(--red); } +.info-section--extra { margin-top: 12px; } + +.info-extra-row { + display: flex; + align-items: center; + gap: 8px; +} + +.info-extra-label { + font-size: 12px; + color: var(--t2); + flex: 1; +} + +.info-extra-input-wrap { + display: flex; + align-items: center; + gap: 4px; +} + +.info-extra-input { + width: 52px; + font-size: 13px; + padding: 3px 6px; + text-align: right; +} + +.info-extra-unit { + font-size: 12px; + color: var(--t3); +} + /* ── Folder Sidebar ──────────────────────────────────────────────────────────── */ .folder-section { margin-bottom: 2px; } diff --git a/js/planner.js b/js/planner.js index f859ef3..004895c 100644 --- a/js/planner.js +++ b/js/planner.js @@ -435,6 +435,15 @@ function avgNonTankMaxHp(plan) { return Math.round(hps.reduce((s, v) => s + v, 0) / hps.length); } +function simulateDrMultiplier(mechanic) { + let mult = 1; + for (const a of mechanic.assignments ?? []) { + if (a.buffType === 'shield') continue; + mult *= (1 - (ABILITY_DR[a.ability] ?? 0)); + } + return mult; +} + function renderMechanicListHtml(plan) { const mechanics = visiblePlanMechanics(plan); if (mechanics.length === 0) { @@ -483,6 +492,14 @@ function renderMechanicListHtml(plan) { : badgeHtml; }).join(''); + const drOnly = m.unmitigatedDamage ? Math.round(m.unmitigatedDamage * simulateDrMultiplier(m)) : 0; + const shieldVal = (plan.shieldK ?? 0) * 1000; + const mitigFull = Math.max(0, drOnly - shieldVal); + const hasDrAssign = (m.assignments ?? []).some(a => a.buffType !== 'shield' && (ABILITY_DR[a.ability] ?? 0) > 0); + const hasShield = shieldVal > 0; + const drOnlyCls = avgHp ? (drOnly <= avgHp ? 'mechanic-mitig--ok' : 'mechanic-mitig--risk') : ''; + const fullCls = avgHp ? (mitigFull <= avgHp ? 'mechanic-mitig--ok' : 'mechanic-mitig--risk') : ''; + return `