fix(combat): show offense + defense damage by element in grid
The element breakdown grid previously only showed damage RECEIVED (defense) in the Mel/Msl and Magic columns, which was mostly empty for characters who evade/resist everything. Now shows both: - Given M/M + Given Mag: damage dealt by element (offense) - Recv M/M + Recv Mag: damage taken by element (defense) This makes the element breakdown immediately useful — you can see that you're dealing Slash damage via melee, for example. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c03b1c19f2
commit
ee30ad2636
1 changed files with 27 additions and 51 deletions
|
|
@ -4810,85 +4810,61 @@ function renderCombatStatsContent(win, charName) {
|
||||||
const avgNormal = normalHits > 0 ? Math.round(offAll.totalNormalDamage / normalHits) : 0;
|
const avgNormal = normalHits > 0 ? Math.round(offAll.totalNormalDamage / normalHits) : 0;
|
||||||
const avgCrit = crits > 0 ? Math.round(offAll.totalCritDamage / crits) : 0;
|
const avgCrit = crits > 0 ? Math.round(offAll.totalCritDamage / crits) : 0;
|
||||||
|
|
||||||
// Damage received by element
|
// Damage by element — offense (given) and defense (received)
|
||||||
const defDmgMM = {}, defDmgMag = {};
|
const offDmgMM = {}, offDmgMag = {}, defDmgMM = {}, defDmgMag = {};
|
||||||
let totalDefMM = 0, totalDefMag = 0;
|
let totalOffMM = 0, totalOffMag = 0, totalDefMM = 0, totalDefMag = 0;
|
||||||
DAMAGE_ELEMENTS.forEach(el => {
|
DAMAGE_ELEMENTS.forEach(el => {
|
||||||
|
offDmgMM[el] = getDefDmg(offense, 'MeleeMissile', el);
|
||||||
|
offDmgMag[el] = getDefDmg(offense, 'Magic', el);
|
||||||
defDmgMM[el] = getDefDmg(defense, 'MeleeMissile', el);
|
defDmgMM[el] = getDefDmg(defense, 'MeleeMissile', el);
|
||||||
defDmgMag[el] = getDefDmg(defense, 'Magic', el);
|
defDmgMag[el] = getDefDmg(defense, 'Magic', el);
|
||||||
|
totalOffMM += offDmgMM[el];
|
||||||
|
totalOffMag += offDmgMag[el];
|
||||||
totalDefMM += defDmgMM[el];
|
totalDefMM += defDmgMM[el];
|
||||||
totalDefMag += defDmgMag[el];
|
totalDefMag += defDmgMag[el];
|
||||||
});
|
});
|
||||||
|
|
||||||
const totalDmgGiven = offAll.totalNormalDamage + offAll.totalCritDamage;
|
const totalDmgGiven = offAll.totalNormalDamage + offAll.totalCritDamage;
|
||||||
|
|
||||||
// Build the grid HTML — matches Mag-Tools CombatTrackerGUIInfo layout
|
// Build the grid HTML
|
||||||
const fmtN = n => n === 0 ? '' : n.toLocaleString();
|
const fmtN = n => n === 0 ? '' : n.toLocaleString();
|
||||||
const rightCell = (text) => `<td style="text-align:right;padding:1px 4px;font-size:0.75rem;color:#ccc;">${text}</td>`;
|
const rightCell = (text) => `<td style="text-align:right;padding:1px 4px;font-size:0.75rem;color:#ccc;">${text}</td>`;
|
||||||
const labelCell = (text) => `<td style="padding:1px 4px;font-size:0.75rem;color:#aaa;">${text}</td>`;
|
const labelCell = (text) => `<td style="padding:1px 4px;font-size:0.75rem;color:#aaa;">${text}</td>`;
|
||||||
const headerCell = (text) => `<td style="text-align:right;padding:1px 4px;font-size:0.72rem;color:#888;font-weight:bold;">${text}</td>`;
|
const headerCell = (text) => `<td style="text-align:right;padding:1px 4px;font-size:0.72rem;color:#888;font-weight:bold;">${text}</td>`;
|
||||||
const statLabel = (text) => `<td style="padding:1px 4px;font-size:0.72rem;color:#888;font-weight:bold;">${text}</td>`;
|
const statLabel = (text) => `<td style="padding:1px 4px;font-size:0.72rem;color:#888;font-weight:bold;">${text}</td>`;
|
||||||
|
const sepCell = `<td style="width:4px;"></td>`;
|
||||||
|
|
||||||
let html = '<table style="width:100%;border-collapse:collapse;">';
|
let html = '<table style="width:100%;border-collapse:collapse;">';
|
||||||
// Header
|
|
||||||
html += `<tr><td></td>${headerCell('Mel/Msl')}${headerCell('Magic')}${statLabel('Attacks')}${rightCell(totalAttacks > 0 ? `${fmtN(totalAttacks)} (${hitRate}%)` : '')}</tr>`;
|
|
||||||
|
|
||||||
const statRows = [
|
// Column headers: Element | Dmg Given (M/M, Mag) | Dmg Recv (M/M, Mag) | Stats
|
||||||
['Typeless', 'Attacks', () => totalAttacks > 0 ? `${fmtN(totalAttacks)} (${hitRate}%)` : ''],
|
html += `<tr><td></td>${headerCell('Given M/M')}${headerCell('Given Mag')}${sepCell}${headerCell('Recv M/M')}${headerCell('Recv Mag')}${sepCell}${statLabel('Attacks')}${rightCell(totalAttacks > 0 ? `${fmtN(totalAttacks)} (${hitRate}%)` : '')}</tr>`;
|
||||||
['Slash', 'Evades', () => totalMeleeDefends > 0 ? `${fmtN(totalMeleeDefends)} (${evadeRate}%)` : ''],
|
|
||||||
['Pierce', 'Resists', () => totalMagicDefends > 0 ? `${fmtN(totalMagicDefends)} (${resistRate}%)` : ''],
|
// Stats to show on the right side of each element row
|
||||||
['Bludgeon', 'A.Surges', () => totalAethSurges > 0 ? `${fmtN(totalAethSurges)} (${aethRate}%)` : ''],
|
const rightStats = [
|
||||||
['Fire', 'C.Surges', () => totalCloakSurges > 0 ? `${fmtN(totalCloakSurges)} (${cloakRate}%)` : ''],
|
['Evades', () => totalMeleeDefends > 0 ? `${fmtN(totalMeleeDefends)} (${evadeRate}%)` : ''],
|
||||||
['Cold', '', () => ''],
|
['Resists', () => totalMagicDefends > 0 ? `${fmtN(totalMagicDefends)} (${resistRate}%)` : ''],
|
||||||
['Acid', 'Av/Mx', () => avgNormal > 0 ? `${fmtN(avgNormal)} / ${fmtN(offAll.maxNormalDamage)}` : ''],
|
['A.Surges', () => totalAethSurges > 0 ? `${fmtN(totalAethSurges)} (${aethRate}%)` : ''],
|
||||||
['Electric', 'Crits', () => crits > 0 ? `${fmtN(crits)} (${critRate}%)` : ''],
|
['C.Surges', () => totalCloakSurges > 0 ? `${fmtN(totalCloakSurges)} (${cloakRate}%)` : ''],
|
||||||
|
['', () => ''],
|
||||||
|
['', () => ''],
|
||||||
|
['Av/Mx', () => avgNormal > 0 ? `${fmtN(avgNormal)} / ${fmtN(offAll.maxNormalDamage)}` : ''],
|
||||||
|
['Crits', () => crits > 0 ? `${fmtN(crits)} (${critRate}%)` : ''],
|
||||||
];
|
];
|
||||||
|
|
||||||
// First row already printed above as header. Now element rows:
|
|
||||||
for (let i = 0; i < DAMAGE_ELEMENTS.length; i++) {
|
for (let i = 0; i < DAMAGE_ELEMENTS.length; i++) {
|
||||||
const el = DAMAGE_ELEMENTS[i];
|
const el = DAMAGE_ELEMENTS[i];
|
||||||
const sr = statRows[i];
|
const rs = rightStats[i] || ['', () => ''];
|
||||||
let statLabelText = sr ? sr[1] : '';
|
html += `<tr>${labelCell(el)}${rightCell(fmtN(offDmgMM[el]))}${rightCell(fmtN(offDmgMag[el]))}${sepCell}${rightCell(fmtN(defDmgMM[el]))}${rightCell(fmtN(defDmgMag[el]))}${sepCell}${rs[0] ? statLabel(rs[0]) : '<td></td>'}${rightCell(rs[1]())}</tr>`;
|
||||||
let statValue = sr ? sr[2]() : '';
|
|
||||||
|
|
||||||
// Skip the duplicate "Attacks" row — it's already in the header
|
|
||||||
if (i === 0) {
|
|
||||||
statLabelText = 'Evades';
|
|
||||||
statValue = totalMeleeDefends > 0 ? `${fmtN(totalMeleeDefends)} (${evadeRate}%)` : '';
|
|
||||||
} else if (i === 1) {
|
|
||||||
statLabelText = 'Resists';
|
|
||||||
statValue = totalMagicDefends > 0 ? `${fmtN(totalMagicDefends)} (${resistRate}%)` : '';
|
|
||||||
} else if (i === 2) {
|
|
||||||
statLabelText = 'A.Surges';
|
|
||||||
statValue = totalAethSurges > 0 ? `${fmtN(totalAethSurges)} (${aethRate}%)` : '';
|
|
||||||
} else if (i === 3) {
|
|
||||||
statLabelText = 'C.Surges';
|
|
||||||
statValue = totalCloakSurges > 0 ? `${fmtN(totalCloakSurges)} (${cloakRate}%)` : '';
|
|
||||||
} else if (i === 4) {
|
|
||||||
statLabelText = '';
|
|
||||||
statValue = '';
|
|
||||||
} else if (i === 5) {
|
|
||||||
statLabelText = '';
|
|
||||||
statValue = '';
|
|
||||||
} else if (i === 6) {
|
|
||||||
statLabelText = 'Av/Mx';
|
|
||||||
statValue = avgNormal > 0 ? `${fmtN(avgNormal)} / ${fmtN(offAll.maxNormalDamage)}` : '';
|
|
||||||
} else if (i === 7) {
|
|
||||||
statLabelText = 'Crits';
|
|
||||||
statValue = crits > 0 ? `${fmtN(crits)} (${critRate}%)` : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += `<tr>${labelCell(el)}${rightCell(fmtN(defDmgMM[el]))}${rightCell(fmtN(defDmgMag[el]))}${statLabelText ? statLabel(statLabelText) : '<td></td>'}${rightCell(statValue)}</tr>`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crit Avg/Max row
|
// Crit Avg/Max row
|
||||||
html += `<tr><td></td><td></td><td></td>${statLabel('Av/Mx')}${rightCell(avgCrit > 0 ? `${fmtN(avgCrit)} / ${fmtN(offAll.maxCritDamage)}` : '')}</tr>`;
|
html += `<tr><td></td><td></td><td></td>${sepCell}<td></td><td></td>${sepCell}${statLabel('Av/Mx')}${rightCell(avgCrit > 0 ? `${fmtN(avgCrit)} / ${fmtN(offAll.maxCritDamage)}` : '')}</tr>`;
|
||||||
|
|
||||||
// Blank row
|
// Blank row
|
||||||
html += '<tr><td colspan="5" style="height:6px;"></td></tr>';
|
html += `<tr><td colspan="9" style="height:6px;"></td></tr>`;
|
||||||
|
|
||||||
// Total row
|
// Total row
|
||||||
html += `<tr>${labelCell('Total')}${rightCell(fmtN(totalDefMM))}${rightCell(fmtN(totalDefMag))}${statLabel('Total')}${rightCell(fmtN(totalDmgGiven))}</tr>`;
|
html += `<tr>${labelCell('Total')}${rightCell(fmtN(totalOffMM))}${rightCell(fmtN(totalOffMag))}${sepCell}${rightCell(fmtN(totalDefMM))}${rightCell(fmtN(totalDefMag))}${sepCell}${statLabel('Total')}${rightCell(fmtN(totalDmgGiven))}</tr>`;
|
||||||
|
|
||||||
html += '</table>';
|
html += '</table>';
|
||||||
grid.innerHTML = html;
|
grid.innerHTML = html;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue